diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-08-16 19:07:08 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-08-16 19:07:08 +0900 |
| commit | 239c206659d02f5e89b3f54aa050aff6a71dcdd5 (patch) | |
| tree | f436807878bfa868e56581e562769c733a45eeb2 /src | |
| parent | 28b2684da9cf8e48cff811b9f5b35997815cb530 (diff) | |
fix(ui): コピー失敗時のエラーハンドリングを追加
Clipboard API が利用できない非セキュアコンテキストや、ブラウザの権限拒否で writeText が失敗した場合に、未処理例外となってコピーボタンが無反応に見える問題を修正。
navigator.clipboard.writeText の存在を事前に確認し、非同期処理を try/catch で囲むことで同期例外と Promise の拒否をまとめて処理する。成功時はチェックマーク、失敗時は警告マークを一時表示し、詳細はコンソールへ記録する。アラートは表示しない。
Diffstat (limited to 'src')
| -rw-r--r-- | src/ollama_web/static/app.js | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/src/ollama_web/static/app.js b/src/ollama_web/static/app.js index 54fb2e0..65aa17b 100644 --- a/src/ollama_web/static/app.js +++ b/src/ollama_web/static/app.js @@ -189,14 +189,24 @@ function addMessage(role, rawText, showCopy = false) { copyBtn.setAttribute("aria-label", t("common.copy", "Copy")); copyBtn.textContent = "📋"; copyBtn.hidden = !showCopy; - copyBtn.addEventListener("click", () => { + copyBtn.addEventListener("click", async () => { const raw = div.dataset.rawText || ""; - navigator.clipboard.writeText(raw).then(() => { - copyBtn.textContent = "✓"; - setTimeout(() => { - copyBtn.textContent = "📋"; - }, 1200); - }); + let feedback = "✓"; + + try { + if (!navigator.clipboard?.writeText) { + throw new Error("Clipboard API is unavailable"); + } + await navigator.clipboard.writeText(raw); + } catch (err) { + console.error("failed to copy message", err); + feedback = "⚠"; + } + + copyBtn.textContent = feedback; + setTimeout(() => { + copyBtn.textContent = "📋"; + }, 1200); }); div.appendChild(copyBtn); chatEl.appendChild(div); @@ -959,4 +969,4 @@ function updateTokenGaugeFromSession() { } loadSessions(); -loadModelCapabilities();
\ No newline at end of file +loadModelCapabilities(); |
