Files
Moku/src/features/reader/lib/readerKeybinds.ts
T
2026-05-15 20:36:15 -05:00

61 lines
3.1 KiB
TypeScript

import { matchesKeybind, toggleFullscreen, DEFAULT_KEYBINDS } from "@core/keybinds";
import type { Keybinds } from "@core/keybinds";
export interface ReaderKeyActions {
goNext: () => void;
goPrev: () => void;
closeReader: () => void;
goToPage: (page: number) => void;
lastPage: () => number;
adjustZoom: (delta: number) => void;
resetZoom: () => void;
cycleStyle: () => void;
toggleDirection: () => void;
openSettings: () => void;
toggleBookmark: () => void;
toggleMarker: () => void;
toggleAutoScroll: () => void;
chapterNext: () => void;
chapterPrev: () => void;
closePopovers: () => boolean;
getKeybinds: () => Keybinds;
}
const ZOOM_STEP = 0.10;
export function createReaderKeyHandler(actions: ReaderKeyActions): (e: KeyboardEvent) => void {
return function onKey(e: KeyboardEvent) {
const target = e.target as HTMLElement;
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") return;
if (e.key === "Escape") {
e.preventDefault();
if (actions.closePopovers()) return;
actions.closeReader();
return;
}
if (e.ctrlKey) {
if (e.key === "=" || e.key === "+") { e.preventDefault(); actions.adjustZoom(ZOOM_STEP); return; }
if (e.key === "-") { e.preventDefault(); actions.adjustZoom(-ZOOM_STEP); return; }
if (e.key === "0") { e.preventDefault(); actions.resetZoom(); return; }
}
const kb = actions.getKeybinds();
if (matchesKeybind(e, kb.exitReader)) { e.preventDefault(); actions.closeReader(); }
else if (matchesKeybind(e, kb.turnPageRight)) { e.preventDefault(); actions.goNext(); }
else if (matchesKeybind(e, kb.turnPageLeft)) { e.preventDefault(); actions.goPrev(); }
else if (matchesKeybind(e, kb.firstPage)) { e.preventDefault(); actions.goToPage(1); }
else if (matchesKeybind(e, kb.lastPage)) { e.preventDefault(); actions.goToPage(actions.lastPage()); }
else if (matchesKeybind(e, kb.turnChapterRight)) { e.preventDefault(); actions.chapterNext(); }
else if (matchesKeybind(e, kb.turnChapterLeft)) { e.preventDefault(); actions.chapterPrev(); }
else if (matchesKeybind(e, kb.togglePageStyle)) { e.preventDefault(); actions.cycleStyle(); }
else if (matchesKeybind(e, kb.toggleReadingDirection)) { e.preventDefault(); actions.toggleDirection(); }
else if (matchesKeybind(e, kb.toggleFullscreen)) { e.preventDefault(); toggleFullscreen().catch(console.error); }
else if (matchesKeybind(e, kb.openSettings)) { e.preventDefault(); actions.openSettings(); }
else if (matchesKeybind(e, kb.toggleBookmark)) { e.preventDefault(); actions.toggleBookmark(); }
else if (matchesKeybind(e, kb.toggleMarker)) { e.preventDefault(); actions.toggleMarker(); }
else if (matchesKeybind(e, kb.toggleAutoScroll)) { e.preventDefault(); actions.toggleAutoScroll(); }
};
}