"use client"; import { useState, useCallback } from "react"; import { Check, Copy, MessageSquare, Terminal, Pencil, Eye, EyeOff, Bot, Loader2, } from "lucide-react"; import { useTranslations } from "next-intl"; import { useDeviceToken } from "@/hooks/use-device-token"; import { cn } from "@/lib/utils"; type Tab = "openclaw" | "terminal"; export function InstallBanner() { const t = useTranslations("installBanner"); const tGuide = useTranslations("skillGuide"); const { token, name, isLoading, error, updateName } = useDeviceToken(); const [activeTab, setActiveTab] = useState("terminal"); const [copied, setCopied] = useState(false); const [isEditingName, setIsEditingName] = useState(false); const [editNameValue, setEditNameValue] = useState(""); const [nameStatus, setNameStatus] = useState< "idle" | "saving" | "success" | "error" >("idle"); const [showToken, setShowToken] = useState(false); const maskedToken = token ? `${token.slice(0, 6)}...` : ""; const openclawPrompt = token ? t("openclawPrompt", { token }) : ""; const terminalCommand = token ? t("terminalCommand", { token }) : ""; const handleCopy = useCallback(async (text: string) => { try { await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { // fallback } }, []); const handleEditName = useCallback(() => { setEditNameValue(name || ""); setIsEditingName(true); setNameStatus("idle"); }, [name]); const handleSaveName = useCallback(async () => { if (!editNameValue.trim()) return; setNameStatus("saving"); const ok = await updateName(editNameValue.trim()); if (ok) { setNameStatus("success"); setIsEditingName(false); setTimeout(() => setNameStatus("idle"), 2000); } else { setNameStatus("error"); } }, [editNameValue, updateName]); const handleCancelEdit = useCallback(() => { setIsEditingName(false); setNameStatus("idle"); }, []); // Loading state if (isLoading) { return (
{t("generatingToken")}
); } // Error state if (error || !token) { return (
{t("tokenError")}
); } return (
{/* Compact header */}
🦞 {t("title")}
{/* Claw name row */}
{t("yourClaw")}: {isEditingName ? (
setEditNameValue(e.target.value)} className="w-20 rounded border border-[var(--accent-cyan)]/30 bg-[var(--bg-primary)] px-1.5 py-0.5 text-[11px] text-[var(--text-primary)] outline-none focus:border-[var(--accent-cyan)]" maxLength={30} autoFocus onKeyDown={(e) => { if (e.key === "Enter") handleSaveName(); if (e.key === "Escape") handleCancelEdit(); }} />
) : (
{name} {nameStatus === "success" && ( )}
)}
{/* Token mini display */}
{/* Compact tabs */}
{/* Tab content */} {activeTab === "openclaw" && (
)} {activeTab === "terminal" && (
$ {terminalCommand}
)} {/* AI-crawlable guide (collapsed) */}
{tGuide("summaryLabel")}

{tGuide("whatTitle")}

{tGuide("whatDescription")}

{tGuide("installTitle")}

  1. {tGuide("step1")}
  2. {tGuide("step2")}
  3. {tGuide("step3")}
  4. {tGuide("step4")}

{tGuide("commandTitle")}

bash <(curl -fsSL https://kymr.top/install.sh) --token YOUR_TOKEN

{tGuide("dataTitle")}

  • {tGuide("data1")}
  • {tGuide("data2")}
  • {tGuide("data3")}
  • {tGuide("data4")}

{tGuide("dataNever")}

{tGuide("permissionsTitle")}

  • {tGuide("perm1")}
  • {tGuide("perm2")}
  • {tGuide("perm3")}
); }