mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-11 07:06:28 +08:00
fix(editor): hide collpased content during dragging note (#10133)
Close [BS-2531](https://linear.app/affine-design/issue/BS-2531/%E6%8B%96%E5%8A%A8%E6%8A%98%E5%8F%A0%E7%9A%84note%E6%97%B6%EF%BC%8C%E4%B8%8D%E6%98%BE%E7%A4%BA%E9%9A%90%E8%97%8F%E5%86%85%E5%AE%B9), [BS-2536](https://linear.app/affine-design/issue/BS-2536/page-block%E9%A1%B6%E9%83%A8toolbar)
This commit is contained in:
@@ -26,12 +26,13 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
|
||||
return (
|
||||
this.model.edgeless.collapse &&
|
||||
this.gfx.selection.has(this.model.id) &&
|
||||
!this._dragging &&
|
||||
(this._isResizing || this._isHover)
|
||||
);
|
||||
}
|
||||
|
||||
get _zoom() {
|
||||
return this.gfx.viewport.zoom;
|
||||
private get _dragging() {
|
||||
return this._isHover && this.gfx.tool.dragging$.value;
|
||||
}
|
||||
|
||||
private _collapsedContent() {
|
||||
@@ -236,6 +237,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
|
||||
></edgeless-note-background>
|
||||
|
||||
<div
|
||||
data-testid="edgeless-note-clip-container"
|
||||
class=${styles.clipContainer}
|
||||
style=${styleMap({
|
||||
'overflow-y': this._isShowCollapsedContent ? 'initial' : 'clip',
|
||||
|
||||
+1
@@ -28,6 +28,7 @@ const buttonPadding = 4;
|
||||
export const button = style({
|
||||
padding: buttonPadding,
|
||||
pointerEvents: 'auto',
|
||||
color: cssVarV2('icon/transparentBlack'),
|
||||
});
|
||||
|
||||
export const headerHeight = 2 * headerPadding + iconSize + 2 * buttonPadding;
|
||||
|
||||
@@ -5,14 +5,19 @@ import {
|
||||
createEdgelessNoteBlock,
|
||||
getEdgelessSelectedIds,
|
||||
getPageMode,
|
||||
getSelectedXYWH,
|
||||
locateEditorContainer,
|
||||
locateElementToolbar,
|
||||
locateModeSwitchButton,
|
||||
moveToView,
|
||||
resizeElementByHandle,
|
||||
toViewCoord,
|
||||
} from '@affine-test/kit/utils/editor';
|
||||
import {
|
||||
pasteByKeyboard,
|
||||
pressBackspace,
|
||||
pressEnter,
|
||||
pressEscape,
|
||||
selectAllByKeyboard,
|
||||
undoByKeyboard,
|
||||
} from '@affine-test/kit/utils/keyboard';
|
||||
@@ -27,6 +32,7 @@ import type {
|
||||
EdgelessRootBlockComponent,
|
||||
NoteBlockModel,
|
||||
} from '@blocksuite/blocks';
|
||||
import type { IVec } from '@blocksuite/global/utils';
|
||||
import { expect, type Page } from '@playwright/test';
|
||||
|
||||
const title = 'Edgeless Note Header Test';
|
||||
@@ -370,3 +376,54 @@ test.describe('edgeless note element toolbar', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('note block rendering', () => {
|
||||
test('collapsed content rendering', async ({ page }) => {
|
||||
await createEdgelessNoteBlock(page, [50, 50]);
|
||||
|
||||
await type(page, 'paragraph 1');
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await pressEnter(page);
|
||||
}
|
||||
await type(page, 'paragraph 2');
|
||||
await pressEscape(page, 3);
|
||||
await clickView(page, [50, 50]);
|
||||
await resizeElementByHandle(page, [0, -50], 'bottom-right');
|
||||
const xywh = await getSelectedXYWH(page);
|
||||
const center: IVec = [xywh[0] + xywh[2] / 2, xywh[1] + xywh[3] / 2];
|
||||
|
||||
const note = page
|
||||
.locator('affine-edgeless-note')
|
||||
.getByTestId('edgeless-note-clip-container')
|
||||
.nth(1);
|
||||
|
||||
await expect(note, 'should hide collapsed content').toHaveCSS(
|
||||
'overflow-y',
|
||||
'clip'
|
||||
);
|
||||
await moveToView(page, center);
|
||||
await expect(note, 'should show collapsed content when hover').toHaveCSS(
|
||||
'overflow-y',
|
||||
'visible'
|
||||
);
|
||||
|
||||
const [x1, y1] = await toViewCoord(page, center);
|
||||
const [x2, y2] = await toViewCoord(page, [center[0], center[1] + 25]);
|
||||
const [x3, y3] = await toViewCoord(page, [center[0], center[1] + 50]);
|
||||
await page.mouse.move(x1, y1);
|
||||
await page.mouse.down();
|
||||
|
||||
await page.mouse.move(x2, y2, { steps: 10 });
|
||||
await expect(
|
||||
note,
|
||||
'should hide collapsed content during dragging'
|
||||
).toHaveCSS('overflow-y', 'clip');
|
||||
await page.mouse.move(x3, y3, { steps: 10 });
|
||||
await page.mouse.up();
|
||||
await page.mouse.move(x3, y3);
|
||||
await expect(
|
||||
note,
|
||||
'should show collapsed content when dragging is finished'
|
||||
).toHaveCSS('overflow-y', 'visible');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -82,6 +82,22 @@ export async function getEdgelessSelectedIds(page: Page, editorIndex = 0) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function getSelectedXYWH(
|
||||
page: Page,
|
||||
index = 0,
|
||||
editorIndex = 0
|
||||
): Promise<[number, number, number, number]> {
|
||||
const container = locateEditorContainer(page, editorIndex);
|
||||
return container.evaluate((container, index) => {
|
||||
const root = container.querySelector('affine-edgeless-root');
|
||||
if (!root) {
|
||||
throw new Error('Edgeless root not found');
|
||||
}
|
||||
const selected = root.service.selection.selectedElements[index];
|
||||
return selected.elementBound.toXYWH();
|
||||
}, index);
|
||||
}
|
||||
|
||||
export async function getViewportCenter(page: Page, editorIndex = 0) {
|
||||
const container = locateEditorContainer(page, editorIndex);
|
||||
return container.evaluate((container: AffineEditorContainer) => {
|
||||
@@ -108,6 +124,17 @@ export async function setViewportCenter(
|
||||
}, center);
|
||||
}
|
||||
|
||||
export async function setViewportZoom(page: Page, zoom = 1, editorIndex = 0) {
|
||||
const container = locateEditorContainer(page, editorIndex);
|
||||
return container.evaluate((container: AffineEditorContainer, zoom) => {
|
||||
const root = container.querySelector('affine-edgeless-root');
|
||||
if (!root) {
|
||||
throw new Error('Edgeless root not found');
|
||||
}
|
||||
root.gfx.viewport.setZoom(zoom);
|
||||
}, zoom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a canvas point to view coordinate
|
||||
* @param point the coordinate on the canvas
|
||||
@@ -119,10 +146,36 @@ export async function toViewCoord(page: Page, point: IVec, editorIndex = 0) {
|
||||
if (!root) {
|
||||
throw new Error('Edgeless root not found');
|
||||
}
|
||||
return root.gfx.viewport.toViewCoord(point[0], point[1]);
|
||||
const coord = root.gfx.viewport.toViewCoord(point[0], point[1]);
|
||||
coord[0] += root.gfx.viewport.left;
|
||||
coord[1] += root.gfx.viewport.top;
|
||||
return coord;
|
||||
}, point);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a view coordinate to canvas point
|
||||
* @param point the coordinate on the view
|
||||
*/
|
||||
export async function toModelCoord(page: Page, point: IVec, editorIndex = 0) {
|
||||
const container = locateEditorContainer(page, editorIndex);
|
||||
return container.evaluate((container: AffineEditorContainer, point) => {
|
||||
const root = container.querySelector('affine-edgeless-root');
|
||||
if (!root) {
|
||||
throw new Error('Edgeless root not found');
|
||||
}
|
||||
return root.gfx.viewport.toModelCoordFromClientCoord(point);
|
||||
}, point);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to a point on the canvas
|
||||
*/
|
||||
export async function moveToView(page: Page, point: IVec, editorIndex = 0) {
|
||||
const [x, y] = await toViewCoord(page, point, editorIndex);
|
||||
await page.mouse.move(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click a point on the canvas
|
||||
* @param point the coordinate on the canvas
|
||||
@@ -331,6 +384,28 @@ export async function setEdgelessTool(
|
||||
}
|
||||
}
|
||||
|
||||
export async function resizeElementByHandle(
|
||||
page: Page,
|
||||
delta: IVec,
|
||||
corner:
|
||||
| 'top-left'
|
||||
| 'top-right'
|
||||
| 'bottom-right'
|
||||
| 'bottom-left' = 'top-left',
|
||||
editorIndex = 0
|
||||
) {
|
||||
const handle = page.locator(`.handle[aria-label="${corner}"] .resize`);
|
||||
const box = await handle.boundingBox();
|
||||
if (box === null) throw new Error();
|
||||
const from = await toModelCoord(
|
||||
page,
|
||||
[box.x + box.width / 2, box.y + box.height / 2],
|
||||
editorIndex
|
||||
);
|
||||
const to: IVec = [from[0] + delta[0], from[1] + delta[1]];
|
||||
await dragView(page, from, to, editorIndex);
|
||||
}
|
||||
|
||||
export function locateElementToolbar(page: Page, editorIndex = 0) {
|
||||
return locateEditorContainer(page, editorIndex).locator(
|
||||
EDGELESS_ELEMENT_TOOLBAR_WIDGET
|
||||
|
||||
Reference in New Issue
Block a user