mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-06 11:59:51 +08:00
fix(editor): improve backspace ux for callout block (#10696)
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
import { CalloutBlockModel } from '@blocksuite/affine-model';
|
||||||
|
import { matchModels } from '@blocksuite/affine-shared/utils';
|
||||||
|
import {
|
||||||
|
BlockSelection,
|
||||||
|
KeymapExtension,
|
||||||
|
TextSelection,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
|
|
||||||
|
export const CalloutKeymapExtension = KeymapExtension(std => {
|
||||||
|
return {
|
||||||
|
Backspace: ctx => {
|
||||||
|
const text = std.selection.find(TextSelection);
|
||||||
|
if (text && text.isCollapsed() && text.from.index === 0) {
|
||||||
|
const event = ctx.get('defaultState').event;
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const block = std.store.getBlock(text.from.blockId);
|
||||||
|
if (!block) return false;
|
||||||
|
const parent = std.store.getParent(block.model);
|
||||||
|
if (!parent) return false;
|
||||||
|
if (!matchModels(parent, [CalloutBlockModel])) return false;
|
||||||
|
|
||||||
|
std.selection.setGroup('note', [
|
||||||
|
std.selection.create(BlockSelection, {
|
||||||
|
blockId: parent.id,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -3,10 +3,12 @@ import { BlockViewExtension, FlavourExtension } from '@blocksuite/block-std';
|
|||||||
import type { ExtensionType } from '@blocksuite/store';
|
import type { ExtensionType } from '@blocksuite/store';
|
||||||
import { literal } from 'lit/static-html.js';
|
import { literal } from 'lit/static-html.js';
|
||||||
|
|
||||||
|
import { CalloutKeymapExtension } from './callout-keymap';
|
||||||
import { calloutSlashMenuConfig } from './configs/slash-menu';
|
import { calloutSlashMenuConfig } from './configs/slash-menu';
|
||||||
|
|
||||||
export const CalloutBlockSpec: ExtensionType[] = [
|
export const CalloutBlockSpec: ExtensionType[] = [
|
||||||
FlavourExtension('affine:callout'),
|
FlavourExtension('affine:callout'),
|
||||||
BlockViewExtension('affine:callout', literal`affine-callout`),
|
BlockViewExtension('affine:callout', literal`affine-callout`),
|
||||||
|
CalloutKeymapExtension,
|
||||||
SlashMenuConfigExtension('affine:callout', calloutSlashMenuConfig),
|
SlashMenuConfigExtension('affine:callout', calloutSlashMenuConfig),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
AttachmentBlockModel,
|
AttachmentBlockModel,
|
||||||
BookmarkBlockModel,
|
BookmarkBlockModel,
|
||||||
|
CalloutBlockModel,
|
||||||
CodeBlockModel,
|
CodeBlockModel,
|
||||||
DatabaseBlockModel,
|
DatabaseBlockModel,
|
||||||
DividerBlockModel,
|
DividerBlockModel,
|
||||||
@@ -53,8 +54,18 @@ export function mergeWithPrev(editorHost: EditorHost, model: BlockModel) {
|
|||||||
return handleNoPreviousSibling(editorHost, model);
|
return handleNoPreviousSibling(editorHost, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const modelIndex = parent.children.indexOf(model);
|
||||||
|
const prevSibling = doc.getPrev(model);
|
||||||
|
if (matchModels(prevSibling, [CalloutBlockModel])) {
|
||||||
|
editorHost.selection.setGroup('note', [
|
||||||
|
editorHost.selection.create(BlockSelection, {
|
||||||
|
blockId: prevSibling.id,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (matchModels(prevBlock, [ParagraphBlockModel, ListBlockModel])) {
|
if (matchModels(prevBlock, [ParagraphBlockModel, ListBlockModel])) {
|
||||||
const modelIndex = parent.children.indexOf(model);
|
|
||||||
if (
|
if (
|
||||||
(modelIndex === -1 || modelIndex === parent.children.length - 1) &&
|
(modelIndex === -1 || modelIndex === parent.children.length - 1) &&
|
||||||
parent.role === 'content'
|
parent.role === 'content'
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { undoByKeyboard } from '@affine-test/kit/utils/keyboard';
|
import {
|
||||||
|
pressArrowDown,
|
||||||
|
pressArrowUp,
|
||||||
|
pressBackspace,
|
||||||
|
pressEnter,
|
||||||
|
undoByKeyboard,
|
||||||
|
} from '@affine-test/kit/utils/keyboard';
|
||||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||||
import { type } from '@affine-test/kit/utils/page-logic';
|
import { type } from '@affine-test/kit/utils/page-logic';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
@@ -60,3 +66,41 @@ test('disable slash menu in callout block', async ({ page }) => {
|
|||||||
await type(page, '/');
|
await type(page, '/');
|
||||||
await expect(slashMenu).toBeVisible();
|
await expect(slashMenu).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('press backspace after callout block', async ({ page }) => {
|
||||||
|
await pressEnter(page);
|
||||||
|
await pressArrowUp(page);
|
||||||
|
await type(page, '/callout\n');
|
||||||
|
await pressArrowDown(page);
|
||||||
|
|
||||||
|
const paragraph = page.locator('affine-paragraph');
|
||||||
|
const callout = page.locator('affine-callout');
|
||||||
|
expect(await paragraph.count()).toBe(3);
|
||||||
|
expect(await callout.count()).toBe(1);
|
||||||
|
|
||||||
|
await pressBackspace(page);
|
||||||
|
expect(await paragraph.count()).toBe(3);
|
||||||
|
expect(await callout.count()).toBe(1);
|
||||||
|
|
||||||
|
await pressBackspace(page);
|
||||||
|
await expect(paragraph).toHaveCount(2);
|
||||||
|
await expect(callout).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('press backspace in callout block', async ({ page }) => {
|
||||||
|
const paragraph = page.locator('affine-paragraph');
|
||||||
|
const callout = page.locator('affine-callout');
|
||||||
|
|
||||||
|
await type(page, '/callout\n');
|
||||||
|
|
||||||
|
expect(await paragraph.count()).toBe(2);
|
||||||
|
expect(await callout.count()).toBe(1);
|
||||||
|
|
||||||
|
await pressBackspace(page);
|
||||||
|
await expect(paragraph).toHaveCount(2);
|
||||||
|
await expect(callout).toHaveCount(1);
|
||||||
|
|
||||||
|
await pressBackspace(page);
|
||||||
|
await expect(paragraph).toHaveCount(1);
|
||||||
|
await expect(callout).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ export async function pressArrowUp(page: Page, count = 1) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function pressArrowDown(page: Page, count = 1) {
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
await page.keyboard.press('ArrowDown', { delay: 20 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function pressTab(page: Page) {
|
export async function pressTab(page: Page) {
|
||||||
await page.keyboard.press('Tab', { delay: 50 });
|
await page.keyboard.press('Tab', { delay: 50 });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user