"use client"
import { useCallback, useEffect, useState } from "react"
import { Check, Copy, ExternalLink, Eye, EyeOff } from "lucide-react"
import { useTranslations } from "next-intl"
import {
startWebServer,
stopWebServer,
getWebServerStatus,
type WebServerInfo,
} from "@/lib/api"
import { openUrl } from "@/lib/platform"
function AddressCard({ label, value }: { label: string; value: string }) {
const t = useTranslations("WebServiceSettings")
return (
{label}
{value}
)
}
function TokenCard({ label, value }: { label: string; value: string }) {
const t = useTranslations("WebServiceSettings")
const [copied, setCopied] = useState(false)
const [revealed, setRevealed] = useState(false)
function handleCopy() {
navigator.clipboard.writeText(value)
setCopied(true)
setTimeout(() => setCopied(false), 1500)
}
const displayValue = revealed
? value
: "\u2022".repeat(Math.max(value.length, 12))
return (
{label}
{displayValue}
)
}
export function WebServiceSettings() {
const t = useTranslations("WebServiceSettings")
const [status, setStatus] = useState(null)
const [port, setPort] = useState("3080")
const [loading, setLoading] = useState(false)
const [error, setError] = useState("")
const fetchStatus = useCallback(async () => {
try {
const info = await getWebServerStatus()
setStatus(info)
if (info) {
setPort(String(info.port))
}
} catch {
// Server status unavailable
}
}, [])
useEffect(() => {
fetchStatus()
}, [fetchStatus])
async function handleStart() {
setError("")
setLoading(true)
try {
const info = await startWebServer({
port: parseInt(port, 10) || 3080,
})
setStatus(info)
} catch (e: unknown) {
const msg =
e && typeof e === "object" && "message" in e
? (e as { message: string }).message
: t("startFailed")
setError(msg)
} finally {
setLoading(false)
}
}
async function handleStop() {
setLoading(true)
try {
await stopWebServer()
setStatus(null)
} catch {
setError(t("stopFailed"))
} finally {
setLoading(false)
}
}
const isRunning = status !== null
return (
{t("sectionTitle")}
{t("sectionDescription")}
{/* Port config */}
setPort(e.target.value)}
disabled={isRunning}
min={1024}
max={65535}
className="flex h-9 w-32 rounded-md border border-input bg-background px-3 py-1 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50"
/>
{/* Start/Stop button */}
{isRunning ? t("running") : t("stopped")}
{error &&
{error}
}
{/* Connection info */}
{isRunning && (
{status.addresses.map((addr) => (
))}
{t("tokenHint")}
)}
)
}