Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(edgeless): add paragraph block when clicking at empty note block #6457

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import type { PointerEventState } from '@blocksuite/block-std';
import { DisposableGroup, noop } from '@blocksuite/global/utils';

import { type EdgelessTool } from '../../../../_common/utils/index.js';
import {
asyncFocusRichText,
type EdgelessTool,
} from '../../../../_common/utils/index.js';
import {
type DefaultTool,
handleNativeRangeAtPoint,
resetNativeSelection,
type Selectable,
} from '../../../../_common/utils/index.js';
import type { FrameBlockModel } from '../../../../frame-block/index.js';
import type { NoteBlockModel } from '../../../../note-block/note-model.js';
import {
GroupElementModel,
ShapeElementModel,
Expand Down Expand Up @@ -130,12 +134,35 @@ export class DefaultToolController extends EdgelessToolController<DefaultTool> {
});
}

private _addEmptyParagraphBlock(note: NoteBlockModel) {
const blockId = this._doc.addBlock(
'affine:paragraph',
{ type: 'text' },
note.id
);
if (blockId) {
asyncFocusRichText(this._edgeless.host, blockId)?.catch(console.error);
}
}

private _handleClickAtNoteBlock(note: NoteBlockModel, e: PointerEventState) {
// check if note has children blocks, if not, add a paragraph block and focus on it
if (note.children.length === 0) {
this._addEmptyParagraphBlock(note);
} else {
handleNativeRangeAtPoint(e.raw.clientX, e.raw.clientY);
}
}

private _handleClickOnSelected(element: EdgelessModel, e: PointerEventState) {
const { selectedIds, selections } = this.selection;
const editing = selections[0]?.editing ?? false;

// click the inner area of active text and note element
if (selectedIds.length === 1 && selectedIds[0] === element.id && editing) {
if (isNoteBlock(element) && element.children.length === 0) {
this._addEmptyParagraphBlock(element);
}
return;
}

Expand All @@ -149,9 +176,9 @@ export class DefaultToolController extends EdgelessToolController<DefaultTool> {
// If the previously selected element is a noteBlock and is in an active state,
// then the currently clicked noteBlock should also be in an active state when selected.
this._setSelectionState([element.id], true);
requestAnimationFrame(() => {
handleNativeRangeAtPoint(e.raw.clientX, e.raw.clientY);
});
this._edgeless.updateComplete
.then(() => this._handleClickAtNoteBlock(element, e))
.catch(console.error);
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,11 @@ export class AffineDragHandleWidget extends WidgetElement<
this.doc.moveBlocks(selectedBlocks, newNoteBlock);
}

edgelessRoot.service.selection.set({
elements: [newNoteBlock.id],
editing: true,
});

return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ export function convertDragPreviewDocToEdgeless({
const blockModel = blockComponent.model;
const blockProps = getBlockProps(blockModel);

edgelessRoot.service.addBlock(
const blockId = edgelessRoot.service.addBlock(
blockComponent.flavour as EdgelessBlockType,
{
...blockProps,
Expand All @@ -427,6 +427,11 @@ export function convertDragPreviewDocToEdgeless({
host.selection.setGroup('note', []);
}

edgelessRoot.service.selection.set({
elements: [blockId],
editing: false,
});

return true;
}

Expand Down
59 changes: 57 additions & 2 deletions tests/edgeless/note.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NoteDisplayMode } from '@blocks/_common/types.js';

Check failure on line 1 in tests/edgeless/note.spec.ts

View workflow job for this annotation

GitHub Actions / Playground E2E test (5)

edgeless/note.spec.ts:88:1 › resize note in edgeless mode

1) edgeless/note.spec.ts:88:1 › resize note in edgeless mode ───────────────────────────────────── Test timeout of 30000ms exceeded.

Check failure on line 1 in tests/edgeless/note.spec.ts

View workflow job for this annotation

GitHub Actions / Playground E2E test (5)

edgeless/note.spec.ts:128:1 › resize note then auto size and custom size

2) edgeless/note.spec.ts:128:1 › resize note then auto size and custom size ────────────────────── Test timeout of 30000ms exceeded.
import { expect } from '@playwright/test';

// eslint-disable-next-line @typescript-eslint/no-restricted-imports
Expand Down Expand Up @@ -363,14 +363,14 @@

await setEdgelessTool(page, 'note');

await page.mouse.click(300, 200);
await page.mouse.click(200, 200);
await focusRichText(page, 3);
await waitNextFrame(page);

// block id 7
await type(page, '000');

await page.mouse.dblclick(CENTER_X, CENTER_Y);
await page.mouse.dblclick(CENTER_X, CENTER_Y - 20);
await dragHandleFromBlockToBlockBottomById(page, '3', '7');
await expect(page.locator('.affine-drag-handle-container')).toBeHidden();
await waitNextFrame(page);
Expand Down Expand Up @@ -939,3 +939,58 @@
// change successfully, there should be 2 notes in doc page
await assertBlockCount(page, 'note', 2);
});

test('Click at empty note should add a paragraph block', async ({ page }) => {
await enterPlaygroundRoom(page);
await initEmptyEdgelessState(page);
await focusRichText(page);
await type(page, '123');
await assertRichTexts(page, ['123']);

await switchEditorMode(page);

// Drag paragraph out of note block
const paragraphBlock = await page
.locator(`[data-block-id="3"]`)
.boundingBox();
assertExists(paragraphBlock);
await page.mouse.dblclick(paragraphBlock.x, paragraphBlock.y);
await waitNextFrame(page);
await page.mouse.move(
paragraphBlock.x + paragraphBlock.width / 2,
paragraphBlock.y + paragraphBlock.height / 2
);
await waitNextFrame(page);
const handle = await page
.locator('.affine-drag-handle-container')
.boundingBox();
assertExists(handle);
await page.mouse.move(
handle.x + handle.width / 2,
handle.y + handle.height / 2,
{ steps: 10 }
);
await page.mouse.down();
await page.mouse.move(100, 200, { steps: 30 });
await page.mouse.up();

// There should be two note blocks and one paragraph block
await assertRichTexts(page, ['123']);
await assertBlockCount(page, 'note', 2);
await assertBlockCount(page, 'paragraph', 1);

// Click at empty note block to add a paragraph block
const emptyNote = await page.locator(`[data-block-id="2"]`).boundingBox();
assertExists(emptyNote);
await page.mouse.click(
emptyNote.x + emptyNote.width / 2,
emptyNote.y + emptyNote.height / 2
);
await waitNextFrame(page, 300);
await type(page, '456');
await waitNextFrame(page, 400);

await page.mouse.click(100, 100);
await waitNextFrame(page, 400);
await assertBlockCount(page, 'paragraph', 2);
});
Loading