2020-05-04 19:31:55 +02:00
|
|
|
import { useEffect, useCallback, useRef } from 'react';
|
2020-11-07 17:59:37 +02:00
|
|
|
import shim from '@joplin/lib/shim';
|
2020-05-04 19:31:55 +02:00
|
|
|
|
|
|
|
interface HookDependencies {
|
2020-11-12 21:13:28 +02:00
|
|
|
editor: any,
|
2020-05-04 19:31:55 +02:00
|
|
|
onScroll: Function,
|
|
|
|
}
|
|
|
|
|
2020-11-12 21:13:28 +02:00
|
|
|
export default function useScroll(dependencies: HookDependencies) {
|
2020-05-04 19:31:55 +02:00
|
|
|
const { editor, onScroll } = dependencies;
|
|
|
|
const scrollTimeoutId_ = useRef(null);
|
|
|
|
|
|
|
|
const maxScrollTop = useCallback(() => {
|
|
|
|
if (!editor) return 0;
|
|
|
|
|
|
|
|
const doc = editor.getDoc();
|
|
|
|
const win = editor.getWin();
|
|
|
|
if (!doc || !win) return 0;
|
|
|
|
const firstChild = doc.firstElementChild;
|
|
|
|
if (!firstChild) return 0;
|
|
|
|
|
|
|
|
const winHeight = win.innerHeight;
|
|
|
|
const contentHeight = firstChild.scrollHeight;
|
|
|
|
return contentHeight < winHeight ? 0 : contentHeight - winHeight;
|
|
|
|
}, [editor]);
|
|
|
|
|
|
|
|
const scrollTop = useCallback(() => {
|
|
|
|
if (!editor) return 0;
|
|
|
|
const win = editor.getWin();
|
|
|
|
if (!win) return 0;
|
|
|
|
return win.scrollY;
|
|
|
|
}, [editor]);
|
|
|
|
|
|
|
|
const scrollPercent = useCallback(() => {
|
|
|
|
const m = maxScrollTop();
|
|
|
|
const t = scrollTop();
|
|
|
|
return m <= 0 ? 0 : t / m;
|
|
|
|
}, [maxScrollTop, scrollTop]);
|
|
|
|
|
2020-11-12 21:13:28 +02:00
|
|
|
const scrollToPercent = useCallback((percent: number) => {
|
2020-05-04 19:31:55 +02:00
|
|
|
if (!editor) return;
|
|
|
|
editor.getWin().scrollTo(0, maxScrollTop() * percent);
|
|
|
|
}, [editor, maxScrollTop]);
|
|
|
|
|
|
|
|
const scheduleOnScroll = useCallback((event: any) => {
|
|
|
|
if (scrollTimeoutId_.current) {
|
2020-10-09 19:35:46 +02:00
|
|
|
shim.clearTimeout(scrollTimeoutId_.current);
|
2020-05-04 19:31:55 +02:00
|
|
|
scrollTimeoutId_.current = null;
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:35:46 +02:00
|
|
|
scrollTimeoutId_.current = shim.setTimeout(() => {
|
2020-05-04 19:31:55 +02:00
|
|
|
scrollTimeoutId_.current = null;
|
|
|
|
onScroll(event);
|
|
|
|
}, 10);
|
|
|
|
}, [onScroll]);
|
|
|
|
|
|
|
|
const onEditorScroll = useCallback(() => {
|
|
|
|
scheduleOnScroll({ percent: scrollPercent() });
|
|
|
|
}, [scheduleOnScroll, scrollPercent]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (!editor) return () => {};
|
|
|
|
|
|
|
|
editor.getDoc().addEventListener('scroll', onEditorScroll);
|
|
|
|
return () => {
|
|
|
|
editor.getDoc().removeEventListener('scroll', onEditorScroll);
|
|
|
|
};
|
|
|
|
}, [editor, onEditorScroll]);
|
|
|
|
|
|
|
|
return { scrollToPercent };
|
|
|
|
}
|