compat(footnote): support footnote text in alt attribute of the image, closes #3576 (#3587)

refactor: remove unused continuous scroll
This commit is contained in:
Huang Xin
2026-03-22 19:17:02 +08:00
committed by GitHub
parent 2905506017
commit 87f0240b0a
8 changed files with 6 additions and 84 deletions
@@ -329,9 +329,9 @@ const FoliateViewer: React.FC<{
}
};
const { handlePageFlip, handleContinuousScroll } = usePagination(bookKey, viewRef, containerRef);
const mouseHandlers = useMouseEvent(bookKey, handlePageFlip, handleContinuousScroll);
const touchHandlers = useTouchEvent(bookKey, handlePageFlip, handleContinuousScroll);
const { handlePageFlip } = usePagination(bookKey, viewRef, containerRef);
const mouseHandlers = useMouseEvent(bookKey, handlePageFlip);
const touchHandlers = useTouchEvent(bookKey, handlePageFlip);
const [selectedImage, setSelectedImage] = useState<string | null>(null);
const [selectedTableHtml, setSelectedTableHtml] = useState<string | null>(null);
@@ -2,24 +2,18 @@ import { useEffect, useRef } from 'react';
import { useReaderStore } from '@/store/readerStore';
import { useBookDataStore } from '@/store/bookDataStore';
import { debounce } from '@/utils/debounce';
import { ScrollSource } from './usePagination';
import { eventDispatcher } from '@/utils/event';
import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL } from '@/services/constants';
export const useMouseEvent = (
bookKey: string,
handlePageFlip: (msg: MessageEvent | React.MouseEvent<HTMLDivElement, MouseEvent>) => void,
handleContinuousScroll: (source: ScrollSource, delta: number, threshold: number) => void,
) => {
const { hoveredBookKey } = useReaderStore();
const debounceScroll = debounce(handleContinuousScroll, 500);
const debounceFlip = debounce(handlePageFlip, 100);
const handleMouseEvent = (msg: MessageEvent | React.MouseEvent<HTMLDivElement, MouseEvent>) => {
if (msg instanceof MessageEvent) {
if (msg.data && msg.data.bookKey === bookKey) {
if (msg.data.type === 'iframe-wheel') {
debounceScroll('mouse', -msg.data.deltaY, 0);
}
if (msg.data.type === 'iframe-wheel') {
if (msg.data.ctrlKey) {
if (msg.data.deltaY > 0) {
@@ -34,10 +28,7 @@ export const useMouseEvent = (
handlePageFlip(msg);
}
}
} else if (msg.type === 'wheel') {
const event = msg as React.WheelEvent<HTMLDivElement>;
debounceScroll('mouse', -event.deltaY, 0);
} else {
} else if (msg.type !== 'wheel') {
handlePageFlip(msg);
}
};
@@ -92,11 +83,7 @@ interface IframeTouchEvent {
targetTouches: IframeTouch[];
}
export const useTouchEvent = (
bookKey: string,
handlePageFlip: (msg: CustomEvent) => void,
handleContinuousScroll: (source: ScrollSource, delta: number, threshold: number) => void,
) => {
export const useTouchEvent = (bookKey: string, handlePageFlip: (msg: CustomEvent) => void) => {
const { getBookData } = useBookDataStore();
const { hoveredBookKey, setHoveredBookKey, getViewSettings, getView } = useReaderStore();
@@ -241,7 +228,6 @@ export const useTouchEvent = (
},
}),
);
handleContinuousScroll('touch', deltaY, 30);
}
touchStartRef.current = null;
@@ -242,45 +242,6 @@ export const usePagination = (
}
};
const handleContinuousScroll = (mode: ScrollSource, scrollDelta: number, threshold: number) => {
const renderer = viewRef.current?.renderer;
const viewSettings = getViewSettings(bookKey)!;
const bookData = getBookData(bookKey)!;
// Continuous scroll is not supported in pre-paginated layout unless scrolled mode is active
if (bookData.bookDoc?.rendition?.layout === 'pre-paginated' && !viewSettings.scrolled) return;
if (renderer && viewSettings.scrolled && viewSettings.continuousScroll) {
const doScroll = () => {
// may have overscroll where the start is greater than 0
if (renderer.start <= scrollDelta && scrollDelta > threshold) {
setTimeout(() => {
viewRef.current?.prev(renderer.start + 1);
}, 100);
// sometimes viewSize has subpixel value that the end never reaches
} else if (
Math.ceil(renderer.end) - scrollDelta >= renderer.viewSize &&
scrollDelta < -threshold
) {
setTimeout(() => {
viewRef.current?.next(renderer.viewSize - Math.floor(renderer.end) + 1);
}, 100);
}
};
if (mode === 'mouse') {
// we can always get mouse wheel events
doScroll();
} else if (mode === 'touch') {
// when the document height is less than the viewport height, we can't get the relocate event
if (renderer.size >= renderer.viewSize) {
doScroll();
} else {
// scroll after the relocate event
renderer.addEventListener('relocate', () => doScroll(), { once: true });
}
}
}
};
useEffect(() => {
if (!appService?.isMobileApp) return;
@@ -301,6 +262,5 @@ export const usePagination = (
return {
handlePageFlip,
handleContinuousScroll,
};
};
@@ -201,6 +201,7 @@ export const handleClick = (
footnote:
footnote.getAttribute('data-wr-footernote') ||
footnote.getAttribute('zy-footnote') ||
footnote.querySelector('img')?.getAttribute('alt') ||
footnote.getAttribute('alt') ||
element?.getAttribute('alt') ||
'',
@@ -27,7 +27,6 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
const [isScrolledMode, setScrolledMode] = useState(viewSettings.scrolled);
const [isContinuousScroll, setIsContinuousScroll] = useState(viewSettings.continuousScroll);
const [scrollingOverlap, setScrollingOverlap] = useState(viewSettings.scrollingOverlap);
const [hideScrollbar, setHideScrollbar] = useState(viewSettings.hideScrollbar || false);
const [volumeKeysToFlip, setVolumeKeysToFlip] = useState(viewSettings.volumeKeysToFlip);
@@ -56,7 +55,6 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
const handleReset = () => {
resetToDefaults({
scrolled: setScrolledMode,
continuousScroll: setIsContinuousScroll,
scrollingOverlap: setScrollingOverlap,
hideScrollbar: setHideScrollbar,
volumeKeysToFlip: setVolumeKeysToFlip,
@@ -95,11 +93,6 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hideScrollbar]);
useEffect(() => {
saveViewSettings(envConfig, bookKey, 'continuousScroll', isContinuousScroll, false, false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isContinuousScroll]);
useEffect(() => {
if (scrollingOverlap === viewSettings.scrollingOverlap) return;
saveViewSettings(envConfig, bookKey, 'scrollingOverlap', scrollingOverlap, false, false);
@@ -242,16 +235,6 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
onChange={() => setScrolledMode(!isScrolledMode)}
/>
</div>
<div className='config-item' data-setting-id='settings.control.continuousScroll'>
<span className=''>{_('Continuous Scroll')}</span>
<input
type='checkbox'
className='toggle'
checked={isContinuousScroll}
disabled={bookData?.isFixedLayout}
onChange={() => setIsContinuousScroll(!isContinuousScroll)}
/>
</div>
<NumberInput
label={_('Overlap Pixels')}
value={scrollingOverlap}
@@ -392,12 +392,6 @@ const controlPanelItems = [
keywords: ['scroll', 'scrolled', 'mode', 'paginate', 'continuous'],
section: 'Scroll',
},
{
id: 'settings.control.continuousScroll',
labelKey: _('Continuous Scroll'),
keywords: ['continuous', 'scroll', 'endless', 'infinite'],
section: 'Scroll',
},
{
id: 'settings.control.overlapPixels',
labelKey: _('Overlap Pixels'),
@@ -184,7 +184,6 @@ export const DEFAULT_BOOK_LAYOUT: BookLayout = {
swapClickArea: false,
disableDoubleClick: false,
volumeKeysToFlip: false,
continuousScroll: false,
maxColumnCount: 2,
maxInlineSize: getDefaultMaxInlineSize(),
maxBlockSize: getDefaultMaxBlockSize(),
-1
View File
@@ -125,7 +125,6 @@ export interface BookLayout {
swapClickArea: boolean;
disableDoubleClick: boolean;
volumeKeysToFlip: boolean;
continuousScroll: boolean;
maxColumnCount: number;
maxInlineSize: number;
maxBlockSize: number;