fix(editor): shape tool should be the last used shape (#12425)
Close [BS-3305](https://linear.app/affine-design/issue/BS-3305/白板按s应该使用上次的shape形状) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added a method to cycle through shape types when using the shape tool. - **Bug Fixes** - Improved shape tool behavior to ensure the selected shape type does not change unexpectedly after adding a new shape. - **Tests** - Added an end-to-end test to verify that the shape tool retains the selected shape type after adding a new shape. - Enhanced shortcut tests to verify cycling shapes forward and backward using 's' and 'Shift+s' keys. - **Refactor** - Streamlined the logic for cycling through shape types and connector modes for improved maintainability. - Removed external utility for cycling shapes, integrating the functionality directly into the shape tool. - Updated keyboard shortcut handling to use the new cycling method within the shape tool. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -235,21 +235,18 @@ export class EdgelessToolbarShapeDraggable extends EdgelessToolbarToolMixin(
|
||||
const locked = this.gfx.viewport.locked;
|
||||
const selection = this.gfx.selection;
|
||||
if (locked || selection.editing) return;
|
||||
if (
|
||||
this.gfx.tool.dragging$.peek() &&
|
||||
this.gfx.tool.currentToolName$.peek() === 'shape'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeIndex = shapes.findIndex(
|
||||
s => s.name === this.draggingShape
|
||||
);
|
||||
const nextIndex = (activeIndex + 1) % shapes.length;
|
||||
const next = shapes[nextIndex];
|
||||
this.draggingShape = next.name;
|
||||
const currentTool = this.gfx.tool.currentToolName$.peek();
|
||||
|
||||
if (this.readyToDrop) {
|
||||
if (currentTool === ShapeTool.toolName) {
|
||||
const activeIndex = shapes.findIndex(
|
||||
s => s.name === this.draggingShape
|
||||
);
|
||||
const nextIndex = (activeIndex + 1) % shapes.length;
|
||||
const next = shapes[nextIndex];
|
||||
this.draggingShape = next.name;
|
||||
}
|
||||
this.draggableController.cancelWithoutAnimation();
|
||||
const el = this.shapeContainer.querySelector(
|
||||
`.shape.${this.draggingShape}`
|
||||
@@ -264,8 +261,14 @@ export class EdgelessToolbarShapeDraggable extends EdgelessToolbarToolMixin(
|
||||
const clientPos = { x: x + left, y: y + top };
|
||||
this.draggableController.dragAndMoveTo(el, clientPos);
|
||||
} else {
|
||||
if (this.gfx.tool.dragging$.peek()) return;
|
||||
let shapeName =
|
||||
this.gfx.tool.get(ShapeTool).activatedOption.shapeName;
|
||||
if (currentTool === ShapeTool.toolName) {
|
||||
shapeName = this.gfx.tool.get(ShapeTool).cycleShapeName('next');
|
||||
}
|
||||
this.setEdgelessTool(ShapeTool, {
|
||||
shapeName: this.draggingShape,
|
||||
shapeName,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5,7 +5,11 @@ import {
|
||||
type SurfaceBlockComponent,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import type { ShapeElementModel, ShapeName } from '@blocksuite/affine-model';
|
||||
import { DefaultTheme, getShapeType } from '@blocksuite/affine-model';
|
||||
import {
|
||||
DefaultTheme,
|
||||
getShapeType,
|
||||
ShapeType,
|
||||
} from '@blocksuite/affine-model';
|
||||
import {
|
||||
EditPropsStore,
|
||||
TelemetryProvider,
|
||||
@@ -15,7 +19,7 @@ import { hasClassNameInList } from '@blocksuite/affine-shared/utils';
|
||||
import type { IBound } from '@blocksuite/global/gfx';
|
||||
import { Bound } from '@blocksuite/global/gfx';
|
||||
import type { PointerEventState } from '@blocksuite/std';
|
||||
import { BaseTool } from '@blocksuite/std/gfx';
|
||||
import { BaseTool, type GfxController } from '@blocksuite/std/gfx';
|
||||
import { effect } from '@preact/signals-core';
|
||||
|
||||
import {
|
||||
@@ -159,6 +163,13 @@ export class ShapeTool extends BaseTool<ShapeToolOption> {
|
||||
this._surfaceComponent?.refresh();
|
||||
}
|
||||
|
||||
constructor(gfx: GfxController) {
|
||||
super(gfx);
|
||||
this.activatedOption = {
|
||||
shapeName: ShapeType.Rect,
|
||||
};
|
||||
}
|
||||
|
||||
override activate() {
|
||||
this.createOverlay();
|
||||
}
|
||||
@@ -337,4 +348,20 @@ export class ShapeTool extends BaseTool<ShapeToolOption> {
|
||||
setDisableOverlay(disable: boolean) {
|
||||
this._disableOverlay = disable;
|
||||
}
|
||||
|
||||
cycleShapeName(dir: 'prev' | 'next' = 'next'): ShapeName {
|
||||
const shapeNames: ShapeName[] = [
|
||||
ShapeType.Rect,
|
||||
ShapeType.Ellipse,
|
||||
ShapeType.Diamond,
|
||||
ShapeType.Triangle,
|
||||
'roundedRect',
|
||||
];
|
||||
|
||||
const currentIndex = shapeNames.indexOf(this.activatedOption.shapeName);
|
||||
const nextIndex =
|
||||
(currentIndex + (dir === 'prev' ? -1 : 1) + shapeNames.length) %
|
||||
shapeNames.length;
|
||||
return shapeNames[nextIndex];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user