Skip to content

fix(ui): make copy work in non-secure contexts (plain HTTP / Tailscale) - #1768

Open
MingxiYe wants to merge 1 commit into
tingly-dev:mainfrom
MingxiYe:fix/clipboard-insecure-context-1746
Open

MingxiYe wants to merge 1 commit into
tingly-dev:mainfrom
MingxiYe:fix/clipboard-insecure-context-1746

Conversation

@MingxiYe

@MingxiYe MingxiYe commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Copy buttons in the Web UI fail when the page is served over plain HTTP to a non-localhost host (a LAN IP, or a Tailscale 100.x address). navigator.clipboard is only defined in a secure context (HTTPS, or http://localhost / 127.0.0.1), so every copy path throws:

  • hooks/useFunctionPanelData.ts catches it and shows "Failed to copy to clipboard"
  • hooks/useCopyFeedback.ts had no .catch and silently no-ops
  • the ~15 direct navigator.clipboard.writeText call sites throw

Fix

  • Add frontend/src/utils/clipboard.ts copyText(): uses navigator.clipboard.writeText in a secure context, otherwise falls back to the legacy document.execCommand('copy') via an off-screen <textarea>; rejects if neither path can copy.
  • Route the copy hooks (useCopyFeedback, useFunctionPanelData) and all direct navigator.clipboard.writeText call sites through it.
  • Promotes the correct fallback that already existed locally in components/rule-card/utils.ts into the shared helper (removes the duplicate).

Test plan

  • pnpm typecheck: no new errors (40 before this change, 40 after — the repo's pre-existing legacy errors are unchanged).
  • pnpm lint: no new findings (only the repo's pre-existing React-pattern warnings remain).
  • Secure-context behavior (localhost / HTTPS) is unchanged — it still uses navigator.clipboard.
  • The non-secure fallback path (plain HTTP to a non-localhost host, e.g. over Tailscale) runs execCommand('copy'). That branch cannot be exercised from a headless localhost/HTTPS context (where navigator.clipboard is present), so it is verified by review here rather than an automated run.

Fixes #1746

🤖 Generated with Claude Code

`navigator.clipboard` is only available in a secure context (HTTPS, or
http://localhost / 127.0.0.1). When the Web UI is served over plain HTTP
to a non-localhost host (a LAN IP, or a Tailscale 100.x address), it is
undefined, so every copy button fails — useFunctionPanelData surfaces
"Failed to copy to clipboard", useCopyFeedback silently no-ops, and the
direct navigator.clipboard.writeText call sites throw.

Add utils/clipboard.ts `copyText()` that falls back to the legacy
execCommand('copy') via an off-screen textarea when navigator.clipboard
is unavailable, and route the copy hooks (useCopyFeedback,
useFunctionPanelData) and all direct writeText call sites through it.
This promotes the correct fallback that already existed locally in
components/rule-card/utils.ts into a single shared helper.

Fixes tingly-dev#1746

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012AKfM1AfoSMcxhZE4Pe6F2
@@ -0,0 +1,34 @@
/**

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hwo about to update navigator.clipboard directly ? if we can not, we may create anothe rnew clipboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Copy buttons fail ("Failed to copy to clipboard") when the Web UI is served over plain HTTP from a non-localhost host (Tailscale/LAN)

2 participants