diff --git a/web/frontend/src/components/transcript/TranscriptView.tsx b/web/frontend/src/components/transcript/TranscriptView.tsx index 90a46da7..0821e378 100644 --- a/web/frontend/src/components/transcript/TranscriptView.tsx +++ b/web/frontend/src/components/transcript/TranscriptView.tsx @@ -273,6 +273,7 @@ export const TranscriptView = forwardRef(({ // Ensure text is the selection target, not the container WebkitTouchCallout: 'default' }} + data-transcript-text > {/* The hook returns the built text string, so we just render it directly */} {fullText} @@ -331,6 +332,7 @@ export const TranscriptView = forwardRef(({ touchAction: 'pan-y pinch-zoom', WebkitTouchCallout: 'default' }} + data-transcript-text > {segment.fullText || segment.text} diff --git a/web/frontend/src/features/transcription/hooks/useSelectionMenu.ts b/web/frontend/src/features/transcription/hooks/useSelectionMenu.ts index 6934decd..4bac67aa 100644 --- a/web/frontend/src/features/transcription/hooks/useSelectionMenu.ts +++ b/web/frontend/src/features/transcription/hooks/useSelectionMenu.ts @@ -86,10 +86,17 @@ export function useSelectionMenu( } // Calculate absolute character index using TreeWalker + // Only count text nodes inside elements marked with data-transcript-text + // This prevents timestamps and speaker names from throwing off the character index const walker = document.createTreeWalker( containerRef.current, NodeFilter.SHOW_TEXT, - null + { + acceptNode: (node) => { + const parent = node.parentElement?.closest('[data-transcript-text]'); + return parent ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP; + } + } ); let charIndex = 0;