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

feat(edgeless): copilot selection widget #6497

Merged
merged 15 commits into from
Mar 22, 2024
7 changes: 6 additions & 1 deletion packages/blocks/src/_common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ export type PanTool = {
panning: boolean;
};

export type AITool = {
type: 'ai';
};

export type NoteChildrenFlavour =
| 'affine:paragraph'
| 'affine:list'
Expand Down Expand Up @@ -239,7 +243,8 @@ export type EdgelessTool =
| ConnectorTool
| EraserTool
| FrameTool
| FrameNavigatorTool;
| FrameNavigatorTool
| AITool;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CopilotSelectionTool


export type EmbedBlockDoubleClickData = {
blockId: string;
Expand Down
4 changes: 4 additions & 0 deletions packages/blocks/src/_common/utils/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export function isMiddleButtonPressed(e: MouseEvent) {
return (MOUSE_BUTTONS.AUXILIARY & e.buttons) === MOUSE_BUTTONS.AUXILIARY;
}

export function isRightButtonPressed(e: MouseEvent) {
return (MOUSE_BUTTONS.SECONDARY & e.buttons) === MOUSE_BUTTONS.SECONDARY;
}

export function stopPropagation(event: Event) {
event.stopPropagation();
}
Expand Down
2 changes: 2 additions & 0 deletions packages/blocks/src/_specs/_specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { PageRootService } from '../root-block/page/page-root-service.js';
import { RootBlockSchema } from '../root-block/root-model.js';
import { AFFINE_DOC_REMOTE_SELECTION_WIDGET } from '../root-block/widgets/doc-remote-selection/doc-remote-selection.js';
import { AFFINE_DRAG_HANDLE_WIDGET } from '../root-block/widgets/drag-handle/drag-handle.js';
import { AFFINE_EDGELESS_AI_WIDGET } from '../root-block/widgets/edgeless-ai-selection/index.js';
import { AFFINE_EDGELESS_REMOTE_SELECTION_WIDGET } from '../root-block/widgets/edgeless-remote-selection/index.js';
import { AFFINE_EDGELESS_ZOOM_TOOLBAR_WIDGET } from '../root-block/widgets/edgeless-zoom-toolbar/index.js';
import { AFFINE_FORMAT_BAR_WIDGET } from '../root-block/widgets/format-bar/format-bar.js';
Expand Down Expand Up @@ -114,6 +115,7 @@ const EdgelessPageSpec: BlockSpec<EdgelessRootBlockWidgetName> = {
[AFFINE_EDGELESS_ZOOM_TOOLBAR_WIDGET]: literal`${unsafeStatic(
AFFINE_EDGELESS_ZOOM_TOOLBAR_WIDGET
)}`,
[AFFINE_EDGELESS_AI_WIDGET]: literal`${unsafeStatic(AFFINE_EDGELESS_AI_WIDGET)}`,
},
},
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { PointerEventState } from '@blocksuite/block-std';
import { Slot } from '@blocksuite/store';

import type { AITool } from '../../../../_common/utils/index.js';
import { EdgelessToolController } from './index.js';

