mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-29 10:09:26 +02:00
web: stop the pixel scroll fallback fighting the block anchor
This commit is contained in:
@@ -950,6 +950,16 @@ function isFile(e: DragEvent) {
|
||||
);
|
||||
}
|
||||
|
||||
/** The editor is not always registered yet when a note first loads. */
|
||||
function retryScrollAnchor(sessionId: string, anchor: ScrollAnchor, tries = 5) {
|
||||
if (tries <= 0) return;
|
||||
requestAnimationFrame(() => {
|
||||
const editor = useEditorManager.getState().getEditor(sessionId)?.editor;
|
||||
if (editor?.restoreScrollAnchor(anchor)) return;
|
||||
retryScrollAnchor(sessionId, anchor, tries - 1);
|
||||
});
|
||||
}
|
||||
|
||||
function restoreScrollPosition(session: EditorSession, editor?: IEditor) {
|
||||
if (session?.activeBlockId) return scrollIntoViewById(session.activeBlockId);
|
||||
|
||||
@@ -957,11 +967,20 @@ function restoreScrollPosition(session: EditorSession, editor?: IEditor) {
|
||||
// against a fully rendered document, and a paged one only knows estimated
|
||||
// heights until it renders. The editor reveals the page holding the block
|
||||
// before scrolling, so the position it lands on is the real one.
|
||||
//
|
||||
// Once there is an anchor the pixel path must not run at all, not even as a
|
||||
// fallback: it scrolls to an offset that means something else now, and its
|
||||
// ResizeObserver fires again every time a page renders and changes the
|
||||
// document's height.
|
||||
const anchor = Config.get<ScrollAnchor | null>(
|
||||
`${session.id}:scroll-anchor`,
|
||||
null
|
||||
);
|
||||
if (anchor && editor?.restoreScrollAnchor(anchor)) return;
|
||||
if (anchor) {
|
||||
if (editor?.restoreScrollAnchor(anchor)) return;
|
||||
retryScrollAnchor(session.id, anchor);
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollContainer = document.getElementById(`editorScroll_${session.id}`);
|
||||
const scrollPosition = Config.get(`${session.id}:scroll-position`, 0);
|
||||
|
||||
@@ -208,6 +208,12 @@ function TipTap(props: TipTapProps) {
|
||||
} = props;
|
||||
|
||||
const autoSave = useRef(true);
|
||||
|
||||
useEffect(() => {
|
||||
profiler.count("editor.mounts");
|
||||
profiler.event("editor.mount", { id });
|
||||
return () => profiler.count("editor.unmounts");
|
||||
}, []);
|
||||
const { toolbarConfig } = useToolbarConfig();
|
||||
const features = useAreFeaturesAvailable([
|
||||
"callout",
|
||||
|
||||
@@ -57,7 +57,8 @@ export const useEditor = (
|
||||
// The Editor constructor already rendered a view into the same element,
|
||||
// so replacing it on the first run means rendering the whole document
|
||||
// twice. Only later runs (changed options) need a fresh view.
|
||||
if (isFirstRun.current) {
|
||||
const firstRun = isFirstRun.current;
|
||||
if (firstRun) {
|
||||
isFirstRun.current = false;
|
||||
} else {
|
||||
profiler.time("editor.destroyView", () => destroyView(editor.view));
|
||||
@@ -70,7 +71,9 @@ export const useEditor = (
|
||||
});
|
||||
}
|
||||
if (oldIsFocused && !editor.isFocused) editor.commands.focus();
|
||||
options.onCreate?.({ editor: editor });
|
||||
// The Editor constructor emits `create` for the view it made, so calling
|
||||
// the option here as well would run every consumer twice on load.
|
||||
if (!firstRun) options.onCreate?.({ editor: editor });
|
||||
|
||||
const { searchTerm, ...searchOptions } = useEditorSearchStore.getState();
|
||||
if (!searchOptions.isSearching) {
|
||||
|
||||
Reference in New Issue
Block a user