chore(editor): improve index of new edgeless note from dnd (#12357)

Close [BS-3500](https://linear.app/affine-design/issue/BS-3500/剪刀没问题了,通过拖动形成的段落能不能也有同样的表现?)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Bug Fixes**
  - Improved the behavior when dragging blocks between notes, ensuring that new note blocks are inserted as siblings when appropriate, instead of always creating them at the root level.

- **Tests**
  - Enhanced and enabled tests to verify correct drag-and-drop behavior across multiple notes and to ensure the relative order of note content is preserved during drag operations.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
L-Sun
2025-05-19 08:49:08 +00:00
parent d5e2fee317
commit b7679497ca
2 changed files with 126 additions and 41 deletions

View File

@@ -30,6 +30,7 @@ import {
import { import {
captureEventTarget, captureEventTarget,
type DropTarget as DropResult, type DropTarget as DropResult,
findNoteBlockModel,
getBlockComponentsExcludeSubtrees, getBlockComponentsExcludeSubtrees,
getRectByBlockComponent, getRectByBlockComponent,
getScrollContainer, getScrollContainer,
@@ -1247,20 +1248,50 @@ export class DragEventWatcher {
console.error console.error
); );
} }
} else { }
// create note to wrap the snapshot // create note to wrap the snapshot
const noteId = store.addBlock( else {
'affine:note', const originalModel = store.getModelById(snapshot.content[0].id);
{ const originalNote = originalModel
xywh: new Bound( ? findNoteBlockModel(originalModel)
point.x, : null;
point.y,
DEFAULT_NOTE_WIDTH, let noteId: string;
DEFAULT_NOTE_HEIGHT if (originalNote) {
).serialize(), const placement =
}, originalNote.children[0].id === snapshot.content[0].id
this.widget.store.root! ? 'before'
); : 'after';
noteId = store.addSiblingBlocks(
originalNote,
[
{
flavour: 'affine:note',
xywh: new Bound(
point.x,
point.y,
DEFAULT_NOTE_WIDTH,
DEFAULT_NOTE_HEIGHT
).serialize(),
},
],
placement
)[0];
} else {
noteId = store.addBlock(
'affine:note',
{
xywh: new Bound(
point.x,
point.y,
DEFAULT_NOTE_WIDTH,
DEFAULT_NOTE_HEIGHT
).serialize(),
},
this.widget.store.root!
);
}
this._dropToModel( this._dropToModel(
{ {

View File

@@ -2,17 +2,23 @@ import { expect } from '@playwright/test';
import { import {
addNote, addNote,
changeNoteDisplayModeWithId,
createNote,
dragBlockToPoint,
dragHandleFromBlockToBlockBottomById, dragHandleFromBlockToBlockBottomById,
enterPlaygroundRoom, enterPlaygroundRoom,
focusRichText, focusRichText,
initEmptyEdgelessState, initEmptyEdgelessState,
initThreeParagraphs, initThreeParagraphs,
pressEnter,
pressEscape,
setEdgelessTool, setEdgelessTool,
switchEditorMode, switchEditorMode,
type, type,
waitNextFrame, waitNextFrame,
} from '../../utils/actions/index.js'; } from '../../utils/actions/index.js';
import { assertRectExist, assertRichTexts } from '../../utils/asserts.js'; import { assertRectExist, assertRichTexts } from '../../utils/asserts.js';
import { NoteDisplayMode } from '../../utils/bs-alternative.js';
import { test } from '../../utils/playwright.js'; import { test } from '../../utils/playwright.js';
const CENTER_X = 450; const CENTER_X = 450;
@@ -120,37 +126,85 @@ test('drag handle should work inside one note', async ({ page }) => {
await assertRichTexts(page, ['456', '789', '123']); await assertRichTexts(page, ['456', '789', '123']);
}); });
test.fixme( test('drag handle should work across multiple notes', async ({ page }) => {
'drag handle should work across multiple notes', await enterPlaygroundRoom(page);
async ({ page }) => { await initEmptyEdgelessState(page);
await enterPlaygroundRoom(page); await initThreeParagraphs(page);
await initEmptyEdgelessState(page); await assertRichTexts(page, ['123', '456', '789']);
await initThreeParagraphs(page);
await assertRichTexts(page, ['123', '456', '789']);
await switchEditorMode(page); await switchEditorMode(page);
await setEdgelessTool(page, 'note'); await setEdgelessTool(page, 'note');
await page.mouse.click(200, 200); await page.mouse.click(200, 200);
await focusRichText(page, 3); await focusRichText(page, 3);
await waitNextFrame(page); await waitNextFrame(page);
// block id 7 // block id 7
await type(page, '000'); await type(page, '000');
await page.mouse.dblclick(CENTER_X, CENTER_Y - 20); await page.mouse.dblclick(CENTER_X, CENTER_Y - 20);
await dragHandleFromBlockToBlockBottomById(page, '3', '7'); await dragHandleFromBlockToBlockBottomById(page, '3', '7');
await expect(page.locator('.affine-drag-handle-container')).toBeHidden(); await expect(page.locator('.affine-drag-handle-container')).toBeHidden();
await waitNextFrame(page); await waitNextFrame(page);
await assertRichTexts(page, ['456', '789', '000', '123']); await assertRichTexts(page, ['456', '789', '000', '123']);
// await page.mouse.dblclick(305, 305); await page
await dragHandleFromBlockToBlockBottomById(page, '3', '4'); .locator('affine-edgeless-note')
await waitNextFrame(page); .nth(1)
await expect(page.locator('.affine-drag-handle-container')).toBeHidden(); .locator('affine-paragraph')
await assertRichTexts(page, ['456', '123', '789', '000']); .nth(1)
.click({ clickCount: 3 });
await dragHandleFromBlockToBlockBottomById(page, '3', '4');
await waitNextFrame(page);
await expect(page.locator('.affine-drag-handle-container')).toBeHidden();
await assertRichTexts(page, ['456', '123', '789', '000']);
await expect(page.locator('selected > *')).toHaveCount(0); await expect(page.locator('selected > *')).toHaveCount(0);
} });
);
test('should keep relative order of new note when a block is dragged from note to canvas', async ({
page,
}) => {
await enterPlaygroundRoom(page);
await initEmptyEdgelessState(page);
await focusRichText(page);
await type(page, '3');
await switchEditorMode(page);
const note2 = await createNote(page, [0, -200], '5');
await pressEnter(page);
await type(page, '6');
await pressEnter(page);
await type(page, '7');
await pressEscape(page, 3);
await changeNoteDisplayModeWithId(
page,
note2,
NoteDisplayMode.DocAndEdgeless
);
await pressEscape(page);
const note3 = await createNote(page, [0, 200], '9');
await pressEscape(page, 3);
await changeNoteDisplayModeWithId(
page,
note3,
NoteDisplayMode.DocAndEdgeless
);
await pressEscape(page);
await assertRichTexts(page, ['3', '5', '6', '7', '9']);
const notes = page.locator('affine-edgeless-note');
await notes.nth(1).dblclick();
await dragBlockToPoint(page, '5', { x: 50, y: 100 });
await waitNextFrame(page);
await assertRichTexts(page, ['3', '5', '6', '7', '9']);
await notes.nth(2).dblclick();
await dragBlockToPoint(page, '7', { x: 50, y: 200 });
await waitNextFrame(page);
await assertRichTexts(page, ['3', '5', '6', '7', '9']);
});