mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-24 04:27:27 +08:00
fix(editor): prevent cursor jumping to title when pressing backspace on the begin of edgeless note (#12410)
Close [BS-3492](https://linear.app/affine-design/issue/BS-3492/白板上的note,在开头按退格键,光标会到page-block的title上) ### Before https://github.com/user-attachments/assets/334504f2-30f3-4ce2-ba60-a2688a811b53 ### After https://github.com/user-attachments/assets/be26be6c-6cfc-4f69-82b7-1127e0d10a1a <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved behavior when deleting a note block to ensure the cursor focus does not incorrectly jump to the page title after pressing backspace. - **Tests** - Added a new test to verify that focus remains within the note block after deletion, preventing unwanted cursor movement to the page title. - Introduced a utility to check if the document title is focused during tests. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
|||||||
EdgelessTextBlockModel,
|
EdgelessTextBlockModel,
|
||||||
ImageBlockModel,
|
ImageBlockModel,
|
||||||
ListBlockModel,
|
ListBlockModel,
|
||||||
|
NoteBlockModel,
|
||||||
ParagraphBlockModel,
|
ParagraphBlockModel,
|
||||||
type RootBlockModel,
|
type RootBlockModel,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
@@ -19,7 +20,6 @@ import { EMBED_BLOCK_MODEL_LIST } from '@blocksuite/affine-shared/consts';
|
|||||||
import type { ExtendedModel } from '@blocksuite/affine-shared/types';
|
import type { ExtendedModel } from '@blocksuite/affine-shared/types';
|
||||||
import {
|
import {
|
||||||
focusTitle,
|
focusTitle,
|
||||||
getDocTitleInlineEditor,
|
|
||||||
getPrevContentBlock,
|
getPrevContentBlock,
|
||||||
matchModels,
|
matchModels,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
@@ -122,41 +122,39 @@ function handleNoPreviousSibling(editorHost: EditorHost, model: ExtendedModel) {
|
|||||||
const text = model.text;
|
const text = model.text;
|
||||||
const parent = doc.getParent(model);
|
const parent = doc.getParent(model);
|
||||||
if (!parent) return false;
|
if (!parent) return false;
|
||||||
const titleEditor = getDocTitleInlineEditor(editorHost);
|
|
||||||
// Probably no title, e.g. in edgeless mode
|
if (matchModels(parent, [NoteBlockModel]) && parent.isPageBlock()) {
|
||||||
if (!titleEditor) {
|
const rootModel = model.store.root as RootBlockModel;
|
||||||
if (
|
const title = rootModel.props.title;
|
||||||
matchModels(parent, [EdgelessTextBlockModel]) ||
|
|
||||||
model.children.length > 0
|
doc.captureSync();
|
||||||
) {
|
let textLength = 0;
|
||||||
|
if (text) {
|
||||||
|
textLength = text.length;
|
||||||
|
title.join(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preserve at least one block to be able to focus on container click
|
||||||
|
if (doc.getNext(model) || model.children.length > 0) {
|
||||||
doc.deleteBlock(model, {
|
doc.deleteBlock(model, {
|
||||||
bringChildrenTo: parent,
|
bringChildrenTo: parent,
|
||||||
});
|
});
|
||||||
return true;
|
} else {
|
||||||
|
text?.clear();
|
||||||
}
|
}
|
||||||
return false;
|
focusTitle(editorHost, title.length - textLength);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootModel = model.store.root as RootBlockModel;
|
if (
|
||||||
const title = rootModel.props.title;
|
matchModels(parent, [EdgelessTextBlockModel]) ||
|
||||||
|
model.children.length > 0
|
||||||
doc.captureSync();
|
) {
|
||||||
let textLength = 0;
|
|
||||||
if (text) {
|
|
||||||
textLength = text.length;
|
|
||||||
title.join(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preserve at least one block to be able to focus on container click
|
|
||||||
if (doc.getNext(model) || model.children.length > 0) {
|
|
||||||
const parent = doc.getParent(model);
|
|
||||||
if (!parent) return false;
|
|
||||||
doc.deleteBlock(model, {
|
doc.deleteBlock(model, {
|
||||||
bringChildrenTo: parent,
|
bringChildrenTo: parent,
|
||||||
});
|
});
|
||||||
} else {
|
return true;
|
||||||
text?.clear();
|
|
||||||
}
|
}
|
||||||
focusTitle(editorHost, title.length - textLength);
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
getEdgelessSelectedIds,
|
getEdgelessSelectedIds,
|
||||||
getPageMode,
|
getPageMode,
|
||||||
getSelectedXYWH,
|
getSelectedXYWH,
|
||||||
|
isDocTitleFocused,
|
||||||
locateEditorContainer,
|
locateEditorContainer,
|
||||||
locateModeSwitchButton,
|
locateModeSwitchButton,
|
||||||
locateToolbar,
|
locateToolbar,
|
||||||
@@ -427,6 +428,14 @@ test.describe('note block rendering', () => {
|
|||||||
'should show collapsed content when dragging is finished'
|
'should show collapsed content when dragging is finished'
|
||||||
).toHaveCSS('overflow-y', 'visible');
|
).toHaveCSS('overflow-y', 'visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('cursor should not jump to page block title from note block', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await createEdgelessNoteBlock(page, [50, 50]);
|
||||||
|
await pressBackspace(page);
|
||||||
|
expect(await isDocTitleFocused(page)).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should convert note block to linked doc when clicking turn into linked doc button', async ({
|
test('should convert note block to linked doc when clicking turn into linked doc button', async ({
|
||||||
|
|||||||
@@ -69,6 +69,14 @@ export function locateDocTitle(page: Page, editorIndex = 0) {
|
|||||||
return locateEditorContainer(page, editorIndex).locator('doc-title');
|
return locateEditorContainer(page, editorIndex).locator('doc-title');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isDocTitleFocused(page: Page, editorIndex = 0) {
|
||||||
|
return locateDocTitle(page, editorIndex)
|
||||||
|
.locator('.inline-editor')
|
||||||
|
.evaluate(inlineEditor => {
|
||||||
|
return document.activeElement === inlineEditor;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function focusDocTitle(page: Page, editorIndex = 0) {
|
export async function focusDocTitle(page: Page, editorIndex = 0) {
|
||||||
await locateDocTitle(page, editorIndex).locator('.inline-editor').focus();
|
await locateDocTitle(page, editorIndex).locator('.inline-editor').focus();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user