Skip to content

Let a chat answer and each code block in it be copied, also where the page has no Clipboard API - #954

Merged
WaylandYang merged 2 commits into
deeplethe:devfrom
Maya-Kid:fix/chat-copy-actions
Sep 26, 2026
Merged

WaylandYang merged 2 commits into
deeplethe:devfrom
Maya-Kid:fix/chat-copy-actions

Conversation

@Maya-Kid

Copy link
Copy Markdown
Contributor

Does item (3) of #936. #936 stays open for (2), retry.

Problem

  • A chat answer cannot be checked, retried or copied #936 (3). An answer has no copy action, and neither does a code block inside it, although SQL and tables are what people most often copy.

  • The existing copy actions call navigator.clipboard directly:

    • the MCP snippet on the tokens page;
    • the error and ingest details in Library;
    • "Copy title" in the conversation menu.

    The Clipboard API exists only in a secure context, meaning https or localhost. A base opened over plain http on a local network has no navigator.clipboard. There these actions do nothing, and say nothing.

Change

  • clipboard.ts: copyText(text) returns whether it copied.
    • It writes through navigator.clipboard when the page has it.
    • Where the API does not exist or refuses, it selects a hidden, read-only text area and calls execCommand("copy"). Then it removes the area and returns focus to the element that had it.
  • chatCopy.tsx:
    • CopyButton is the shell's IconButton with the Copy / Check icons. After a copy it shows the check and reads "Copied" for 1.5 s. A failed copy says so in a toast.
    • CodeBlock wraps <pre> and puts a CopyButton at its top right. It copies the code itself: the text of the <pre>, without the fence's final newline.
  • chatCitations.tsx: chatMarkdown renders pre through CodeBlock. It is still a module-level constant, so Segment's memoization holds.
  • Chat.tsx: a finished answer gains a row of actions under its sources, for now just "Copy answer".
  • styles.css:
    • The wrapper takes the code block's vertical margin, so the prose's first-child and last-child rules still reach it.
    • The <pre> gets right padding, so the button does not cover short lines.
  • Wording: four entries in S.ask, in en.ts and zh.ts.

Verification

Run in containers on a Linux host: Node 20 with pnpm 10.2.1, and Playwright 1.58.2 with Chromium.

New tests

  • clipboard.test.ts (vitest) covers four cases:

    • the Clipboard API is used when it is there;
    • where it does not exist, a selected, read-only text area holds the text when execCommand("copy") runs, it is removed afterwards, and focus goes back;
    • a refused writeText falls back the same way;
    • false when neither works, whether execCommand returns false or throws.
  • chat-view.test.mjs (browser) replays a stored answer with a SQL code block twice:

    • once with navigator.clipboard replaced by a recorder;
    • once with it removed and execCommand recording the selected text.

    Each time, "Copy code" copies exactly the SQL and the button then reads "Copied", "Copy answer" copies the whole Markdown, and the page logs no error.

On dev (f2e0d5b) with only the browser test added

The new case fails waiting for a "Copy code" button, which dev does not have: 22 tests, 20 pass, 2 fail (the case and its parent). The vitest file imports the new module, so it was left out.

With this change

  • pnpm install --frozen-lockfile passes.
  • pnpm test: 146 passed.
  • pnpm build passes, including style-guard and tsc.
  • The browser test: 22 of 22 pass.

Limits

  • The copy actions that already existed still call navigator.clipboard directly. They can move to copyText in a follow-up.
  • A copied answer keeps its [n] marks. The sources listed under it are not copied.
  • execCommand("copy") is deprecated. It is reached only where the Clipboard API is missing or refuses, and browsers still support it.

… page has no Clipboard API

Signed-off-by: dada-yan <BinjunYann@gmail.com>

@WaylandYang WaylandYang left a comment

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.

Item (3) of #936: the shell's IconButton on the answer and on each code block, copying the stored Markdown and the pre's text, and a fallback where the Clipboard API is missing over plain http, which is how most self-hosted bases are opened. The follow-up for the existing copy actions is noted. Merging.

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.

2 participants