Fix race condition that could cause the editor to not scroll the cursor(s) into the viewport upon loading

This commit is contained in:
Jonatan Heyman 2024-07-15 20:23:17 +02:00
parent 4b5222c324
commit 86243f493d
4 changed files with 39 additions and 33 deletions

View File

@ -136,35 +136,41 @@ export class HeynoteEditor {
}
setContent(content) {
this.note = NoteFormat.load(content)
// set buffer content
this.view.dispatch({
changes: {
from: 0,
to: this.view.state.doc.length,
insert: this.note.content,
},
annotations: [heynoteEvent.of(SET_CONTENT)],
return new Promise((resolve) => {
this.note = NoteFormat.load(content)
// set buffer content
this.view.dispatch({
changes: {
from: 0,
to: this.view.state.doc.length,
insert: this.note.content,
},
annotations: [heynoteEvent.of(SET_CONTENT)],
})
// Ensure we have a parsed syntax tree when buffer is loaded. This prevents errors for large buffers
// when moving the cursor to the end of the buffer when the program starts
ensureSyntaxTree(this.view.state, this.view.state.doc.length, 5000)
// Set cursor positions
// We use requestAnimationFrame to avoid a race condition causing the scrollIntoView to sometimes not work
requestAnimationFrame(() => {
if (this.note.cursors) {
this.view.dispatch({
selection: EditorSelection.fromJSON(this.note.cursors),
scrollIntoView: true,
})
} else {
// if metadata doesn't contain cursor position, we set the cursor to the end of the buffer
this.view.dispatch({
selection: {anchor: this.view.state.doc.length, head: this.view.state.doc.length},
scrollIntoView: true,
})
}
resolve()
})
})
// Ensure we have a parsed syntax tree when buffer is loaded. This prevents errors for large buffers
// when moving the cursor to the end of the buffer when the program starts
ensureSyntaxTree(this.view.state, this.view.state.doc.length, 5000)
// set cursor positions
if (this.note.cursors) {
this.view.dispatch({
selection: EditorSelection.fromJSON(this.note.cursors),
scrollIntoView: true,
})
} else {
// if metadata doesn't contain cursor position, we set the cursor to the end of the buffer
this.view.dispatch({
selection: {anchor: this.view.state.doc.length, head: this.view.state.doc.length},
scrollIntoView: true,
})
}
}
getBlocks() {

View File

@ -8,7 +8,7 @@ test.beforeEach(async ({page}) => {
await heynotePage.goto()
expect((await heynotePage.getBlocks()).length).toBe(1)
heynotePage.setContent(`
await heynotePage.setContent(`
text
Block A
text

View File

@ -10,7 +10,7 @@ test.beforeEach(async ({ page }) => {
test("JSON formatting", async ({ page }) => {
heynotePage.setContent(`
await heynotePage.setContent(`
json
{"test": 1, "key2": "hey!"}
`)
@ -25,7 +25,7 @@ test("JSON formatting", async ({ page }) => {
})
test("JSON formatting (cursor at start)", async ({ page }) => {
heynotePage.setContent(`
await heynotePage.setContent(`
json
{"test": 1, "key2": "hey!"}
`)

View File

@ -11,7 +11,7 @@ test.beforeEach(async ({ page }) => {
test("test restore cursor position", async ({ page, browserName }) => {
heynotePage.setContent(`{"formatVersion":"1.0", "cursors":{"ranges":[{"anchor":13,"head":13}],"main":0}}
await heynotePage.setContent(`{"formatVersion":"1.0", "cursors":{"ranges":[{"anchor":13,"head":13}],"main":0}}
text
Textblock`)
await page.locator("body").press((heynotePage.isMac ? "Meta" : "Control") + "+Alt+Enter")
@ -24,7 +24,7 @@ block`)
test("test save cursor positions", async ({ page, browserName }) => {
heynotePage.setContent(`{"formatVersion":"1.0", "cursors":{"ranges":[{"anchor":9,"head":9}],"main":0}}
await heynotePage.setContent(`{"formatVersion":"1.0", "cursors":{"ranges":[{"anchor":9,"head":9}],"main":0}}
text
this
is