feat: add keyboard shortcuts for toggling bookmarks/sidebar, importing books, closing window (#2170)

And make the shortcuts compatible with GNOME Human Interface Guidelines.
This closes #2079 and closes #2168.
This commit is contained in:
Huang Xin
2025-10-04 22:12:31 +08:00
committed by GitHub
parent 4d577774f3
commit 562ccd4b9e
4 changed files with 57 additions and 10 deletions
+13
View File
@@ -38,6 +38,7 @@ import { useOpenWithBooks } from '@/hooks/useOpenWithBooks';
import { SelectedFile, useFileSelector } from '@/hooks/useFileSelector';
import { lockScreenOrientation } from '@/utils/bridge';
import {
tauriHandleClose,
tauriHandleSetAlwaysOnTop,
tauriHandleToggleFullScreen,
tauriQuitApp,
@@ -79,6 +80,7 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
const { safeAreaInsets: insets, isRoundedWindow } = useThemeStore();
const { settings, setSettings, saveSettings } = useSettingsStore();
const { isFontLayoutSettingsDialogOpen } = useSettingsStore();
const { setFontLayoutSettingsDialogOpen } = useSettingsStore();
const [loading, setLoading] = useState(false);
const isInitiating = useRef(false);
const [libraryLoaded, setLibraryLoaded] = useState(false);
@@ -116,11 +118,22 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
await tauriHandleToggleFullScreen();
}
},
onCloseWindow: async () => {
if (isTauriAppPlatform()) {
await tauriHandleClose();
}
},
onQuitApp: async () => {
if (isTauriAppPlatform()) {
await tauriQuitApp();
}
},
onOpenFontLayoutSettings: () => {
setFontLayoutSettingsDialogOpen(true);
},
onOpenBooks: () => {
handleImportBooks();
},
});
useEffect(() => {
@@ -11,6 +11,7 @@ import { BookNote } from '@/types/book';
import { uniqueId } from '@/utils/misc';
import Button from '@/components/Button';
import { getCurrentPage } from '@/utils/book';
import { eventDispatcher } from '@/utils/event';
interface BookmarkTogglerProps {
bookKey: string;
@@ -21,17 +22,21 @@ const BookmarkToggler: React.FC<BookmarkTogglerProps> = ({ bookKey }) => {
const { envConfig } = useEnv();
const { settings } = useSettingsStore();
const { getConfig, saveConfig, getBookData, updateBooknotes } = useBookDataStore();
const { getProgress, setBookmarkRibbonVisibility } = useReaderStore();
const config = getConfig(bookKey)!;
const progress = getProgress(bookKey)!;
const bookData = getBookData(bookKey)!;
const { getProgress, getViewState, setBookmarkRibbonVisibility } = useReaderStore();
const [isBookmarked, setIsBookmarked] = useState(false);
const config = getConfig(bookKey);
const progress = getProgress(bookKey);
const toggleBookmark = () => {
const bookData = getBookData(bookKey);
const config = getConfig(bookKey);
const progress = getProgress(bookKey);
if (!bookData || !config || !progress) return;
const { booknotes: bookmarks = [] } = config;
const { location: cfi, range } = progress;
if (!cfi) return;
const isBookmarked = getViewState(bookKey)?.ribbonVisible;
if (!isBookmarked) {
setIsBookmarked(true);
const text = range?.startContainer.textContent?.slice(0, 128) || '';
@@ -78,6 +83,19 @@ const BookmarkToggler: React.FC<BookmarkTogglerProps> = ({ bookKey }) => {
}
};
useEffect(() => {
const handleBookmarkToggle = (e: CustomEvent) => {
const { bookKey: eventBookKey } = e.detail;
if (eventBookKey !== bookKey) return;
toggleBookmark();
};
eventDispatcher.on('toggle-bookmark', handleBookmarkToggle);
return () => {
eventDispatcher.off('toggle-bookmark', handleBookmarkToggle);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [bookKey]);
useEffect(() => {
const { booknotes = [] } = config || {};
const { location: cfi } = progress || {};
@@ -5,7 +5,7 @@ import { useSidebarStore } from '@/store/sidebarStore';
import { useSettingsStore } from '@/store/settingsStore';
import { useBookDataStore } from '@/store/bookDataStore';
import { getStyles } from '@/utils/style';
import { tauriHandleToggleFullScreen, tauriQuitApp } from '@/utils/window';
import { tauriHandleClose, tauriHandleToggleFullScreen, tauriQuitApp } from '@/utils/window';
import { eventDispatcher } from '@/utils/event';
import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL, ZOOM_STEP } from '@/services/constants';
import { viewPagination } from './usePagination';
@@ -95,6 +95,12 @@ const useBookShortcuts = ({ sideBarBookKey, bookKeys }: UseBookShortcutsProps) =
}
};
const closeWindow = async () => {
if (isTauriAppPlatform()) {
await tauriHandleClose();
}
};
const quitApp = async () => {
// on web platform use browser's default shortcut to close the tab
if (isTauriAppPlatform()) {
@@ -145,17 +151,24 @@ const useBookShortcuts = ({ sideBarBookKey, bookKeys }: UseBookShortcutsProps) =
eventDispatcher.dispatch(viewState?.ttsEnabled ? 'tts-stop' : 'tts-speak', { bookKey });
};
const toggleBookmark = () => {
if (!sideBarBookKey) return;
eventDispatcher.dispatch('toggle-bookmark', { bookKey: sideBarBookKey });
};
useShortcuts(
{
onSwitchSideBar: switchSideBar,
onToggleSideBar: toggleSideBar,
onToggleNotebook: toggleNotebook,
onToggleScrollMode: toggleScrollMode,
onToggleBookmark: toggleBookmark,
onOpenFontLayoutSettings: () => setFontLayoutSettingsDialogOpen(true),
onToggleSearchBar: showSearchBar,
onToggleFullscreen: toggleFullscreen,
onToggleTTS: toggleTTS,
onReloadPage: reloadPage,
onCloseWindow: closeWindow,
onQuitApp: quitApp,
onGoLeft: goLeft,
onGoRight: goRight,
+7 -4
View File
@@ -1,14 +1,17 @@
const DEFAULT_SHORTCUTS = {
onSwitchSideBar: ['ctrl+Tab', 'opt+Tab', 'alt+Tab'],
onToggleSideBar: ['s'],
onToggleSideBar: ['s', 'F9'],
onToggleNotebook: ['n'],
onToggleSearchBar: ['ctrl+f', 'cmd+f'],
onToggleScrollMode: ['shift+j'],
onToggleSelectMode: ['shift+s'],
onToggleBookmark: ['ctrl+d', 'cmd+d'],
onToggleTTS: ['t'],
onOpenFontLayoutSettings: ['shift+f'],
onOpenFontLayoutSettings: ['shift+f', 'ctrl+,', 'cmd+,'],
onOpenBooks: ['ctrl+o', 'cmd+o'],
onReloadPage: ['shift+r'],
onToggleFullscreen: ['F11'],
onCloseWindow: ['ctrl+w', 'cmd+w'],
onQuitApp: ['ctrl+q', 'cmd+q'],
onGoLeft: ['ArrowLeft', 'PageUp', 'h'],
onGoRight: ['ArrowRight', 'PageDown', 'l', ' '],
@@ -16,8 +19,8 @@ const DEFAULT_SHORTCUTS = {
onGoPrev: ['ArrowUp', 'k'],
onGoHalfPageDown: ['shift+ArrowDown', 'd'],
onGoHalfPageUp: ['shift+ArrowUp', 'u'],
onGoBack: ['shift+ArrowLeft', 'shift+h'],
onGoForward: ['shift+ArrowRight', 'shift+l'],
onGoBack: ['shift+ArrowLeft', 'shift+h', 'alt+ArrowLeft'],
onGoForward: ['shift+ArrowRight', 'shift+l', 'alt+ArrowRight'],
onZoomIn: ['ctrl+=', 'cmd+=', 'shift+='],
onZoomOut: ['ctrl+-', 'cmd+-', 'shift+-'],
onResetZoom: ['ctrl+0', 'cmd+0'],