fix(reader): add Alt+P proofread shortcut and let Shift+P exit paragraph mode (#4717) (#4723)

On Windows/Linux, Ctrl+P opens the proofread/replace rules but also
triggers the browser print dialog, since the selection shortcut handlers
return undefined and never preventDefault. Add a print-free `alt+p`
binding for Proofread Selection alongside ctrl+p/cmd+p.

Also fix Shift+P being unable to exit paragraph mode: the paragraph
overlay attaches a capture-phase keydown listener that calls
stopImmediatePropagation() on every key while visible, so the global
toggle shortcut never reached useShortcuts. Honor the configured
"Toggle Paragraph Mode" shortcut directly in the overlay so the same
shortcut that enters paragraph mode also exits it.

Extract the shared shortcut event-matching into matchesShortcut() in
utils/shortcutKeys.ts and reuse it from useShortcuts instead of its
private duplicate.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-06-22 10:57:04 +08:00
committed by GitHub
parent b87c735c1e
commit a6d28ffcdf
7 changed files with 134 additions and 48 deletions
@@ -64,6 +64,38 @@ export const formatKeyForDisplay = (key: string, isMac: boolean): string => {
return [...modifiers, displayKey].join('+');
};
export type ShortcutEventLike = Pick<
KeyboardEvent,
'key' | 'ctrlKey' | 'altKey' | 'metaKey' | 'shiftKey'
>;
const parseShortcut = (shortcut: string) => {
const keys = shortcut.toLowerCase().split('+');
return {
ctrlKey: keys.includes('ctrl'),
altKey: keys.includes('alt') || keys.includes('opt'),
metaKey: keys.includes('meta') || keys.includes('cmd'),
shiftKey: keys.includes('shift'),
key: keys.find((k) => !MODIFIERS.has(k)),
};
};
// Whether a keyboard event matches any of the given shortcut strings. `alt`/`opt`
// and `cmd`/`meta` are treated as equivalent, matching how shortcuts are authored.
export const matchesShortcut = (event: ShortcutEventLike, keys: string[]): boolean => {
const key = event.key.toLowerCase();
return keys.some((shortcut) => {
const parsed = parseShortcut(shortcut);
return (
parsed.key === key &&
parsed.ctrlKey === event.ctrlKey &&
parsed.altKey === event.altKey &&
parsed.metaKey === event.metaKey &&
parsed.shiftKey === event.shiftKey
);
});
};
const MAC_MODIFIERS = new Set(['cmd', 'opt']);
const OTHER_MODIFIERS = new Set(['ctrl', 'alt']);