mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 19:16:29 +08:00
feat(editor): group gfx extension (#11950)
Closes: BS-3208 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a new group view extension, enhancing how group elements are handled and displayed. - Added new store and view modules for group-related features, improving modularity and integration. - **Refactor** - Updated the group element architecture to use extension-based registration for views, toolbars, and effects. - Simplified and reorganized exports for group and text modules. - **Chores** - Updated dependencies and project references to improve build consistency and compatibility. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -188,7 +188,9 @@
|
||||
"./gfx/connector": "./src/gfx/connector/index.ts",
|
||||
"./gfx/connector/store": "./src/gfx/connector/store.ts",
|
||||
"./gfx/connector/view": "./src/gfx/connector/view.ts",
|
||||
"./gfx/group": "./src/gfx/group.ts",
|
||||
"./gfx/group": "./src/gfx/group/index.ts",
|
||||
"./gfx/group/store": "./src/gfx/group/store.ts",
|
||||
"./gfx/group/view": "./src/gfx/group/view.ts",
|
||||
"./gfx/template": "./src/gfx/template/index.ts",
|
||||
"./gfx/template/view": "./src/gfx/template/view.ts",
|
||||
"./gfx/turbo-renderer": "./src/gfx/turbo-renderer.ts",
|
||||
|
||||
@@ -17,6 +17,7 @@ import { SurfaceRefStoreExtension } from '@blocksuite/affine-block-surface-ref/s
|
||||
import { TableStoreExtension } from '@blocksuite/affine-block-table/store';
|
||||
import { BrushStoreExtension } from '@blocksuite/affine-gfx-brush/store';
|
||||
import { ConnectorStoreExtension } from '@blocksuite/affine-gfx-connector/store';
|
||||
import { GroupStoreExtension } from '@blocksuite/affine-gfx-group/store';
|
||||
import { MindmapStoreExtension } from '@blocksuite/affine-gfx-mindmap/store';
|
||||
import { ShapeStoreExtension } from '@blocksuite/affine-gfx-shape/store';
|
||||
import { FootnoteStoreExtension } from '@blocksuite/affine-inline-footnote/store';
|
||||
@@ -57,6 +58,7 @@ export function getInternalStoreExtensions() {
|
||||
ShapeStoreExtension,
|
||||
MindmapStoreExtension,
|
||||
ConnectorStoreExtension,
|
||||
GroupStoreExtension,
|
||||
|
||||
MigratingStoreExtension,
|
||||
];
|
||||
|
||||
@@ -17,6 +17,7 @@ import { SurfaceRefViewExtension } from '@blocksuite/affine-block-surface-ref/vi
|
||||
import { TableViewExtension } from '@blocksuite/affine-block-table/view';
|
||||
import { BrushViewExtension } from '@blocksuite/affine-gfx-brush/view';
|
||||
import { ConnectorViewExtension } from '@blocksuite/affine-gfx-connector/view';
|
||||
import { GroupViewExtension } from '@blocksuite/affine-gfx-group/view';
|
||||
import { MindmapViewExtension } from '@blocksuite/affine-gfx-mindmap/view';
|
||||
import { NoteViewExtension as GfxNoteViewExtension } from '@blocksuite/affine-gfx-note/view';
|
||||
import { ShapeViewExtension } from '@blocksuite/affine-gfx-shape/view';
|
||||
@@ -32,11 +33,13 @@ import { MigratingViewExtension } from './migrating-view';
|
||||
|
||||
export function getInternalViewExtensions() {
|
||||
return [
|
||||
// Gfx
|
||||
GfxNoteViewExtension,
|
||||
BrushViewExtension,
|
||||
ShapeViewExtension,
|
||||
MindmapViewExtension,
|
||||
ConnectorViewExtension,
|
||||
GroupViewExtension,
|
||||
TemplateViewExtension,
|
||||
|
||||
// Block
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-gfx-group/store';
|
||||
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-gfx-group/view';
|
||||
@@ -1,12 +1,4 @@
|
||||
import { FileDropExtension } from '@blocksuite/affine-components/drop-indicator';
|
||||
import {
|
||||
ConnectorElementRendererExtension,
|
||||
ConnectorElementView,
|
||||
} from '@blocksuite/affine-gfx-connector';
|
||||
import {
|
||||
GroupElementRendererExtension,
|
||||
GroupElementView,
|
||||
} from '@blocksuite/affine-gfx-group';
|
||||
import {
|
||||
TextElementRendererExtension,
|
||||
TextElementView,
|
||||
@@ -42,16 +34,10 @@ import { viewportOverlayWidget } from './widgets';
|
||||
* Because in some cases we need to create edgeless elements in page mode.
|
||||
* And these view may contain some logic when elements initialize.
|
||||
*/
|
||||
const EdgelessElementViews = [
|
||||
ConnectorElementView,
|
||||
GroupElementView,
|
||||
TextElementView,
|
||||
];
|
||||
const EdgelessElementViews = [TextElementView];
|
||||
|
||||
export const EdgelessElementRendererExtension: ExtensionType[] = [
|
||||
TextElementRendererExtension,
|
||||
ConnectorElementRendererExtension,
|
||||
GroupElementRendererExtension,
|
||||
];
|
||||
|
||||
export const CommonSpecs: ExtensionType[] = [
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { groupToolbarExtension } from '@blocksuite/affine-gfx-group';
|
||||
import { textToolbarExtension } from '@blocksuite/affine-gfx-text';
|
||||
import { ToolbarModuleExtension } from '@blocksuite/affine-shared/services';
|
||||
import { BlockFlavourIdentifier } from '@blocksuite/std';
|
||||
@@ -7,8 +6,6 @@ import type { ExtensionType } from '@blocksuite/store';
|
||||
import { builtinLockedToolbarConfig, builtinMiscToolbarConfig } from './misc';
|
||||
|
||||
export const EdgelessElementToolbarExtension: ExtensionType[] = [
|
||||
groupToolbarExtension,
|
||||
|
||||
textToolbarExtension,
|
||||
|
||||
ToolbarModuleExtension({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { effects as gfxGroupEffects } from '@blocksuite/affine-gfx-group/effects';
|
||||
import { effects as gfxCanvasTextEffects } from '@blocksuite/affine-gfx-text/effects';
|
||||
import { effects as widgetEdgelessToolbarEffects } from '@blocksuite/affine-widget-edgeless-toolbar/effects';
|
||||
import { effects as widgetMobileToolbarEffects } from '@blocksuite/affine-widget-keyboard-toolbar/effects';
|
||||
@@ -73,7 +72,6 @@ function registerRootComponents() {
|
||||
|
||||
function registerGfxEffects() {
|
||||
gfxCanvasTextEffects();
|
||||
gfxGroupEffects();
|
||||
}
|
||||
|
||||
function registerWidgets() {
|
||||
|
||||
@@ -11,7 +11,6 @@ import * as Y from 'yjs';
|
||||
import { elementsCtorMap } from './element-model/index.js';
|
||||
import { surfaceMiddlewareIdentifier } from './extensions/surface-middleware.js';
|
||||
import { SurfaceBlockTransformer } from './surface-transformer.js';
|
||||
import { groupRelationWatcher } from './watchers/group.js';
|
||||
|
||||
export const SurfaceBlockSchema = defineBlockSchema({
|
||||
flavour: 'affine:surface',
|
||||
@@ -50,10 +49,6 @@ export class SurfaceBlockModel extends BaseSurfaceModel {
|
||||
.forEach(({ middleware }) => {
|
||||
this._disposables.add(middleware(this));
|
||||
});
|
||||
|
||||
[groupRelationWatcher(this)].forEach(disposable =>
|
||||
this._disposables.add(disposable)
|
||||
);
|
||||
}
|
||||
|
||||
getConnectors(id: string) {
|
||||
|
||||
@@ -6,9 +6,11 @@ import {
|
||||
import { ConnectionOverlay } from './connector-manager';
|
||||
import { ConnectorTool } from './connector-tool';
|
||||
import { effects } from './effects';
|
||||
import { ConnectorElementRendererExtension } from './element-renderer';
|
||||
import { ConnectorFilter } from './element-transform';
|
||||
import { connectorToolbarExtension } from './toolbar/config';
|
||||
import { connectorQuickTool } from './toolbar/quick-tool';
|
||||
import { ConnectorElementView } from './view/view';
|
||||
|
||||
export class ConnectorViewExtension extends ViewExtensionProvider {
|
||||
override name = 'affine-connector-gfx';
|
||||
@@ -20,6 +22,8 @@ export class ConnectorViewExtension extends ViewExtensionProvider {
|
||||
|
||||
override setup(context: ViewExtensionContext) {
|
||||
super.setup(context);
|
||||
context.register(ConnectorElementView);
|
||||
context.register(ConnectorElementRendererExtension);
|
||||
if (this.isEdgeless(context.scope)) {
|
||||
context.register(ConnectorTool);
|
||||
context.register(ConnectorFilter);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-block-surface": "workspace:*",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-ext-loader": "workspace:*",
|
||||
"@blocksuite/affine-gfx-text": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
@@ -34,7 +35,9 @@
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./effects": "./src/effects.ts"
|
||||
"./effects": "./src/effects.ts",
|
||||
"./view": "./src/view.ts",
|
||||
"./store": "./src/store.ts"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { GroupElementModel } from '@blocksuite/affine-model';
|
||||
import { GfxElementModelView } from '@blocksuite/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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+12
-4
@@ -1,8 +1,11 @@
|
||||
import { SurfaceGroupLikeModel } from '../element-model/base.js';
|
||||
import type { SurfaceMiddleware } from '../extensions/surface-middleware.js';
|
||||
import type { SurfaceBlockModel } from '../surface-model.js';
|
||||
import {
|
||||
type SurfaceBlockModel,
|
||||
SurfaceGroupLikeModel,
|
||||
type SurfaceMiddleware,
|
||||
surfaceMiddlewareExtension,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
|
||||
export const groupRelationWatcher: SurfaceMiddleware = (
|
||||
const groupRelationWatcher: SurfaceMiddleware = (
|
||||
surface: SurfaceBlockModel
|
||||
) => {
|
||||
const disposables = [
|
||||
@@ -26,3 +29,8 @@ export const groupRelationWatcher: SurfaceMiddleware = (
|
||||
disposables.forEach(d => d.unsubscribe());
|
||||
};
|
||||
};
|
||||
|
||||
export const groupRelationWatcherExtension = surfaceMiddlewareExtension(
|
||||
'group-relation-watcher',
|
||||
groupRelationWatcher
|
||||
);
|
||||
@@ -1,6 +1,6 @@
|
||||
export * from './adapter';
|
||||
export * from './command';
|
||||
export * from './element-renderer';
|
||||
export * from './element-view';
|
||||
export * from './text/text';
|
||||
export * from './toolbar/config';
|
||||
export * from './view';
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import {
|
||||
type StoreExtensionContext,
|
||||
StoreExtensionProvider,
|
||||
} from '@blocksuite/affine-ext-loader';
|
||||
|
||||
import {
|
||||
groupToMarkdownAdapterMatcher,
|
||||
groupToPlainTextAdapterMatcher,
|
||||
} from './adapter';
|
||||
import { groupRelationWatcherExtension } from './group-watcher';
|
||||
|
||||
export class GroupStoreExtension extends StoreExtensionProvider {
|
||||
override name = 'affine-group-gfx';
|
||||
|
||||
override setup(context: StoreExtensionContext) {
|
||||
super.setup(context);
|
||||
context.register(groupToPlainTextAdapterMatcher);
|
||||
context.register(groupToMarkdownAdapterMatcher);
|
||||
context.register(groupRelationWatcherExtension);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,27 @@
|
||||
import type { GroupElementModel } from '@blocksuite/affine-model';
|
||||
import { GfxElementModelView } from '@blocksuite/std/gfx';
|
||||
import {
|
||||
type ViewExtensionContext,
|
||||
ViewExtensionProvider,
|
||||
} from '@blocksuite/affine-ext-loader';
|
||||
|
||||
import { mountGroupTitleEditor } from './text/edgeless-group-title-editor';
|
||||
import { effects } from './effects';
|
||||
import { GroupElementRendererExtension } from './element-renderer';
|
||||
import { GroupElementView } from './element-view';
|
||||
import { groupToolbarExtension } from './toolbar/config';
|
||||
|
||||
export class GroupElementView extends GfxElementModelView<GroupElementModel> {
|
||||
static override type: string = 'group';
|
||||
export class GroupViewExtension extends ViewExtensionProvider {
|
||||
override name = 'affine-group-gfx';
|
||||
|
||||
override onCreated(): void {
|
||||
super.onCreated();
|
||||
|
||||
this._initDblClickToEdit();
|
||||
override effect(): void {
|
||||
super.effect();
|
||||
effects();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
override setup(context: ViewExtensionContext) {
|
||||
super.setup(context);
|
||||
context.register(GroupElementRendererExtension);
|
||||
context.register(GroupElementView);
|
||||
if (this.isEdgeless(context.scope)) {
|
||||
context.register(groupToolbarExtension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"references": [
|
||||
{ "path": "../../blocks/surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../ext-loader" },
|
||||
{ "path": "../text" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
|
||||
@@ -2,6 +2,6 @@ export * from './adapter';
|
||||
export * from './commands';
|
||||
export * from './edgeless-text-editor';
|
||||
export * from './element-renderer';
|
||||
export * from './element-view';
|
||||
export * from './tool';
|
||||
export * from './toolbar';
|
||||
export * from './view';
|
||||
|
||||
@@ -530,6 +530,7 @@ export const PackageList = [
|
||||
workspaceDependencies: [
|
||||
'blocksuite/affine/blocks/surface',
|
||||
'blocksuite/affine/components',
|
||||
'blocksuite/affine/ext-loader',
|
||||
'blocksuite/affine/gfx/text',
|
||||
'blocksuite/affine/model',
|
||||
'blocksuite/affine/rich-text',
|
||||
|
||||
@@ -3159,6 +3159,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@blocksuite/affine-block-surface": "workspace:*"
|
||||
"@blocksuite/affine-components": "workspace:*"
|
||||
"@blocksuite/affine-ext-loader": "workspace:*"
|
||||
"@blocksuite/affine-gfx-text": "workspace:*"
|
||||
"@blocksuite/affine-model": "workspace:*"
|
||||
"@blocksuite/affine-rich-text": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user