mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop: TinyMCE: Added support for scroll restore
This commit is contained in:
parent
c3a1e7c6e9
commit
3f8833eaf1
@ -68,6 +68,7 @@ ElectronClient/gui/NoteEditor/NoteBody/AceEditor/Toolbar.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
ElectronClient/gui/NoteEditor/NoteEditor.js
|
||||
ElectronClient/gui/NoteEditor/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/index.js
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -58,6 +58,7 @@ ElectronClient/gui/NoteEditor/NoteBody/AceEditor/Toolbar.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
ElectronClient/gui/NoteEditor/NoteEditor.js
|
||||
ElectronClient/gui/NoteEditor/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/index.js
|
||||
|
@ -1,7 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { useState, useEffect, useCallback, useRef, forwardRef, useImperativeHandle } from 'react';
|
||||
import { EditorCommand, NoteBodyEditorProps } from '../../utils/types';
|
||||
import { ScrollOptions, ScrollOptionTypes, EditorCommand, NoteBodyEditorProps } from '../../utils/types';
|
||||
import { resourcesStatus } from '../../utils/resourceHandling';
|
||||
import useScroll from './utils/useScroll';
|
||||
const { MarkupToHtml } = require('lib/joplin-renderer');
|
||||
const taboverride = require('taboverride');
|
||||
const { reg } = require('lib/registry.js');
|
||||
@ -142,6 +143,9 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
const attachResources = useRef(null);
|
||||
attachResources.current = props.attachResources;
|
||||
|
||||
const props_onMessage = useRef(null);
|
||||
props_onMessage.current = props.onMessage;
|
||||
|
||||
const markupToHtml = useRef(null);
|
||||
markupToHtml.current = props.markupToHtml;
|
||||
|
||||
@ -154,6 +158,8 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
const styles = styles_(props);
|
||||
const theme = themeStyle(props.theme);
|
||||
|
||||
const { scrollToPercent } = useScroll({ editor, onScroll: props.onScroll });
|
||||
|
||||
const dispatchDidUpdate = (editor:any) => {
|
||||
if (dispatchDidUpdateIID_) clearTimeout(dispatchDidUpdateIID_);
|
||||
dispatchDidUpdateIID_ = setTimeout(() => {
|
||||
@ -197,10 +203,25 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
console.warn('TinyMCE::setContent - not implemented');
|
||||
},
|
||||
resetScroll: () => {
|
||||
console.warn('TinyMCE::resetScroll - not implemented');
|
||||
if (editor) editor.getWin().scrollTo(0,0);
|
||||
},
|
||||
scrollTo: (/* options:ScrollOptions*/) => {
|
||||
console.warn('TinyMCE::scrollTo - not implemented');
|
||||
scrollTo: (options:ScrollOptions) => {
|
||||
if (!editor) return;
|
||||
|
||||
if (options.type === ScrollOptionTypes.Hash) {
|
||||
const anchor = editor.getDoc().getElementById(options.value);
|
||||
if (!anchor) {
|
||||
console.warn('Cannot find hash', options);
|
||||
return;
|
||||
}
|
||||
anchor.scrollIntoView();
|
||||
} else if (options.type === ScrollOptionTypes.Percent) {
|
||||
scrollToPercent(options.value);
|
||||
} else {
|
||||
throw new Error(`Unsupported scroll options: ${options.type}`);
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
clearState: () => {
|
||||
console.warn('TinyMCE::clearState - not implemented');
|
||||
@ -575,6 +596,10 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
editor.on('init', () => {
|
||||
setEditorReady(true);
|
||||
});
|
||||
|
||||
editor.on('SetContent', () => {
|
||||
props_onMessage.current({ channel: 'noteRenderComplete' });
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,70 @@
|
||||
import { useEffect, useCallback, useRef } from 'react';
|
||||
|
||||
interface HookDependencies {
|
||||
editor:any,
|
||||
onScroll: Function,
|
||||
}
|
||||
|
||||
export default function useScroll(dependencies:HookDependencies) {
|
||||
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]);
|
||||
|
||||
const scrollToPercent = useCallback((percent:number) => {
|
||||
if (!editor) return;
|
||||
editor.getWin().scrollTo(0, maxScrollTop() * percent);
|
||||
}, [editor, maxScrollTop]);
|
||||
|
||||
const scheduleOnScroll = useCallback((event: any) => {
|
||||
if (scrollTimeoutId_.current) {
|
||||
clearTimeout(scrollTimeoutId_.current);
|
||||
scrollTimeoutId_.current = null;
|
||||
}
|
||||
|
||||
scrollTimeoutId_.current = setTimeout(() => {
|
||||
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 };
|
||||
}
|
Loading…
Reference in New Issue
Block a user