refactor: rewrite dblclick and selection logic of default-tool (#11036)

continue #10824

### Changed
- Moved double-click-to-edit behavior from the default tool to individual model views
- Introduced `onSelected` callback interface in gfx view components to allows developers to override default selection logic
This commit is contained in:
doouding
2025-03-26 07:32:43 +00:00
parent 61c0d01da3
commit ace5d44a61
38 changed files with 779 additions and 353 deletions

View File

@@ -1,3 +1,4 @@
export * from './command';
export * from './text/text';
export * from './toolbar/config';
export * from './view';

View File

@@ -5,15 +5,49 @@ import {
} from '@blocksuite/affine-block-surface';
import type { GroupElementModel } from '@blocksuite/affine-model';
import type { RichText } from '@blocksuite/affine-rich-text';
import { type BlockComponent, ShadowlessElement } from '@blocksuite/block-std';
import {
type BlockComponent,
type BlockStdScope,
ShadowlessElement,
stdContext,
} from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { RANGE_SYNC_EXCLUDE_ATTR } from '@blocksuite/block-std/inline';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
import { Bound } from '@blocksuite/global/gfx';
import { WithDisposable } from '@blocksuite/global/lit';
import { consume } from '@lit/context';
import { html, nothing } from 'lit';
import { property, query } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
export function mountGroupTitleEditor(
group: GroupElementModel,
edgeless: BlockComponent
) {
const mountElm = edgeless.querySelector('.edgeless-mount-point');
if (!mountElm) {
throw new BlockSuiteError(
ErrorCode.ValueNotExists,
"edgeless block's mount point does not exist"
);
}
const gfx = edgeless.std.get(GfxControllerIdentifier);
// @ts-expect-error FIXME: resolve after gfx tool refactor
gfx.tool.setTool('default');
gfx.selection.set({
elements: [group.id],
editing: true,
});
const groupEditor = new EdgelessGroupTitleEditor();
groupEditor.group = group;
mountElm.append(groupEditor);
}
export class EdgelessGroupTitleEditor extends WithDisposable(
ShadowlessElement
) {
@@ -26,7 +60,7 @@ export class EdgelessGroupTitleEditor extends WithDisposable(
}
get gfx() {
return this.edgeless.std.get(GfxControllerIdentifier);
return this.std.get(GfxControllerIdentifier);
}
get selection() {
@@ -50,7 +84,7 @@ export class EdgelessGroupTitleEditor extends WithDisposable(
}
override firstUpdated(): void {
const dispatcher = this.edgeless.std.event;
const dispatcher = this.std.event;
this.updateComplete
.then(() => {
@@ -141,12 +175,14 @@ export class EdgelessGroupTitleEditor extends WithDisposable(
></rich-text>`;
}
@property({ attribute: false })
accessor edgeless!: BlockComponent;
@property({ attribute: false })
accessor group!: GroupElementModel;
@consume({
context: stdContext,
})
accessor std!: BlockStdScope;
@query('rich-text')
accessor richText!: RichText;
}

View File

@@ -28,7 +28,6 @@ export function mountGroupTitleEditor(
const groupEditor = new EdgelessGroupTitleEditor();
groupEditor.group = group;
groupEditor.edgeless = edgeless;
mountElm.append(groupEditor);
}

View File

@@ -0,0 +1,24 @@
import type { GroupElementModel } from '@blocksuite/affine-model';
import { GfxElementModelView } from '@blocksuite/block-std/gfx';
import { mountGroupTitleEditor } from './text/edgeless-group-title-editor';
export class GroupElementView extends GfxElementModelView<GroupElementModel> {
static override type: string = 'group';
override onCreated(): void {
super.onCreated();
this._initDblClickToEdit();
}
private _initDblClickToEdit(): void {
this.on('dblclick', () => {
const edgeless = this.std.view.getBlock(this.std.store.root!.id);
if (edgeless && !this.model.isLocked()) {
mountGroupTitleEditor(this.model, edgeless);
}
});
}
}