MCPcopy Index your code
hub / github.com/codeaashu/claude-code / useCopyOnSelect

Function useCopyOnSelect

src/hooks/useCopyOnSelect.ts:26–83  ·  view source on GitHub ↗
(
  selection: Selection,
  isActive: boolean,
  onCopied?: (text: string) => void,
)

Source from the content-addressed store, hash-verified

24 * fullscreen REPL passes showCopiedToast for user feedback.
25 */
26export function useCopyOnSelect(
27 selection: Selection,
28 isActive: boolean,
29 onCopied?: (text: string) => void,
30): void {
31 // Tracks whether the *previous* notification had a visible selection with
32 // isDragging=false (i.e., we already auto-copied it). Without this, the
33 // finish→clear transition would look like a fresh selection-gone-idle
34 // event and we'd toast twice for a single drag.
35 const copiedRef = useRef(false)
36 // onCopied is a fresh closure each render; read through a ref so the
37 // effect doesn't re-subscribe (which would reset copiedRef via unmount).
38 const onCopiedRef = useRef(onCopied)
39 onCopiedRef.current = onCopied
40
41 useEffect(() => {
42 if (!isActive) return
43
44 const unsubscribe = selection.subscribe(() => {
45 const sel = selection.getState()
46 const has = selection.hasSelection()
47 // Drag in progress — wait for finish. Reset copied flag so a new drag
48 // that ends on the same range still triggers a fresh copy.
49 if (sel?.isDragging) {
50 copiedRef.current = false
51 return
52 }
53 // No selection (cleared, or click-without-drag) — reset.
54 if (!has) {
55 copiedRef.current = false
56 return
57 }
58 // Selection settled (drag finished OR multi-click). Already copied
59 // this one — the only way to get here again without going through
60 // isDragging or !has is a spurious notify (shouldn't happen, but safe).
61 if (copiedRef.current) return
62
63 // Default true: macOS users expect cmd+c to work. It can't — the
64 // terminal's Edit > Copy intercepts it before the pty sees it, and
65 // finds no native selection (mouse tracking disabled it). Auto-copy
66 // on mouse-up makes cmd+c a no-op that leaves the clipboard intact
67 // with the right content, so paste works as expected.
68 const enabled = getGlobalConfig().copyOnSelect ?? true
69 if (!enabled) return
70
71 const text = selection.copySelectionNoClear()
72 // Whitespace-only (e.g., blank-line multi-click) — not worth a
73 // clipboard write or toast. Still set copiedRef so we don't retry.
74 if (!text || !text.trim()) {
75 copiedRef.current = true
76 return
77 }
78 copiedRef.current = true
79 onCopiedRef.current?.(text)
80 })
81 return unsubscribe
82 }, [isActive, selection])
83}

Callers 1

ScrollKeybindingHandlerFunction · 0.85

Calls 3

getGlobalConfigFunction · 0.85
copySelectionNoClearMethod · 0.80
hasSelectionMethod · 0.45

Tested by

no test coverage detected