feat(shortcut): add ctrl + mouse wheel to zoom in/out, closes #2011 (#2533)

This commit is contained in:
Huang Xin
2025-11-25 00:19:28 +08:00
committed by GitHub
parent fa66e6fca6
commit a54daaaa90
5 changed files with 113 additions and 6 deletions
@@ -1,3 +1,4 @@
import { useEffect } from 'react';
import { useReaderStore } from '@/store/readerStore';
import { useNotebookStore } from '@/store/notebookStore';
import { isTauriAppPlatform } from '@/services/environment';
@@ -171,20 +172,38 @@ const useBookShortcuts = ({ sideBarBookKey, bookKeys }: UseBookShortcutsProps) =
}
};
const zoomIn = () => {
const zoomInFactor = (factor = 1.0) => {
if (!sideBarBookKey) return;
const viewSettings = getViewSettings(sideBarBookKey)!;
const zoomLevel = viewSettings!.zoomLevel + ZOOM_STEP;
const zoomLevel = viewSettings!.zoomLevel + ZOOM_STEP * factor;
applyZoomLevel(Math.min(zoomLevel, MAX_ZOOM_LEVEL));
};
const zoomOut = () => {
const zoomOutFactor = (factor = 1.0) => {
if (!sideBarBookKey) return;
const viewSettings = getViewSettings(sideBarBookKey)!;
const zoomLevel = viewSettings!.zoomLevel - ZOOM_STEP;
const zoomLevel = viewSettings!.zoomLevel - ZOOM_STEP * factor;
applyZoomLevel(Math.max(zoomLevel, MIN_ZOOM_LEVEL));
};
const zoomIn = () => {
zoomInFactor();
};
const zoomOut = () => {
zoomOutFactor();
};
const handleZoomIn = (event: CustomEvent) => {
const factor = event.detail?.factor || 1.0;
zoomInFactor(factor);
};
const handleZoomOut = (event: CustomEvent) => {
const factor = event.detail?.factor || 1.0;
zoomOutFactor(factor);
};
const resetZoom = () => {
if (!sideBarBookKey) return;
applyZoomLevel(100);
@@ -202,6 +221,18 @@ const useBookShortcuts = ({ sideBarBookKey, bookKeys }: UseBookShortcutsProps) =
eventDispatcher.dispatch('toggle-bookmark', { bookKey: sideBarBookKey });
};
useEffect(() => {
eventDispatcher.on('zoom-in', handleZoomIn);
eventDispatcher.on('zoom-out', handleZoomOut);
eventDispatcher.on('reset-zoom', resetZoom);
return () => {
eventDispatcher.off('zoom-in', handleZoomIn);
eventDispatcher.off('zoom-out', handleZoomOut);
eventDispatcher.off('reset-zoom', resetZoom);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sideBarBookKey]);
useShortcuts(
{
onSwitchSideBar: switchSideBar,
@@ -3,6 +3,7 @@ import { useReaderStore } from '@/store/readerStore';
import { useBookDataStore } from '@/store/bookDataStore';
import { debounce } from '@/utils/debounce';
import { ScrollSource } from './usePagination';
import { eventDispatcher } from '@/utils/event';
export const useMouseEvent = (
bookKey: string,
@@ -19,7 +20,15 @@ export const useMouseEvent = (
debounceScroll('mouse', -msg.data.deltaY, 0);
}
if (msg.data.type === 'iframe-wheel') {
debounceFlip(msg);
if (msg.data.ctrlKey) {
if (msg.data.deltaY > 0) {
eventDispatcher.dispatch('zoom-out', { factor: Math.abs(msg.data.deltaY) / 100 });
} else if (msg.data.deltaY < 0) {
eventDispatcher.dispatch('zoom-in', { factor: Math.abs(msg.data.deltaY) / 100 });
}
} else {
debounceFlip(msg);
}
} else {
handlePageFlip(msg);
}