From e0dea8288d03e27518dfb03aafdec1f7ad7a1189 Mon Sep 17 00:00:00 2001 From: zhengkunwang223 <31820853+zhengkunwang223@users.noreply.github.com> Date: Wed, 23 Sep 2026 19:22:22 +0800 Subject: [PATCH] fix: Fixed bug with playground --- frontend/src/App.tsx | 35 ++++++++++++++++++++++++++++++++++- frontend/src/Playground.tsx | 4 +++- frontend/src/i18n.tsx | 3 +++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3b09d9e..77e4b98 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -22,6 +22,32 @@ function displayError(error: unknown, t: Translate) { return apiErrorMessage(error instanceof ApiError ? error.code : undefined, t) } +async function copyText(value: string): Promise { + if (navigator.clipboard?.writeText) { + try { + await navigator.clipboard.writeText(value) + return true + } catch { /* Fall back when clipboard access is denied. */ } + } + + const field = document.createElement("textarea") + field.value = value + field.readOnly = true + field.style.position = "fixed" + field.style.opacity = "0" + const focused = document.activeElement instanceof HTMLElement ? document.activeElement : null + document.body.appendChild(field) + field.select() + try { + return document.execCommand("copy") + } catch { + return false + } finally { + field.remove() + focused?.focus() + } +} + function loadAvailableModels(): Promise<{ models: Model[] }> { return api("/internal/models") } @@ -142,6 +168,7 @@ function Keys({ csrf }: { csrf: string }) { const [rawKey, setRawKey] = useState("") const [showCreate, setShowCreate] = useState(false) const [error, setError] = useState(null) + const [copyError, setCopyError] = useState(false) const [busy, setBusy] = useState(false) const reload = () => api("/internal/api-keys").then(setKeys).catch(setError) useEffect(() => { void reload() }, []) @@ -153,6 +180,7 @@ function Keys({ csrf }: { csrf: string }) { try { const created = await api<{ key: string }>("/internal/api-keys", { method: "POST", body: JSON.stringify({ name }) }, csrf) setRawKey(created.key) + setCopyError(false) setName("") setShowCreate(false) await reload() @@ -173,10 +201,15 @@ function Keys({ csrf }: { csrf: string }) { } } + async function copyKey() { + setCopyError(false) + if (!await copyText(rawKey)) setCopyError(true) + } + return <> setShowCreate(true)}> {t("createKey")}} /> {error ?
{displayError(error, t)}
: null} - {rawKey ?
{t("saveKeyTitle")}

{t("saveKeyDescription")}

{rawKey}
: null} + {rawKey ?
{t("saveKeyTitle")}

{t("saveKeyDescription")}

{copyError ?

{t("copyManually")}

: null}
{rawKey}
: null}

{t("keyList")}

{t("keyCount", { count: keys.length })}
{keys.length === 0 ?

{t("noKey")}

{t("noKeyDescription")}

:
{keys.map(key => diff --git a/frontend/src/Playground.tsx b/frontend/src/Playground.tsx index c98b74e..162bfaf 100644 --- a/frontend/src/Playground.tsx +++ b/frontend/src/Playground.tsx @@ -34,8 +34,10 @@ class DraftError extends Error { constructor(readonly key: MessageKey, readonly values?: Record) { super(key) } } +let nextQuestionUid = 0 + function makeQuestion(type: QuestionType = "noul"): Question { - return { uid: crypto.randomUUID(), id: "", type, instructions: "", choices: [{ label: "", description: "" }, { label: "", description: "" }], levels: ["", ""] } + return { uid: String(++nextQuestionUid), id: "", type, instructions: "", choices: [{ label: "", description: "" }, { label: "", description: "" }], levels: ["", ""] } } function parseDraft(value: string): Draft { diff --git a/frontend/src/i18n.tsx b/frontend/src/i18n.tsx index 7c8ae34..aee41c1 100644 --- a/frontend/src/i18n.tsx +++ b/frontend/src/i18n.tsx @@ -36,6 +36,7 @@ const zhCN = { saveKeyTitle: "请立即保存这把密钥", saveKeyDescription: "关闭后将无法再次查看完整密钥。", copy: "复制", + copyManually: "浏览器无法自动复制,请手动选中并复制上方密钥。", closeKeyNotice: "关闭密钥提示", keyList: "密钥的列表", keyCount: "{count} 把密钥", @@ -176,6 +177,7 @@ const en: Record = { saveKeyTitle: "Save this key now", saveKeyDescription: "You cannot view the full key again after closing this notice.", copy: "Copy", + copyManually: "Your browser could not copy the key. Select and copy it manually above.", closeKeyNotice: "Close key notice", keyList: "Keys", keyCount: "Total keys: {count}", @@ -314,6 +316,7 @@ const zhTW: Record = { saveKeyTitle: "請立即儲存這把金鑰", saveKeyDescription: "關閉提示後將無法再次查看完整金鑰。", copy: "複製", + copyManually: "瀏覽器無法自動複製,請手動選取並複製上方金鑰。", closeKeyNotice: "關閉金鑰提示", keyList: "金鑰列表", keyCount: "{count} 把金鑰",
{t("name")}{t("key")}{t("createdAt")}{t("lastUsed")}{t("status")}