export class AIToolController extends EdgelessToolController<AITool> {
readonly tool = <AITool>{
type: 'ai',
};

private _dragStartPoint: [number, number] = [0, 0];
private _dragLastPoint: [number, number] = [0, 0];
private _dragging = false;

draggingAreaUpdated = new Slot();

get area() {
const start = new DOMPoint(
this._dragStartPoint[0],
this._dragStartPoint[1]
);
const end = new DOMPoint(this._dragLastPoint[0], this._dragLastPoint[1]);

const minX = Math.min(start.x, end.x);
const minY = Math.min(start.y, end.y);
const maxX = Math.max(start.x, end.x);
const maxY = Math.max(start.y, end.y);

return new DOMRect(minX, minY, maxX - minX, maxY - minY);
}

private _initDragState(e: PointerEventState) {
this._dragStartPoint = this._service.viewport.toModelCoord(e.x, e.y);
this._dragLastPoint = this._dragStartPoint;
}

override onContainerDragStart(e: PointerEventState): void {
this._initDragState(e);
this._dragging = true;
this.draggingAreaUpdated.emit();
}

override onContainerDragMove(e: PointerEventState): void {
if (!this._dragging) return;

this._dragLastPoint = this._service.viewport.toModelCoord(e.x, e.y);
this.draggingAreaUpdated.emit();
}

override onContainerDragEnd(): void {
this._dragging = false;
}

onContainerPointerDown(): void {}

onContainerClick(): void {}

onContainerContextMenu(): void {}

onContainerDblClick(): void {}

onContainerTripleClick(): void {}

onContainerMouseMove(): void {}

onContainerMouseOut(): void {}

onPressShiftKey(): void {}

onPressSpaceBar(): void {}

beforeModeSwitch(): void {}

afterModeSwitch(): void {}
}
69 changes: 62 additions & 7 deletions packages/blocks/src/root-block/edgeless/edgeless-keyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IS_MAC } from '@blocksuite/global/env';

import { type EdgelessTool } from '../../_common/types.js';
import { matchFlavours } from '../../_common/utils/model.js';
import { once } from '../../index.js';
import {
Bound,
ConnectorElementModel,
Expand Down Expand Up @@ -195,6 +196,26 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager {
global: true,
}
);

this._bindMetaKey();
this._bindShiftKey();
this._bindToggleHand();
}

private _bindMetaKey() {
this.rootElement.handleEvent(
'keyDown',
ctx => {
const event = ctx.get('defaultState').event;
if (event instanceof KeyboardEvent) {
this._meta(event);
}
},
{ global: true }
);
}

private _bindShiftKey() {
this.rootElement.handleEvent(
'keyDown',
ctx => {
Expand All @@ -217,7 +238,6 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager {
global: true,
}
);
this._bindToggleHand();
}

private _bindToggleHand() {
Expand Down Expand Up @@ -288,13 +308,48 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager {

private _shift(event: KeyboardEvent) {
const edgeless = this.rootElement;
if (!event.repeat) {
if (event.key.toLowerCase() === 'shift' && event.shiftKey) {
edgeless.slots.pressShiftKeyUpdated.emit(true);
} else {
edgeless.slots.pressShiftKeyUpdated.emit(false);
}

if (event.repeat) return;

const shiftKeyPressed =
event.key.toLowerCase() === 'shift' && event.shiftKey;

if (shiftKeyPressed) {
edgeless.slots.pressShiftKeyUpdated.emit(true);
} else {
edgeless.slots.pressShiftKeyUpdated.emit(false);
}
}

private _meta(event: KeyboardEvent) {
const edgeless = this.rootElement;
const selection = edgeless.service.selection;
const currentTool = edgeless.edgelessTool;

if (
selection.editing ||
(IS_MAC && !event.metaKey) ||
(!IS_MAC && !event.ctrlKey)
) {
return;
}

edgeless.tools.metaKey = true;
this._setEdgelessTool(edgeless, {
type: 'ai',
});

once(document, 'keyup', () => {
edgeless.tools.metaKey = false;
edgeless.tools.setEdgelessTool(
currentTool,
{
elements: [],
editing: false,
},
false
);
});
}

private _delete() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import type { EdgelessBlockPortalContainer } from './components/block-portal/edg
import { EdgelessToolbar } from './components/toolbar/edgeless-toolbar.js';
import { readImageSize } from './components/utils.js';
import { EdgelessClipboardController } from './controllers/clipboard.js';
import { AIToolController } from './controllers/tools/ai-tool.js';
import { BrushToolController } from './controllers/tools/brush-tool.js';
import { ConnectorToolController } from './controllers/tools/connector-tool.js';
import { DefaultToolController } from './controllers/tools/default-tool.js';
Expand Down Expand Up @@ -713,6 +714,7 @@ export class EdgelessRootBlockComponent extends BlockElement<
FrameToolController,
PanToolController,
PresentToolController,
AIToolController,
] as EdgelessToolConstructor[];

tools.forEach(tool => {
Expand Down
Loading
Loading