mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-07-07 14:12:40 +08:00
fix(shell): use c to copy for claude
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import type { MutableRefObject, RefObject } from 'react';
|
||||
import { ClipboardAddon, type IClipboardProvider } from '@xterm/addon-clipboard';
|
||||
import { FitAddon } from '@xterm/addon-fit';
|
||||
import { WebLinksAddon } from '@xterm/addon-web-links';
|
||||
import { WebglAddon } from '@xterm/addon-webgl';
|
||||
@@ -19,6 +20,43 @@ import {
|
||||
import { sendSocketMessage } from '../utils/socket';
|
||||
import { ensureXtermFocusStyles } from '../utils/terminalStyles';
|
||||
|
||||
// CLIs running inside the pty (e.g. `claude auth login`'s "press c to copy"
|
||||
// device-flow prompt) write to the clipboard via an OSC 52 escape sequence,
|
||||
// not a browser event — xterm.js ignores OSC 52 unless a clipboard addon is
|
||||
// loaded. Routes writes through the same fallback-aware helper the terminal's
|
||||
// own selection-copy shortcut uses, since `navigator.clipboard` is often
|
||||
// unavailable on self-hosted, non-HTTPS deployments.
|
||||
// `ClipboardSelectionType.SYSTEM` is `'c'` (vs. `'p'` for the X11 primary
|
||||
// selection) — compared as a literal since the addon ships it as a const
|
||||
// enum, which isolatedModules builds (esbuild/Vite) can't import as a value.
|
||||
const oscClipboardProvider: IClipboardProvider = {
|
||||
readText: async (selection) => {
|
||||
if (selection !== 'c') {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
return (await navigator.clipboard?.readText?.()) || '';
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
writeText: async (selection, text) => {
|
||||
if (selection !== 'c') {
|
||||
return;
|
||||
}
|
||||
await copyTextToClipboard(text);
|
||||
},
|
||||
};
|
||||
|
||||
// The addon's published typings declare a single `(provider?)` constructor
|
||||
// param, but the shipped runtime actually takes `(base64?, provider?)` — see
|
||||
// node_modules/@xterm/addon-clipboard/lib/addon-clipboard.js. Cast to call it
|
||||
// the way it's really implemented.
|
||||
const ClipboardAddonCtor = ClipboardAddon as unknown as new (
|
||||
base64?: unknown,
|
||||
provider?: IClipboardProvider,
|
||||
) => ClipboardAddon;
|
||||
|
||||
type UseShellTerminalOptions = {
|
||||
terminalContainerRef: RefObject<HTMLDivElement>;
|
||||
terminalRef: MutableRefObject<Terminal | null>;
|
||||
@@ -93,6 +131,8 @@ export function useShellTerminal({
|
||||
fitAddonRef.current = nextFitAddon;
|
||||
nextTerminal.loadAddon(nextFitAddon);
|
||||
|
||||
nextTerminal.loadAddon(new ClipboardAddonCtor(undefined, oscClipboardProvider));
|
||||
|
||||
// Avoid wrapped partial links in compact login flows.
|
||||
if (!minimal) {
|
||||
nextTerminal.loadAddon(new WebLinksAddon());
|
||||
|
||||
Reference in New Issue
Block a user