From 854569af2dc3dfefd75ddc2d2bb8c99b356e5c3a Mon Sep 17 00:00:00 2001 From: Saul-Mirone Date: Mon, 7 Apr 2025 01:12:28 +0000 Subject: [PATCH] refactor(editor): remove lasso tool (#11481) --- .../components/toolbar/lasso/icons.ts | 71 ---- .../toolbar/lasso/lasso-dense-menu.ts | 41 --- .../toolbar/lasso/lasso-tool-button.ts | 99 ------ .../src/edgeless/edgeless-builtin-spec.ts | 2 - .../src/edgeless/edgeless-keyboard.ts | 42 --- .../block-root/src/edgeless/gfx-tool/index.ts | 1 - .../src/edgeless/gfx-tool/lasso-tool.ts | 326 ------------------ .../block-root/src/edgeless/utils/query.ts | 1 - .../affine/blocks/block-root/src/effects.ts | 3 - .../src/services/feature-flag-service.ts | 2 - blocksuite/affine/shared/src/types/index.ts | 5 - tests/blocksuite/e2e/edgeless/lasso.spec.ts | 262 -------------- tests/blocksuite/e2e/edgeless/lock.spec.ts | 2 +- .../blocksuite/e2e/edgeless/shortcut.spec.ts | 27 -- .../blocksuite/e2e/utils/actions/edgeless.ts | 24 +- tests/kit/src/utils/editor.ts | 5 +- 16 files changed, 3 insertions(+), 910 deletions(-) delete mode 100644 blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/icons.ts delete mode 100644 blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-dense-menu.ts delete mode 100644 blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-tool-button.ts delete mode 100644 blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/lasso-tool.ts delete mode 100644 tests/blocksuite/e2e/edgeless/lasso.spec.ts diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/icons.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/icons.ts deleted file mode 100644 index 0881074304..0000000000 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/icons.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { html } from 'lit'; - -export const LassoFreeHandIcon = html` - - - - - - -`; - -export const LassoPolygonalIcon = html` - - - - - - -`; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-dense-menu.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-dense-menu.ts deleted file mode 100644 index ca82117540..0000000000 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-dense-menu.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { menu } from '@blocksuite/affine-components/context-menu'; -import { LassoMode } from '@blocksuite/affine-shared/types'; -import type { DenseMenuBuilder } from '@blocksuite/affine-widget-edgeless-toolbar'; - -import { LassoFreeHandIcon, LassoPolygonalIcon } from './icons.js'; - -export const buildLassoDenseMenu: DenseMenuBuilder = (_, gfx) => { - // TODO: active state - // const prevMode = - // edgeless.service.editPropsStore.getLastProps('lasso').mode ?? - // LassoMode.FreeHand; - - const isActive = gfx.tool.currentToolName$.peek() === 'lasso'; - - const createSelect = (mode: LassoMode) => () => { - gfx.tool.setTool('lasso', { mode }); - }; - - return menu.subMenu({ - name: 'Lasso', - prefix: LassoFreeHandIcon, - select: createSelect(LassoMode.FreeHand), - isSelected: isActive, - options: { - items: [ - menu.action({ - prefix: LassoFreeHandIcon, - name: 'Free', - select: createSelect(LassoMode.FreeHand), - // isSelected: isActive && prevMode === LassoMode.FreeHand, - }), - menu.action({ - prefix: LassoPolygonalIcon, - name: 'Polygonal', - select: createSelect(LassoMode.Polygonal), - // isSelected: isActive && prevMode === LassoMode.Polygonal, - }), - ], - }, - }); -}; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-tool-button.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-tool-button.ts deleted file mode 100644 index 76a673b3d7..0000000000 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/lasso/lasso-tool-button.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { LassoMode } from '@blocksuite/affine-shared/types'; -import { QuickToolMixin } from '@blocksuite/affine-widget-edgeless-toolbar'; -import { WithDisposable } from '@blocksuite/global/lit'; -import { effect } from '@preact/signals-core'; -import { css, html, LitElement } from 'lit'; -import { query, state } from 'lit/decorators.js'; - -import { LassoFreeHandIcon, LassoPolygonalIcon } from './icons.js'; - -export class EdgelessLassoToolButton extends QuickToolMixin( - WithDisposable(LitElement) -) { - static override styles = css` - .current-icon { - transition: 100ms; - width: 24px; - height: 24px; - } - .current-icon > svg { - display: block; - } - `; - - private readonly _changeTool = () => { - const tool = this.edgelessTool; - if (tool.type !== 'lasso') { - this.setEdgelessTool({ type: 'lasso', mode: this.curMode }); - return; - } - - this._fadeOut(); - setTimeout(() => { - this.curMode === LassoMode.FreeHand - ? this.setEdgelessTool({ type: 'lasso', mode: LassoMode.Polygonal }) - : this.setEdgelessTool({ type: 'lasso', mode: LassoMode.FreeHand }); - this._fadeIn(); - }, 100); - }; - - override type = 'lasso' as const; - - private _fadeIn() { - this.currentIcon.style.opacity = '1'; - this.currentIcon.style.transform = `translateY(0px)`; - } - - private _fadeOut() { - this.currentIcon.style.opacity = '0'; - this.currentIcon.style.transform = `translateY(-5px)`; - } - - override connectedCallback(): void { - super.connectedCallback(); - - this.disposables.add( - effect(() => { - const tool = this.gfx.tool.currentToolOption$.value; - - if (tool?.type === 'lasso') { - const { mode } = tool; - this.curMode = mode; - } - }) - ); - } - - override render() { - const type = this.edgelessTool?.type; - const mode = this.curMode === LassoMode.FreeHand ? 'freehand' : 'polygonal'; - - return html` - `} - .tooltipOffset=${17} - .active=${type === 'lasso'} - .iconContainerPadding=${6} - .iconSize=${'24px'} - @click=${this._changeTool} - > - - ${this.curMode === LassoMode.FreeHand - ? LassoFreeHandIcon - : LassoPolygonalIcon} - - - - `; - } - - @state() - accessor curMode: LassoMode = LassoMode.FreeHand; - - @query('.current-icon') - accessor currentIcon!: HTMLInputElement; -} diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts index aa3613559a..90b8ed768f 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts @@ -29,7 +29,6 @@ import { DblClickAddEdgelessText } from './element-transform/dblclick-add-edgele import { SnapExtension } from './element-transform/snap-manager.js'; import { DefaultTool } from './gfx-tool/default-tool.js'; import { EmptyTool } from './gfx-tool/empty-tool.js'; -import { LassoTool } from './gfx-tool/lasso-tool.js'; import { PanTool } from './gfx-tool/pan-tool.js'; import { TemplateTool } from './gfx-tool/template-tool.js'; import { EditPropsMiddlewareBuilder } from './middlewares/base.js'; @@ -47,7 +46,6 @@ export const EdgelessToolExtension: ExtensionType[] = [ TemplateTool, EmptyTool, FrameTool, - LassoTool, PresentTool, HighlighterTool, ]; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts index 4a7dc143c0..1df0ce912d 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts @@ -26,10 +26,8 @@ import { } from '@blocksuite/affine-model'; import { EditPropsStore, - FeatureFlagService, TelemetryProvider, } from '@blocksuite/affine-shared/services'; -import { LassoMode } from '@blocksuite/affine-shared/types'; import { matchModels } from '@blocksuite/affine-shared/utils'; import { IS_MAC } from '@blocksuite/global/env'; import { Bound, getCommonBound } from '@blocksuite/global/gfx'; @@ -44,7 +42,6 @@ import { import { PageKeyboardManager } from '../keyboard/keyboard-manager.js'; import type { EdgelessRootBlockComponent } from './edgeless-root-block.js'; -import { LassoTool } from './gfx-tool/lasso-tool.js'; import { DEFAULT_NOTE_CHILD_FLAVOUR, DEFAULT_NOTE_CHILD_TYPE, @@ -76,40 +73,6 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { }); this._setEdgelessTool('connector', { mode }); }, - l: () => { - if ( - !rootComponent.doc - .get(FeatureFlagService) - .getFlag('enable_lasso_tool') - ) { - return; - } - - this._setEdgelessTool('lasso', { - mode: LassoMode.Polygonal, - }); - }, - 'Shift-l': () => { - if ( - !rootComponent.doc - .get(FeatureFlagService) - .getFlag('enable_lasso_tool') - ) { - return; - } - // toggle between lasso modes - const edgeless = rootComponent; - const cur = edgeless.gfx.tool.currentTool$.peek(); - - this._setEdgelessTool('lasso', { - mode: - cur?.toolName === 'lasso' - ? (cur as LassoTool).activatedOption.mode === LassoMode.FreeHand - ? LassoMode.Polygonal - : LassoMode.FreeHand - : LassoMode.FreeHand, - }); - }, h: () => { this._setEdgelessTool('pan', { panning: false, @@ -324,11 +287,6 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { this._delete(); }, Escape: () => { - const currentTool = this.rootComponent.gfx.tool.currentTool$.peek(); - if (currentTool instanceof LassoTool && currentTool.isSelecting) { - currentTool.abort(); - } - if (!this.rootComponent.service.selection.empty) { rootComponent.selection.clear(); } diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts index b703333308..54c30e114a 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts @@ -1,5 +1,4 @@ export { DefaultTool } from './default-tool.js'; export { EmptyTool } from './empty-tool.js'; -export { LassoTool, type LassoToolOption } from './lasso-tool.js'; export { PanTool, type PanToolOption } from './pan-tool.js'; export { TemplateTool } from './template-tool.js'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/lasso-tool.ts b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/lasso-tool.ts deleted file mode 100644 index 3d1658d3ec..0000000000 --- a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/lasso-tool.ts +++ /dev/null @@ -1,326 +0,0 @@ -import { - Overlay, - type SurfaceBlockComponent, -} from '@blocksuite/affine-block-surface'; -import { ThemeProvider } from '@blocksuite/affine-shared/services'; -import { LassoMode } from '@blocksuite/affine-shared/types'; -import type { IPoint, IVec } from '@blocksuite/global/gfx'; -import { - Bound, - getBoundFromPoints, - getPolygonPathFromPoints, - getSvgPathFromStroke, - linePolygonIntersects, - pointInPolygon, - rotatePoints, - Vec, -} from '@blocksuite/global/gfx'; -import type { PointerEventState } from '@blocksuite/std'; -import { BaseTool } from '@blocksuite/std/gfx'; - -class LassoOverlay extends Overlay { - d = ''; - - startPoint: IVec | null = null; - - render(ctx: CanvasRenderingContext2D): void { - const path = new Path2D(this.d); - const zoom = this._renderer?.viewport.zoom ?? 1.0; - ctx.save(); - const primaryColor = this.gfx.std - .get(ThemeProvider) - .getCssVariableColor('--affine-primary-color'); - const strokeColor = this.gfx.std - .get(ThemeProvider) - .getCssVariableColor('--affine-secondary-color'); - if (this.startPoint) { - const [x, y] = this.startPoint; - ctx.beginPath(); - ctx.arc(x, y, 2 / zoom, 0, Math.PI * 2); - ctx.fillStyle = primaryColor; - ctx.fill(); - } - - ctx.strokeStyle = strokeColor; - ctx.fillStyle = 'rgba(255, 255, 255, 0.1)'; - ctx.lineWidth = 2 / zoom; - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - ctx.setLineDash([2, 5]); - ctx.fill(path); - ctx.stroke(path); - ctx.restore(); - } -} - -export type LassoToolOption = { - mode: LassoMode; -}; -export class LassoTool extends BaseTool { - static override toolName: string = 'lasso'; - - private _currentSelectionState = new Set(); - - private _isSelecting = false; - - private _lassoPoints: IVec[] = []; - - private _lastPoint: IVec = [0, 0]; - - private readonly _loop = () => { - const path = - this.activatedOption.mode === LassoMode.FreeHand - ? getSvgPathFromStroke(this._lassoPoints) - : getPolygonPathFromPoints(this._lassoPoints); - - this._overlay.d = path; - (this.gfx.surfaceComponent as SurfaceBlockComponent)?.refresh?.(); - this._raf = requestAnimationFrame(this._loop); - }; - - private readonly _overlay = new LassoOverlay(this.gfx); - - private _raf = 0; - - get isSelecting() { - return this._isSelecting; - } - - get selection() { - return this.gfx.selection; - } - - get surfaceComponent() { - return this.gfx.surfaceComponent as SurfaceBlockComponent; - } - - private _clearLastSelection() { - if (this.selection.empty) { - this.selection.clearLast(); - } - } - - private _getElementsInsideLasso() { - const lassoBounds = getBoundFromPoints(this._lassoPoints); - return this.gfx - .getElementsByBound(lassoBounds) - .filter(e => - this.isInsideLassoSelection(Bound.deserialize(e.xywh), e.rotate) - ); - } - - private _getSelectionMode(ev: PointerEventState): 'add' | 'sub' | 'set' { - const shiftKey = ev.keys.shift ?? this.gfx.keyboard.shiftKey$.peek(); - const altKey = ev.keys.alt ?? false; - if (shiftKey) return 'add'; - else if (altKey) return 'sub'; - else { - return 'set'; - } - } - - private _reset() { - cancelAnimationFrame(this._raf); - ( - this.gfx.surfaceComponent as SurfaceBlockComponent - )?.renderer.removeOverlay(this._overlay); - this._overlay.d = ''; - this._overlay.startPoint = null; - - const elements = this._getElementsInsideLasso(); - - this._currentSelectionState = new Set([ - ...Array.from(this._currentSelectionState), - ...elements.map(el => el.id), - ]); - - this._lassoPoints = []; - this._isSelecting = false; - } - - private _setSelectionState(elements: string[], editing: boolean) { - this.selection.set({ - elements, - editing, - }); - } - - private _updateSelection(e: PointerEventState) { - // elements inside the lasso selection - const elements = this._getElementsInsideLasso() - .filter(el => !el.isLocked()) - .map(el => el.id); - - // current selections - const selection = this.selection.selectedElements.map(el => el.id); - - const selectionMode = this._getSelectionMode(e); - let set!: Set; - switch (selectionMode) { - case 'add': - set = new Set([ - ...elements, - ...selection.filter(elId => this._currentSelectionState.has(elId)), - ]); - break; - case 'sub': { - const toRemove = new Set(elements); - set = new Set( - Array.from(this._currentSelectionState).filter( - el => !toRemove.has(el) - ) - ); - break; - } - case 'set': - set = new Set(elements); - break; - } - - this._setSelectionState(Array.from(set), false); - } - - private isInsideLassoSelection(bound: Bound, rotate: number): boolean { - const { points, center } = bound; - - const firstPoint = this._lassoPoints[0]; - const lassoPoints = this._lassoPoints.concat( - firstPoint ? [firstPoint] : [] - ); - - const elPoly = rotatePoints(points, center, rotate); - const lassoLen = lassoPoints.length; - return ( - elPoly.some(point => pointInPolygon(point, lassoPoints)) || - lassoPoints.some((point, i, points) => { - return linePolygonIntersects(point, points[(i + 1) % lassoLen], elPoly); - }) - ); - } - - private toModelCoord(p: IPoint): IVec { - return this.gfx.viewport.toModelCoord(p.x, p.y); - } - - abort() { - this._reset(); - } - - override activate(): void { - this._currentSelectionState = new Set( - this.selection.selectedElements.map(el => el.id) - ); - this._reset(); - } - - override deactivate() { - this._clearLastSelection(); - } - - override dragEnd(e: PointerEventState): void { - if (this.activatedOption.mode !== LassoMode.FreeHand) return; - - this._updateSelection(e); - - this._reset(); - } - - override dragMove(e: PointerEventState): void { - if (this.activatedOption.mode !== LassoMode.FreeHand) return; - - const { point } = e; - const [x, y] = this.toModelCoord(point); - this._lassoPoints.push([x, y]); - - this._updateSelection(e); - } - - // For Freehand Mode = - override dragStart(e: PointerEventState): void { - if (this.activatedOption.mode !== LassoMode.FreeHand) return; - const { alt, shift } = e.keys; - - if (!shift && !alt) { - this._currentSelectionState.clear(); - this.selection.clear(); - } - - this._currentSelectionState = new Set( - this.selection.selectedElements.map(el => el.id) - ); - - this._isSelecting = true; - - const { point } = e; - const [x, y] = this.toModelCoord(point); - this._lassoPoints = [[x, y]]; - this._raf = requestAnimationFrame(this._loop); - this._overlay.startPoint = this._lassoPoints[0]; - this.surfaceComponent.renderer.addOverlay(this._overlay); - } - - override pointerDown(e: PointerEventState): void { - const { mode } = this.activatedOption; - if (mode !== LassoMode.Polygonal) return; - - const { alt, shift } = e.keys; - if (!shift && !alt) { - this._currentSelectionState.clear(); - this.selection.clear(); - } - - this._isSelecting = true; - - const { point } = e; - const [x, y] = this.toModelCoord(point); - if (this._lassoPoints.length < 2) { - this._currentSelectionState = new Set( - this.selection.selectedElements.map(el => el.id) - ); - - const a: IVec = [x, y]; - const b: IVec = [x, y]; - this._lassoPoints = [a, b]; - this._lastPoint = b; - this._overlay.startPoint = a; - this._raf = requestAnimationFrame(this._loop); - this.surfaceComponent.renderer.addOverlay(this._overlay); - } else { - const firstPoint = this._lassoPoints[0]; - const lastPoint = this._lastPoint; - const dx = lastPoint[0] - firstPoint[0]; - const dy = lastPoint[1] - firstPoint[1]; - if (Vec.len2([dx, dy]) < 20 ** 2) { - this._updateSelection(e); - - return this._reset(); - } - - this._lastPoint = [x, y]; - this._lassoPoints.push(this._lastPoint); - } - } - - override pointerMove(e: PointerEventState): void { - if (this.activatedOption.mode !== LassoMode.Polygonal || !this._isSelecting) - return; - - const lastPoint = this._lastPoint; - const [x, y] = this.toModelCoord(e.point); - if (lastPoint) { - lastPoint[0] = x; - lastPoint[1] = y; - } - this._updateSelection(e); - } -} - -declare module '@blocksuite/std/gfx' { - interface GfxToolsMap { - lasso: LassoTool; - } - - interface GfxToolsOption { - lasso: LassoToolOption; - } -} diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts b/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts index 357bc696f5..f5b750c5e5 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts @@ -222,7 +222,6 @@ export function getCursorMode(edgelessTool: GfxToolsFullOptionValue | null) { case 'shape': case 'connector': case 'frame': - case 'lasso': return 'crosshair'; case 'text': return 'text'; diff --git a/blocksuite/affine/blocks/block-root/src/effects.ts b/blocksuite/affine/blocks/block-root/src/effects.ts index f5c9eb20cd..b1275d763f 100644 --- a/blocksuite/affine/blocks/block-root/src/effects.ts +++ b/blocksuite/affine/blocks/block-root/src/effects.ts @@ -25,7 +25,6 @@ import { import { EdgelessSlideMenu } from './edgeless/components/toolbar/common/slide-menu.js'; import { ToolbarArrowUpIcon } from './edgeless/components/toolbar/common/toolbar-arrow-up-icon.js'; import { EdgelessDefaultToolButton } from './edgeless/components/toolbar/default/default-tool-button.js'; -import { EdgelessLassoToolButton } from './edgeless/components/toolbar/lasso/lasso-tool-button.js'; import { EdgelessLinkToolButton } from './edgeless/components/toolbar/link/link-tool-button.js'; import { AffineModalWidget, @@ -121,7 +120,6 @@ function registerEdgelessToolbarComponents() { EdgelessDefaultToolButton ); customElements.define('edgeless-link-tool-button', EdgelessLinkToolButton); - customElements.define('edgeless-lasso-tool-button', EdgelessLassoToolButton); // Menus customElements.define('edgeless-slide-menu', EdgelessSlideMenu); @@ -181,7 +179,6 @@ declare global { 'edgeless-slide-menu': EdgelessSlideMenu; 'toolbar-arrow-up-icon': ToolbarArrowUpIcon; 'edgeless-default-tool-button': EdgelessDefaultToolButton; - 'edgeless-lasso-tool-button': EdgelessLassoToolButton; 'edgeless-link-tool-button': EdgelessLinkToolButton; 'affine-page-root': PageRootBlockComponent; 'zoom-bar-toggle-button': ZoomBarToggleButton; diff --git a/blocksuite/affine/shared/src/services/feature-flag-service.ts b/blocksuite/affine/shared/src/services/feature-flag-service.ts index ed72544ece..075092141a 100644 --- a/blocksuite/affine/shared/src/services/feature-flag-service.ts +++ b/blocksuite/affine/shared/src/services/feature-flag-service.ts @@ -6,7 +6,6 @@ export interface BlockSuiteFlags { enable_database_attachment_note: boolean; enable_database_full_width: boolean; enable_block_query: boolean; - enable_lasso_tool: boolean; enable_edgeless_text: boolean; enable_ai_onboarding: boolean; enable_ai_chat_block: boolean; @@ -29,7 +28,6 @@ export class FeatureFlagService extends StoreExtension { enable_database_attachment_note: false, enable_database_full_width: false, enable_block_query: false, - enable_lasso_tool: false, enable_edgeless_text: true, enable_ai_onboarding: true, enable_ai_chat_block: true, diff --git a/blocksuite/affine/shared/src/types/index.ts b/blocksuite/affine/shared/src/types/index.ts index 996b7edb89..b52238fc7b 100644 --- a/blocksuite/affine/shared/src/types/index.ts +++ b/blocksuite/affine/shared/src/types/index.ts @@ -13,11 +13,6 @@ export interface EditingState { rect: DOMRect; } -export enum LassoMode { - FreeHand, - Polygonal, -} - export type NoteChildrenFlavour = | 'affine:paragraph' | 'affine:list' diff --git a/tests/blocksuite/e2e/edgeless/lasso.spec.ts b/tests/blocksuite/e2e/edgeless/lasso.spec.ts deleted file mode 100644 index 4f19aae0d7..0000000000 --- a/tests/blocksuite/e2e/edgeless/lasso.spec.ts +++ /dev/null @@ -1,262 +0,0 @@ -import { sleep } from '@blocksuite/global/utils'; -import { expect } from '@playwright/test'; - -import { - addBasicRectShapeElement, - assertEdgelessTool, - edgelessCommonSetup as commonSetup, - setEdgelessTool, -} from '../utils/actions/edgeless.js'; -import { - dragBetweenCoords, - selectAllByKeyboard, -} from '../utils/actions/index.js'; -import { - assertEdgelessNonSelectedRect, - assertEdgelessSelectedRect, -} from '../utils/asserts.js'; -import { test } from '../utils/playwright.js'; - -test.skip('lasso tool should deselect when dragging in an empty area', async ({ - page, -}) => { - await commonSetup(page); - - const start = { x: 100, y: 100 }; - const end = { x: 200, y: 200 }; - await addBasicRectShapeElement(page, start, end); - await assertEdgelessSelectedRect(page, [100, 100, 100, 100]); - - await setEdgelessTool(page, 'lasso'); - await assertEdgelessTool(page, 'lasso'); - - await dragBetweenCoords(page, { x: 10, y: 10 }, { x: 15, y: 15 }); - - await assertEdgelessNonSelectedRect(page); -}); - -test.skip('freehand lasso basic test', async ({ page }) => { - await commonSetup(page); - - await addBasicRectShapeElement(page, { x: 100, y: 100 }, { x: 200, y: 200 }); - await addBasicRectShapeElement(page, { x: 300, y: 300 }, { x: 400, y: 400 }); - - await page.mouse.click(10, 10); // deselect - - await setEdgelessTool(page, 'lasso'); - await assertEdgelessTool(page, 'lasso'); - - await assertEdgelessNonSelectedRect(page); - - // simulate a basic lasso selection to select both the rects - const points: [number, number][] = [ - [500, 100], - [500, 500], - [90, 500], - ]; - await page.mouse.move(90, 90); - await page.mouse.down(); - for (const point of points) await page.mouse.move(...point); - await page.mouse.up(); - - await assertEdgelessSelectedRect(page, [100, 100, 200, 200]); -}); - -test.skip('freehand lasso add to selection', async ({ page }) => { - await commonSetup(page); - - await addBasicRectShapeElement(page, { x: 100, y: 100 }, { x: 200, y: 200 }); - await addBasicRectShapeElement(page, { x: 300, y: 300 }, { x: 400, y: 400 }); - - await page.mouse.click(10, 10); // deselect - - await setEdgelessTool(page, 'lasso'); - await assertEdgelessTool(page, 'lasso'); - await assertEdgelessNonSelectedRect(page); - - // some random selection covering the rectangle - let points: [number, number][] = [ - [250, 90], - [250, 300], - [10, 300], - ]; - await page.mouse.move(90, 90); - await page.mouse.down(); - for (const point of points) await page.mouse.move(...point); - await page.mouse.up(); - - await assertEdgelessSelectedRect(page, [100, 100, 100, 100]); - - points = [ - [400, 250], - [400, 450], - [250, 450], - ]; - - await page.keyboard.down('Shift'); // addition selection - await page.mouse.move(250, 250); - await page.mouse.down(); - for (const point of points) await page.mouse.move(...point); - await page.mouse.up(); - - await assertEdgelessSelectedRect(page, [100, 100, 200, 200]); -}); - -test.skip('freehand lasso subtract from selection', async ({ page }) => { - await commonSetup(page); - - await addBasicRectShapeElement(page, { x: 100, y: 100 }, { x: 200, y: 200 }); - await addBasicRectShapeElement(page, { x: 300, y: 300 }, { x: 400, y: 400 }); - await setEdgelessTool(page, 'default'); - - await selectAllByKeyboard(page); - - await setEdgelessTool(page, 'lasso'); - - const points: [number, number][] = [ - [410, 290], - [410, 410], - [290, 410], - ]; - - await page.keyboard.down('Alt'); - - await page.mouse.move(290, 290); - await page.mouse.down(); - for (const point of points) await page.mouse.move(...point); - await page.mouse.up(); - - await assertEdgelessSelectedRect(page, [100, 100, 100, 100]); // only the first rectangle should be selected -}); - -test.skip('polygonal lasso basic test', async ({ page }) => { - await commonSetup(page); - await addBasicRectShapeElement(page, { x: 100, y: 100 }, { x: 200, y: 200 }); - await addBasicRectShapeElement(page, { x: 300, y: 300 }, { x: 400, y: 400 }); - await page.mouse.click(10, 10); // deselect - - await assertEdgelessNonSelectedRect(page); - - await setEdgelessTool(page, 'lasso'); - await setEdgelessTool(page, 'lasso'); // switch to polygonal lasso - await sleep(100); - - const points: [number, number][] = [ - [90, 90], - [500, 90], - [500, 500], - [90, 500], - [90, 90], - ]; - - for (const point of points) { - await page.mouse.click(...point); - } - - await assertEdgelessSelectedRect(page, [100, 100, 200, 200]); -}); - -test.skip('polygonal lasso add to selection by holding Shift Key', async ({ - page, -}) => { - await commonSetup(page); - - await addBasicRectShapeElement(page, { x: 100, y: 100 }, { x: 200, y: 200 }); - await addBasicRectShapeElement(page, { x: 300, y: 300 }, { x: 400, y: 400 }); - - await page.mouse.click(10, 10); // deselect - await assertEdgelessNonSelectedRect(page); - - await setEdgelessTool(page, 'lasso'); - await setEdgelessTool(page, 'lasso'); - await sleep(100); - - let points: [number, number][] = [ - [90, 90], - [150, 90], - [150, 150], - [90, 150], - [90, 90], - ]; - - // select the first rectangle - for (const point of points) await page.mouse.click(...point); - - points = [ - [290, 290], - [350, 290], - [350, 350], - [290, 350], - [290, 290], - ]; - - await page.keyboard.down('Shift'); // add to selection - // selects the second rectangle - for (const point of points) await page.mouse.click(...point); - - // by the end both of the rects should be selected - await assertEdgelessSelectedRect(page, [100, 100, 200, 200]); -}); - -test.skip('polygonal lasso subtract from selection by holding Alt', async ({ - page, -}) => { - await commonSetup(page); - - await addBasicRectShapeElement(page, { x: 100, y: 100 }, { x: 200, y: 200 }); - await addBasicRectShapeElement(page, { x: 300, y: 300 }, { x: 400, y: 400 }); - - await selectAllByKeyboard(page); - - const points: [number, number][] = [ - [290, 290], - [350, 290], - [350, 350], - [290, 350], - [290, 290], - ]; - - // switch to polygonal lasso tool - await setEdgelessTool(page, 'lasso'); - await setEdgelessTool(page, 'lasso'); - await sleep(100); - - await page.keyboard.down('Alt'); // subtract from selection - for (const point of points) await page.mouse.click(...point); - - // By the end the second rectangle must be deselected leaving the first rect selection - await assertEdgelessSelectedRect(page, [100, 100, 100, 100]); -}); - -test.skip('polygonal lasso should complete selection when clicking the last point', async ({ - page, -}) => { - await commonSetup(page); - - // switch to polygonal lasso - await setEdgelessTool(page, 'lasso'); - await setEdgelessTool(page, 'lasso'); - await sleep(100); - - const lassoPoints: [number, number][] = [ - [100, 100], - [200, 200], - [250, 150], - [100, 100], - ]; - - for (const point of lassoPoints) await page.mouse.click(...point); - - const isSelecting = await page.evaluate(() => { - const edgeless = document.querySelector('affine-edgeless-root'); - if (!edgeless) throw new Error('Missing edgless root block'); - - const curController = edgeless.gfx.tool.currentTool$.peek(); - if (curController?.toolName !== 'lasso') - throw new Error('expected lasso tool controller'); - - return (curController as any)['_isSelecting']; - }); - - expect(isSelecting).toBe(false); -}); diff --git a/tests/blocksuite/e2e/edgeless/lock.spec.ts b/tests/blocksuite/e2e/edgeless/lock.spec.ts index 13e130a41f..9f80c54912 100644 --- a/tests/blocksuite/e2e/edgeless/lock.spec.ts +++ b/tests/blocksuite/e2e/edgeless/lock.spec.ts @@ -122,7 +122,7 @@ test.describe('lock', () => { expect(await getSelectedIds(page)).toHaveLength(1); }); - test('locked element should not be selectable by dragging default tool or lasso tool. unlocking will recover', async ({ + test('locked element should not be selectable by dragging default tool. unlocking will recover', async ({ page, }) => { await edgelessCommonSetup(page); diff --git a/tests/blocksuite/e2e/edgeless/shortcut.spec.ts b/tests/blocksuite/e2e/edgeless/shortcut.spec.ts index 0f125649cd..1bf73d3956 100644 --- a/tests/blocksuite/e2e/edgeless/shortcut.spec.ts +++ b/tests/blocksuite/e2e/edgeless/shortcut.spec.ts @@ -65,33 +65,6 @@ test('shortcut', async ({ page }) => { await page.keyboard.press('c'); const connectorButton = await locatorEdgelessToolButton(page, 'connector'); await expect(connectorButton).toHaveAttribute('active', ''); - - // await page.keyboard.press('l'); - // const lassoButton = await locatorEdgelessToolButton(page, 'lasso'); - // await expect(lassoButton).toHaveAttribute('active', ''); -}); - -test.skip('toggle lasso tool modes', async ({ page }) => { - await enterPlaygroundRoom(page); - await initEmptyEdgelessState(page); - await switchEditorMode(page); - await page.mouse.click(100, 100); - - const lassoButton = await locatorEdgelessToolButton(page, 'lasso', false); - - const isLassoMode = async (type: 'freehand' | 'polygonal') => { - const classes = (await lassoButton.getAttribute('class'))?.split(' ') ?? []; - return classes.includes(type); - }; - - await page.keyboard.press('Shift+l'); - expect(await isLassoMode('freehand')).toBe(true); - - await page.keyboard.press('Shift+l'); - expect(await isLassoMode('polygonal')).toBe(true); - - await page.keyboard.press('Shift+l'); - expect(await isLassoMode('freehand')).toBe(true); }); test('toggle shapes shortcut', async ({ page }) => { diff --git a/tests/blocksuite/e2e/utils/actions/edgeless.ts b/tests/blocksuite/e2e/utils/actions/edgeless.ts index 5f6143245a..f1785d07e2 100644 --- a/tests/blocksuite/e2e/utils/actions/edgeless.ts +++ b/tests/blocksuite/e2e/utils/actions/edgeless.ts @@ -52,11 +52,6 @@ export enum Shape { Triangle = 'Triangle', } -export enum LassoMode { - FreeHand = 'freehand', - Polygonal = 'polygonal', -} - export enum ConnectorMode { Straight, Orthogonal, @@ -166,8 +161,7 @@ type EdgelessTool = | 'text' | 'connector' | 'frame' - | 'frameNavigator' - | 'lasso'; + | 'frameNavigator'; type ZoomToolType = 'zoomIn' | 'zoomOut' | 'fitToScreen'; type ComponentToolType = 'shape' | 'thin' | 'thick' | 'brush' | 'more'; @@ -211,7 +205,6 @@ export async function locatorEdgelessToolButton( note: '.edgeless-note-button', frame: '.edgeless-frame-button', frameNavigator: '.edgeless-frame-navigator-button', - lasso: '.edgeless-lasso-button', }[type]; let buttonType; @@ -362,7 +355,6 @@ export async function setEdgelessTool( break; } - case 'lasso': case 'note': case 'eraser': case 'frame': @@ -438,20 +430,6 @@ export async function assertEdgelessConnectorToolMode( expect(tool.mode).toEqual(mode); } -export async function assertEdgelessLassoToolMode(page: Page, mode: LassoMode) { - const tool = await page.evaluate(() => { - const container = document.querySelector('affine-edgeless-root'); - if (!container) { - throw new Error('Missing edgeless page'); - } - return container.gfx.tool.currentToolOption$.peek(); - }); - if (tool.type !== 'lasso') { - throw new Error('Expected lasso tool'); - } - expect(tool.mode).toEqual(mode === LassoMode.FreeHand ? 0 : 1); -} - export async function getEdgelessBlockChild(page: Page) { const block = page.locator('affine-edgeless-note'); const blockBox = await block.boundingBox(); diff --git a/tests/kit/src/utils/editor.ts b/tests/kit/src/utils/editor.ts index f0ca99071b..a048c1bd79 100644 --- a/tests/kit/src/utils/editor.ts +++ b/tests/kit/src/utils/editor.ts @@ -237,8 +237,7 @@ type EdgelessTool = | 'text' | 'connector' | 'frame' - | 'frameNavigator' - | 'lasso'; + | 'frameNavigator'; /** * @param type the type of the tool in the toolbar @@ -265,7 +264,6 @@ export async function locateEdgelessToolButton( note: '.edgeless-note-button', frame: '.edgeless-frame-button', frameNavigator: '.edgeless-frame-navigator-button', - lasso: '.edgeless-lasso-button', }[type]; let buttonType; @@ -391,7 +389,6 @@ export async function setEdgelessTool( break; } - case 'lasso': case 'note': case 'eraser': case 'frame':