Add a "Highlight Current Sentence" keyboard action (default Shift+M, in the Text to Speech shortcut section) that persists the sentence TTS is reading aloud as a normal highlight using the user's default style/color — no text selection, eyes-off, silent, and idempotent (a repeat press on the same sentence is a no-op rather than a duplicate). Flow: the shortcut handler in useBookShortcuts dispatches tts-highlight-sentence → useTTSControl (which owns the TTSController) resolves the current sentence via the new TTSController.getSpokenSentence() and relays create-tts-highlight → Annotator builds the BookNote with the pure, unit-tested buildTTSSentenceHighlight helper and persists/renders it like any other highlight. Closes #4085 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,7 +47,11 @@ import { getWordCount } from '@/utils/word';
|
||||
import { getIndexFromCfi, isCfiInLocation } from '@/utils/cfi';
|
||||
import { TransformContext } from '@/services/transformers/types';
|
||||
import { transformContent } from '@/services/transformService';
|
||||
import { getHighlightColorHex, removeBookNoteOverlays } from '../../utils/annotatorUtil';
|
||||
import {
|
||||
buildTTSSentenceHighlight,
|
||||
getHighlightColorHex,
|
||||
removeBookNoteOverlays,
|
||||
} from '../../utils/annotatorUtil';
|
||||
import {
|
||||
expandAllRenderedSections,
|
||||
expandGlobalAnnotation,
|
||||
@@ -536,10 +540,12 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
eventDispatcher.on('export-annotations', handleExportMarkdown);
|
||||
eventDispatcher.on('clear-annotations', handleClearAnnotations);
|
||||
eventDispatcher.on('import-annotations', handleImportAnnotations);
|
||||
eventDispatcher.on('create-tts-highlight', handleCreateTTSHighlight);
|
||||
return () => {
|
||||
eventDispatcher.off('export-annotations', handleExportMarkdown);
|
||||
eventDispatcher.off('clear-annotations', handleClearAnnotations);
|
||||
eventDispatcher.off('import-annotations', handleImportAnnotations);
|
||||
eventDispatcher.off('create-tts-highlight', handleCreateTTSHighlight);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
@@ -839,6 +845,29 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreateTTSHighlight = (event: CustomEvent) => {
|
||||
const detail = event.detail as { bookKey: string; cfi: string; text: string } | undefined;
|
||||
if (!detail || detail.bookKey !== bookKey) return;
|
||||
const { settings } = useSettingsStore.getState();
|
||||
const style = settings.globalReadSettings.highlightStyle;
|
||||
const color = settings.globalReadSettings.highlightStyles[style];
|
||||
const { booknotes: annotations = [] } = getConfig(bookKey)!;
|
||||
const page = getProgress(bookKey)?.page;
|
||||
const annotation = buildTTSSentenceHighlight(
|
||||
annotations,
|
||||
{ cfi: detail.cfi, text: detail.text, style, color, page },
|
||||
Date.now(),
|
||||
);
|
||||
if (!annotation) return;
|
||||
annotations.push(annotation);
|
||||
const updatedConfig = updateBooknotes(bookKey, annotations);
|
||||
if (updatedConfig) {
|
||||
saveConfig(envConfig, bookKey, updatedConfig, settings);
|
||||
}
|
||||
const views = getViewsById(bookKey.split('-')[0]!);
|
||||
views.forEach((view) => view?.addAnnotation(annotation));
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle the `global` flag on the annotation currently anchored at
|
||||
* `selection.cfi`. When enabling, fan out overlays for every other
|
||||
|
||||
Reference in New Issue
Block a user