Skip to content

Commit

Permalink
Position the cursor at the beginning of the next block when a block i…
Browse files Browse the repository at this point in the history
…s deleted

This also changes the behavior when blocks are moved.
Add tests for the deleteBlock command.
  • Loading branch information
heyman committed Jan 9, 2025
1 parent 03ec7a4 commit e195472
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 8 deletions.
40 changes: 40 additions & 0 deletions src/editor/block/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,46 @@ export function triggerCurrenciesLoaded(state, dispatch) {
}

export const deleteBlock = (editor) => ({state, dispatch}) => {
const range = state.selection.asSingle().ranges[0]
const blocks = state.facet(blockState)
let block
let nextBlock
for (let i = 0; i < blocks.length; i++) {
block = blocks[i]
if (block.range.from <= range.head && block.range.to >= range.head) {
if (i < blocks.length - 1) {
nextBlock = blocks[i + 1]
}
break
}
}

let replace = ""
let newSelection

if (blocks.length == 1) {
replace = getBlockDelimiter(editor.defaultBlockToken, editor.defaultBlockAutoDetect)
newSelection = replace.length
} else if (!nextBlock) {
// if it's the last block, the cursor should go at the en of the previous block
newSelection = block.delimiter.from
} else {
// if there is a next block, we want the cursor to be at the beginning of that block
newSelection = block.delimiter.from + (nextBlock.delimiter.to - nextBlock.delimiter.from)
}

dispatch(state.update({
changes: {
from: block.range.from,
to: block.range.to,
insert: replace,
},
selection: EditorSelection.cursor(newSelection),
annotations: [heynoteEvent.of(DELETE_BLOCK)],
}))
}

export const deleteBlockSetCursorPreviousBlock = (editor) => ({state, dispatch}) => {
const block = getActiveNoteBlock(state)
const blocks = state.facet(blockState)
let replace = ""
Expand Down
7 changes: 7 additions & 0 deletions src/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ export class HeynoteEditor {
return this.view.state.selection.main.head
}

setCursorPosition(position) {
this.view.dispatch({
selection: {anchor: position, head: position},
scrollIntoView: true,
})
}

focus() {
this.view.focus()
}
Expand Down
44 changes: 44 additions & 0 deletions tests/delete-block.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {expect, test} from "@playwright/test";
import {HeynotePage} from "./test-utils.js";

import { AUTO_SAVE_INTERVAL } from "../src/common/constants.js"
import { NoteFormat } from "../src/common/note-format.js"


let heynotePage

test.beforeEach(async ({page}) => {
heynotePage = new HeynotePage(page)
await heynotePage.goto()

expect((await heynotePage.getBlocks()).length).toBe(1)
await heynotePage.setContent(`
∞∞∞text
Block A
∞∞∞markdown
Block B
∞∞∞text
Block C`)
await page.waitForTimeout(100)
})

test("delete first block", async ({page}) => {
await heynotePage.setCursorPosition(10)
await page.locator("body").press(heynotePage.agnosticKey("Mod+Shift+D"))
await page.waitForTimeout(50)
expect(await heynotePage.getCursorPosition()).toBe(13)
})

test("delete middle block", async ({page}) => {
await heynotePage.setCursorPosition(32)
await page.locator("body").press(heynotePage.agnosticKey("Mod+Shift+D"))
await page.waitForTimeout(50)
expect(await heynotePage.getCursorPosition()).toBe(25)
})

test("delete last block", async ({page}) => {
await heynotePage.setCursorPosition(52)
await page.locator("body").press(heynotePage.agnosticKey("Mod+Shift+D"))
await page.waitForTimeout(50)
expect(await heynotePage.getCursorPosition()).toBe(36)
})
40 changes: 32 additions & 8 deletions tests/move-block.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ Block C`)

// check that visual block layers are created
await expect(page.locator("css=.heynote-blocks-layer > div")).toHaveCount(3)
});


test("move block to other buffer", async ({page}) => {
// create secondary buffer
await heynotePage.saveBuffer("other.txt", `
∞∞∞text-a
First block
∞∞∞math
Second block`)
});


test("move block to other buffer", async ({page}) => {
await page.locator("body").press(heynotePage.agnosticKey("Mod+S"))
await page.waitForTimeout(50)
await page.locator("body").press("Enter")
Expand Down Expand Up @@ -62,11 +64,6 @@ Block C`)


test("move block to other open/cached buffer", async ({page}) => {
await heynotePage.saveBuffer("other.txt", `
∞∞∞text-a
First block
∞∞∞math
Second block`)
await page.locator("body").press(heynotePage.agnosticKey("Mod+P"))
await page.locator("body").press("Enter")
await page.waitForTimeout(50)
Expand Down Expand Up @@ -99,3 +96,30 @@ Block C`)

})

test("cursor position after moving first block", async ({page}) => {
await heynotePage.setCursorPosition(10)
expect(await heynotePage.getCursorPosition()).toBe(10)
await page.locator("body").press(heynotePage.agnosticKey("Mod+S"))
await page.waitForTimeout(50)
await page.locator("body").press("Enter")
await page.waitForTimeout(50)
expect(await heynotePage.getCursorPosition()).toBe(9)
})

test("cursor position after moving middle block", async ({page}) => {
await heynotePage.setCursorPosition(28)
await page.locator("body").press(heynotePage.agnosticKey("Mod+S"))
await page.waitForTimeout(50)
await page.locator("body").press("Enter")
await page.waitForTimeout(50)
expect(await heynotePage.getCursorPosition()).toBe(25)
})

test("cursor position after moving last block", async ({page}) => {
await heynotePage.setCursorPosition(48)
await page.locator("body").press(heynotePage.agnosticKey("Mod+S"))
await page.waitForTimeout(50)
await page.locator("body").press("Enter")
await page.waitForTimeout(50)
expect(await heynotePage.getCursorPosition()).toBe(32)
})
4 changes: 4 additions & 0 deletions tests/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export class HeynotePage {
return await this.page.evaluate(() => window._heynote_editor.getCursorPosition())
}

async setCursorPosition(position) {
await this.page.evaluate((position) => window._heynote_editor.setCursorPosition(position), position)
}

async getBlockContent(blockIndex) {
const blocks = await this.getBlocks()
const content = await this.getContent()
Expand Down

0 comments on commit e195472

Please sign in to comment.