Add arrow down/up keybinding for scrolling page

This commit is contained in:
chrox
2024-11-09 13:26:02 +01:00
parent 3aace9a228
commit d5835780a0
5 changed files with 60 additions and 74 deletions
@@ -12,6 +12,8 @@ export interface FoliateView extends HTMLElement {
init: (options: { lastLocation: string }) => void;
goTo: (href: string) => void;
goToFraction: (fraction: number) => void;
prev: (distance: number) => void;
next: (distance: number) => void;
goLeft: () => void;
goRight: () => void;
getCFI: (index: number, range: Range) => string;
@@ -57,7 +59,8 @@ const FoliateViewer: React.FC<{
};
const handleKeydown = (event: KeyboardEvent) => {
if (event.key === 'Backspace') {
// prevent default navigation keys in iframes
if (['Backspace', 'ArrowDown', 'ArrowUp'].includes(event.key)) {
event.preventDefault();
}
window.postMessage(
@@ -14,8 +14,12 @@ const useBookShortcuts = ({
openSplitView,
getNextBookKey,
}: UseBookShortcutsProps) => {
const { getView, setSideBarBookKey } = useReaderStore();
const { toggleSideBar } = useReaderStore();
const { getView, getConfig, toggleSideBar, setSideBarBookKey } = useReaderStore();
const config = getConfig(sideBarBookKey);
const viewSettings = config?.viewSettings;
const fontSize = viewSettings?.defaultFontSize ?? 16;
const lineHeight = viewSettings?.lineHeight ?? 1.6;
const distance = fontSize * lineHeight * 3;
const switchSideBar = () => {
if (sideBarBookKey) setSideBarBookKey(getNextBookKey(sideBarBookKey));
@@ -29,6 +33,14 @@ const useBookShortcuts = ({
getView(sideBarBookKey)?.goRight();
};
const goPrev = () => {
getView(sideBarBookKey)?.prev(distance);
};
const goNext = () => {
getView(sideBarBookKey)?.next(distance);
};
const reloadPage = () => {
window.location.reload();
};
@@ -41,6 +53,8 @@ const useBookShortcuts = ({
onReloadPage: reloadPage,
onGoLeft: goLeft,
onGoRight: goRight,
onGoPrev: goPrev,
onGoNext: goNext,
},
[sideBarBookKey, bookKeys],
);
+21 -14
View File
@@ -1,25 +1,32 @@
export interface ShortcutConfig {
switchSidebar: string[];
toggleSidebar: string[];
openSplitView: string[];
reloadPage: string[];
goLeft: string[];
goRight: string[];
onSwitchSideBar: string[];
onToggleSideBar: string[];
onOpenSplitView: string[];
onReloadPage: string[];
onGoLeft: string[];
onGoRight: string[];
onGoNext: string[];
onGoPrev: string[];
}
const DEFAULT_SHORTCUTS: ShortcutConfig = {
switchSidebar: ['ctrl+Tab', 'opt+Tab', 'alt+Tab'],
toggleSidebar: ['t'],
openSplitView: ['shift+p'],
reloadPage: ['shift+r'],
goLeft: ['ArrowLeft', 'PageUp', 'h'],
goRight: ['ArrowRight', 'PageDown', 'l'],
onSwitchSideBar: ['ctrl+Tab', 'opt+Tab', 'alt+Tab'],
onToggleSideBar: ['t'],
onOpenSplitView: ['shift+p'],
onReloadPage: ['shift+r'],
onGoLeft: ['ArrowLeft', 'PageUp', 'h'],
onGoRight: ['ArrowRight', 'PageDown', 'l'],
onGoNext: ['ArrowDown', 'j'],
onGoPrev: ['ArrowUp', 'k'],
};
// Load shortcuts from localStorage or fallback to defaults
export const loadShortcuts = (): ShortcutConfig => {
const storedShortcuts = localStorage.getItem('customShortcuts');
return storedShortcuts ? JSON.parse(storedShortcuts) : DEFAULT_SHORTCUTS;
const customShortcuts = JSON.parse(localStorage.getItem('customShortcuts') || '{}');
return {
...DEFAULT_SHORTCUTS,
...customShortcuts,
};
};
// Save custom shortcuts to localStorage
+16 -55
View File
@@ -1,14 +1,9 @@
import { useEffect, useState } from 'react';
import { loadShortcuts, ShortcutConfig } from '../helpers/shortcuts';
interface KeyActionHandlers {
onSwitchSideBar?: () => void;
onToggleSideBar?: () => void;
onOpenSplitView?: () => void;
onReloadPage?: () => void;
onGoLeft?: () => void;
onGoRight?: () => void;
}
export type KeyActionHandlers = {
[K in keyof ShortcutConfig]?: () => void;
};
const useShortcuts = (actions: KeyActionHandlers, dependencies: React.DependencyList = []) => {
const [shortcuts, setShortcuts] = useState<ShortcutConfig>(loadShortcuts);
@@ -60,53 +55,19 @@ const useShortcuts = (actions: KeyActionHandlers, dependencies: React.Dependency
) => {
// FIXME: This is a temporary fix to disable Back button navigation
if (key === 'backspace') return true;
if (
shortcuts.switchSidebar.some((shortcut) =>
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
)
) {
actions.onSwitchSideBar?.();
return true;
}
if (
shortcuts.toggleSidebar.some((shortcut) =>
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
)
) {
actions.onToggleSideBar?.();
return true;
}
if (
shortcuts.openSplitView.some((shortcut) =>
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
)
) {
actions.onOpenSplitView?.();
return true;
}
if (
shortcuts.reloadPage.some((shortcut) =>
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
)
) {
actions.onReloadPage?.();
return true;
}
if (
shortcuts.goLeft.some((shortcut) =>
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
)
) {
actions.onGoLeft?.();
return true;
}
if (
shortcuts.goRight.some((shortcut) =>
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
)
) {
actions.onGoRight?.();
return true;
for (const [actionName, actionHandler] of Object.entries(actions)) {
const shortcutKey = actionName as keyof ShortcutConfig;
const handler = actionHandler as (() => void) | undefined;
const shortcutList = shortcuts[shortcutKey as keyof ShortcutConfig];
if (
handler &&
shortcutList?.some((shortcut) =>
isShortcutMatch(shortcut, key, ctrlKey, altKey, metaKey, shiftKey),
)
) {
handler();
return true;
}
}
return false;
};
+3 -2
View File
@@ -67,7 +67,7 @@ interface ReaderStore {
) => void;
getProgress: (key: string) => BookProgress | null;
setConfig: (key: string, config: BookConfig) => void;
getConfig: (key: string) => BookConfig | null;
getConfig: (key: string | null) => BookConfig | null;
setView: (key: string, view: FoliateView) => void;
getView: (key: string | null) => FoliateView | null;
getViewsById: (id: string) => FoliateView[];
@@ -135,7 +135,8 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
});
},
getConfig: (key: string) => {
getConfig: (key: string | null) => {
if (!key) return null;
const id = key.split('-')[0]!;
return get().booksData[id]?.config || null;
},