refactor(editor): extract drag handle widget (#9415)

This commit is contained in:
Saul-Mirone
2024-12-29 06:51:48 +00:00
parent b96a03b283
commit cec4a4b2c0
47 changed files with 277 additions and 92 deletions

View File

@@ -4,8 +4,10 @@ import {
DocDisplayMetaService,
DocModeService,
EmbedOptionService,
PageViewportServiceExtension,
ThemeService,
} from '@blocksuite/affine-shared/services';
import { AFFINE_DRAG_HANDLE_WIDGET } from '@blocksuite/affine-widget-drag-handle';
import {
AFFINE_DOC_REMOTE_SELECTION_WIDGET,
AFFINE_EDGELESS_REMOTE_SELECTION_WIDGET,
@@ -25,7 +27,6 @@ import { literal, unsafeStatic } from 'lit/static-html.js';
import { ExportManagerExtension } from '../../_common/export-manager/export-manager.js';
import { RootBlockAdapterExtensions } from '../adapters/extension.js';
import { commands } from '../commands/index.js';
import { AFFINE_DRAG_HANDLE_WIDGET } from '../widgets/drag-handle/consts.js';
import { AFFINE_EDGELESS_AUTO_CONNECT_WIDGET } from '../widgets/edgeless-auto-connect/edgeless-auto-connect.js';
import { AFFINE_EDGELESS_ZOOM_TOOLBAR_WIDGET } from '../widgets/edgeless-zoom-toolbar/index.js';
import { EDGELESS_ELEMENT_TOOLBAR_WIDGET } from '../widgets/element-toolbar/index.js';
@@ -97,6 +98,7 @@ const EdgelessCommonExtension: ExtensionType[] = [
ExportManagerExtension,
ToolController,
DNDAPIExtension,
PageViewportServiceExtension,
DocDisplayMetaService,
RootBlockAdapterExtensions,
FileDropExtension,

View File

@@ -1,4 +1,5 @@
import type { SurfaceBlockComponent } from '@blocksuite/affine-block-surface';
import { addNote } from '@blocksuite/affine-block-surface';
import {
DEFAULT_NOTE_HEIGHT,
DEFAULT_NOTE_WIDTH,
@@ -11,7 +12,6 @@ import { Point } from '@blocksuite/global/utils';
import { effect } from '@preact/signals-core';
import { hasClassNameInList } from '../../../_common/utils/index.js';
import { addNote } from '../utils/common.js';
import { EXCLUDING_MOUSE_OUT_CLASS_LIST } from '../utils/consts.js';
import { DraggingNoteOverlay, NoteOverlay } from '../utils/tool-overlay.js';

View File

@@ -1,135 +0,0 @@
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
import {
DEFAULT_NOTE_HEIGHT,
DEFAULT_NOTE_WIDTH,
NOTE_MIN_HEIGHT,
type NoteBlockModel,
NoteDisplayMode,
} from '@blocksuite/affine-model';
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
import type { NoteChildrenFlavour } from '@blocksuite/affine-shared/types';
import { handleNativeRangeAtPoint } from '@blocksuite/affine-shared/utils';
import type { BlockStdScope } from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import {
type IPoint,
type Point,
serializeXYWH,
} from '@blocksuite/global/utils';
import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from './consts.js';
export function addNoteAtPoint(
std: BlockStdScope,
/**
* The point is in browser coordinate
*/
point: IPoint,
options: {
width?: number;
height?: number;
parentId?: string;
noteIndex?: number;
offsetX?: number;
offsetY?: number;
scale?: number;
} = {}
) {
const gfx = std.get(GfxControllerIdentifier);
const crud = std.get(EdgelessCRUDIdentifier);
const {
width = DEFAULT_NOTE_WIDTH,
height = DEFAULT_NOTE_HEIGHT,
offsetX = DEFAULT_NOTE_OFFSET_X,
offsetY = DEFAULT_NOTE_OFFSET_Y,
parentId = gfx.doc.root?.id,
noteIndex,
scale = 1,
} = options;
const [x, y] = gfx.viewport.toModelCoord(point.x, point.y);
const blockId = crud.addBlock(
'affine:note',
{
xywh: serializeXYWH(
x - offsetX * scale,
y - offsetY * scale,
width,
height
),
displayMode: NoteDisplayMode.EdgelessOnly,
},
parentId,
noteIndex
);
std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
control: 'canvas:draw',
page: 'whiteboard editor',
module: 'toolbar',
segment: 'toolbar',
type: 'note',
});
return blockId;
}
type NoteOptions = {
childFlavour: NoteChildrenFlavour;
childType: string | null;
collapse: boolean;
};
export function addNote(
std: BlockStdScope,
point: Point,
options: NoteOptions,
width = DEFAULT_NOTE_WIDTH,
height = DEFAULT_NOTE_HEIGHT
) {
const noteId = addNoteAtPoint(std, point, {
width,
height,
});
const gfx = std.get(GfxControllerIdentifier);
const doc = std.doc;
const blockId = doc.addBlock(
options.childFlavour,
{ type: options.childType },
noteId
);
if (options.collapse && height > NOTE_MIN_HEIGHT) {
const note = doc.getBlockById(noteId) as NoteBlockModel;
doc.updateBlock(note, () => {
note.edgeless.collapse = true;
note.edgeless.collapsedHeight = height;
});
}
gfx.tool.setTool('default');
// Wait for edgelessTool updated
requestAnimationFrame(() => {
const blocks =
(doc.root?.children.filter(
child => child.flavour === 'affine:note'
) as BlockSuite.EdgelessBlockModelType[]) ?? [];
const element = blocks.find(b => b.id === noteId);
if (element) {
gfx.selection.set({
elements: [element.id],
editing: true,
});
// Waiting dom updated, `note mask` is removed
if (blockId) {
focusTextModel(gfx.std, blockId);
} else {
// Cannot reuse `handleNativeRangeClick` directly here,
// since `retargetClick` will re-target to pervious editor
handleNativeRangeAtPoint(point.x, point.y);
}
}
});
}

View File

@@ -6,8 +6,6 @@ import {
StrokeStyle,
} from '@blocksuite/affine-model';
export const DEFAULT_NOTE_OFFSET_X = 30;
export const DEFAULT_NOTE_OFFSET_Y = 40;
export const NOTE_OVERLAY_OFFSET_X = 6;
export const NOTE_OVERLAY_OFFSET_Y = 6;
export const NOTE_OVERLAY_WIDTH = 100;