mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
editor: size the note without rendering pages it will scroll past
This commit is contained in:
@@ -195,6 +195,26 @@ describe("scroll anchor", () => {
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
test("does not render pages it is about to scroll away from", () => {
|
||||
const editor = createEditor(createContainer());
|
||||
stubLayout(editor);
|
||||
const before = Array.from(editor.view.dom.children).map((page) =>
|
||||
(page as HTMLElement).hasAttribute("data-page-placeholder")
|
||||
);
|
||||
|
||||
restoreScrollAnchor(editor.view, { blockId: "blk300", offset: 0 });
|
||||
|
||||
// page 3 is neither an edge, nor next to the caret, nor near the anchor:
|
||||
// nothing should have rendered it on the way past
|
||||
expect(before[3]).toBe(true);
|
||||
expect(
|
||||
(editor.view.dom.children[3] as HTMLElement).hasAttribute(
|
||||
"data-page-placeholder"
|
||||
)
|
||||
).toBe(true);
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
test("reports failure for a block that is no longer there", () => {
|
||||
const editor = createEditor(createContainer());
|
||||
stubLayout(editor);
|
||||
|
||||
@@ -22,6 +22,7 @@ import { EditorView } from "@tiptap/pm/view";
|
||||
import { profiler } from "../../utils/profiler.js";
|
||||
import { isPage } from "./split.js";
|
||||
import {
|
||||
calibrateHeightsNow,
|
||||
findScrollParent,
|
||||
renderViewportNow,
|
||||
viewportKey
|
||||
@@ -113,11 +114,12 @@ export function restoreScrollAnchor(
|
||||
return false;
|
||||
}
|
||||
|
||||
// Empty pages start out sized from a guess, and the note shrinks once the
|
||||
// first real measurements arrive. Doing that first means scrolling against
|
||||
// the heights the note will actually have, instead of being dragged along
|
||||
// when it changes size a moment later.
|
||||
renderViewportNow(view);
|
||||
// Empty pages start out sized from a guess, and the note changes height once
|
||||
// the first real measurements arrive. Sizing them first means scrolling
|
||||
// against the heights the note will actually have, and doing it without
|
||||
// rendering anything avoids showing pages here that are about to be left
|
||||
// behind.
|
||||
calibrateHeightsNow(view);
|
||||
|
||||
const target = findBlock(view.state.doc, anchor.blockId);
|
||||
if (!target.found) {
|
||||
|
||||
@@ -38,6 +38,16 @@ type PageRange = { from: number; to: number; index: number };
|
||||
const EMPTY_VISIBLE: Set<string> = new Set();
|
||||
|
||||
const pending = new WeakMap<EditorView, () => void>();
|
||||
const calibrations = new WeakMap<EditorView, () => void>();
|
||||
|
||||
/**
|
||||
* Sizes the empty pages from what the note actually looks like, without
|
||||
* changing which pages are rendered. Used before scrolling somewhere, so the
|
||||
* note is not still changing height once it gets there.
|
||||
*/
|
||||
export function calibrateHeightsNow(view: EditorView): void {
|
||||
calibrations.get(view)?.();
|
||||
}
|
||||
|
||||
/**
|
||||
* Works out what is on screen right now instead of waiting for the next frame.
|
||||
@@ -500,6 +510,11 @@ export function viewportPlugin(heights: HeightMap): Plugin<ViewportState> {
|
||||
};
|
||||
|
||||
pending.set(editorView, flush);
|
||||
calibrations.set(editorView, () => {
|
||||
updateMetrics();
|
||||
measureRenderedPages();
|
||||
resizePlaceholders();
|
||||
});
|
||||
window.addEventListener("beforeprint", beforePrint);
|
||||
window.addEventListener("afterprint", afterPrint);
|
||||
|
||||
@@ -533,6 +548,7 @@ export function viewportPlugin(heights: HeightMap): Plugin<ViewportState> {
|
||||
window.removeEventListener("afterprint", afterPrint);
|
||||
printMedia?.removeEventListener?.("change", onPrintMedia);
|
||||
pending.delete(editorView);
|
||||
calibrations.delete(editorView);
|
||||
window.removeEventListener("resize", schedule);
|
||||
scrollParent?.removeEventListener("scroll", schedule);
|
||||
layout?.disconnect();
|
||||
|
||||
Reference in New Issue
Block a user