diff --git a/apps/readest-app/src/app/reader/components/FoliateViewer.tsx b/apps/readest-app/src/app/reader/components/FoliateViewer.tsx
index 60534b6c..727287ea 100644
--- a/apps/readest-app/src/app/reader/components/FoliateViewer.tsx
+++ b/apps/readest-app/src/app/reader/components/FoliateViewer.tsx
@@ -114,18 +114,6 @@ const FoliateViewer: React.FC<{
const detail = (event as CustomEvent).detail;
if (detail.reason !== 'scroll' && detail.reason !== 'page') return;
- if (detail.reason === 'scroll') {
- const renderer = viewRef.current?.renderer;
- const viewSettings = getViewSettings(bookKey)!;
- if (renderer && viewSettings.continuousScroll) {
- if (renderer.start <= 0) {
- viewRef.current?.prev(1);
- // sometimes viewSize has subpixel value that the end never reaches
- } else if (renderer.end + 1 >= renderer.viewSize) {
- viewRef.current?.next(1);
- }
- }
- }
const parallelViews = getParallels(bookKey);
if (parallelViews && parallelViews.size > 0) {
parallelViews.forEach((key) => {
@@ -140,7 +128,7 @@ const FoliateViewer: React.FC<{
};
const { handlePageFlip } = usePageFlip(bookKey, viewRef, containerRef);
- useTouchEvent(bookKey, viewRef);
+ const { onTouchStart, onTouchMove, onTouchEnd } = useTouchEvent(bookKey, viewRef);
useClickEvent(bookKey, handlePageFlip);
useFoliateEvents(viewRef.current, {
@@ -226,6 +214,9 @@ const FoliateViewer: React.FC<{
handlePageFlip(event)}
+ onTouchStart={onTouchStart}
+ onTouchMove={onTouchMove}
+ onTouchEnd={onTouchEnd}
ref={containerRef}
/>
>
diff --git a/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts b/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts
index 29606161..2a0c3b73 100644
--- a/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts
+++ b/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts
@@ -29,25 +29,25 @@ export const useTouchEvent = (
viewRef: React.MutableRefObject,
) => {
const { hoveredBookKey, setHoveredBookKey, getViewSettings } = useReaderStore();
- const viewSettings = getViewSettings(bookKey)!;
let touchStart: IframeTouch | null = null;
let touchEnd: IframeTouch | null = null;
- const onTouchStart = (e: IframeTouchEvent) => {
+ const onTouchStart = (e: IframeTouchEvent | React.TouchEvent) => {
touchEnd = null;
const touch = e.targetTouches[0];
if (!touch) return;
touchStart = touch;
};
- const onTouchMove = (e: IframeTouchEvent) => {
+ const onTouchMove = (e: IframeTouchEvent | React.TouchEvent) => {
if (!touchStart) return;
const touch = e.targetTouches[0];
if (touch) {
touchEnd = touch;
}
if (hoveredBookKey && touchEnd) {
+ const viewSettings = getViewSettings(bookKey)!;
const deltaY = touchEnd.screenY - touchStart.screenY;
const deltaX = touchEnd.screenX - touchStart.screenX;
if (!viewSettings!.scrolled && !viewSettings!.vertical) {
@@ -60,7 +60,7 @@ export const useTouchEvent = (
}
};
- const onTouchEnd = (e: IframeTouchEvent) => {
+ const onTouchEnd = (e: IframeTouchEvent | React.TouchEvent) => {
if (!touchStart) return;
const touch = e.targetTouches[0];
@@ -70,6 +70,7 @@ export const useTouchEvent = (
const windowWidth = window.innerWidth;
if (touchEnd) {
+ const viewSettings = getViewSettings(bookKey)!;
const deltaY = touchEnd.screenY - touchStart.screenY;
const deltaX = touchEnd.screenX - touchStart.screenX;
// also check for deltaX to prevent swipe page turn from triggering the toggle
@@ -87,6 +88,34 @@ export const useTouchEvent = (
setHoveredBookKey(null);
}
}
+ const renderer = viewRef.current?.renderer;
+ if (renderer && viewSettings.scrolled && viewSettings.continuousScroll) {
+ const SCROLL_THRESHOLD = 30;
+ const doScroll = () => {
+ // may have overscroll where the start is greater than 0
+ if (renderer.start <= deltaY && deltaY > SCROLL_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) - deltaY >= renderer.viewSize &&
+ deltaY < -SCROLL_THRESHOLD
+ ) {
+ setTimeout(() => {
+ viewRef.current?.next(renderer.viewSize - Math.floor(renderer.end) + 1);
+ }, 100);
+ }
+ };
+ if (renderer.size >= renderer.viewSize) {
+ doScroll();
+ } else {
+ const handleRelocate = () => {
+ doScroll();
+ };
+ renderer.addEventListener('relocate', handleRelocate, { once: true });
+ }
+ }
}
touchStart = null;
@@ -112,4 +141,10 @@ export const useTouchEvent = (
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hoveredBookKey, viewRef.current]);
+
+ return {
+ onTouchStart,
+ onTouchMove,
+ onTouchEnd,
+ };
};
diff --git a/apps/readest-app/src/types/view.ts b/apps/readest-app/src/types/view.ts
index fce1767a..92621ebf 100644
--- a/apps/readest-app/src/types/view.ts
+++ b/apps/readest-app/src/types/view.ts
@@ -48,7 +48,11 @@ export interface FoliateView extends HTMLElement {
goTo?: (params: { index: number; anchor: number }) => void;
setStyles?: (css: string) => void;
getContents: () => { doc: Document; index?: number }[];
- addEventListener: (type: string, listener: EventListener) => void;
+ addEventListener: (
+ type: string,
+ listener: EventListener,
+ option?: AddEventListenerOptions,
+ ) => void;
removeEventListener: (type: string, listener: EventListener) => void;
};
}