From 4ebeb530e0186a29183adf4e8482c482d5c476b3 Mon Sep 17 00:00:00 2001 From: Saul-Mirone Date: Tue, 13 May 2025 11:09:21 +0000 Subject: [PATCH] refactor(editor): config the extension provider directly (#12252) ## Summary by CodeRabbit - **New Features** - Added new export paths to improve module accessibility for foundation store and view components. - Introduced new extension points for telemetry, font configuration, link preview cache, and peek view services in the view extension foundation. - **Improvements** - Enhanced flexibility by allowing optional configuration of placeholders in paragraph view extensions. - Switched to runtime schema validation for font configuration, increasing reliability. - Streamlined service registration for peek view providers. - **Refactor** - Centralized and simplified extension management by removing redundant extension files and consolidating setup logic. - Updated internal integration of telemetry, font, and peek view services for improved maintainability. --- blocksuite/affine/all/package.json | 4 +- blocksuite/affine/all/src/foundation/store.ts | 1 + blocksuite/affine/all/src/foundation/view.ts | 1 + .../affine/blocks/paragraph/src/view.ts | 9 ++-- .../affine/components/src/peek/service.ts | 2 +- blocksuite/affine/foundation/src/view.ts | 47 +++++++++++++++-- .../shared/src/services/font-loader/config.ts | 15 +++--- .../telemetry-service/telemetry-service.ts | 11 ++++ .../src/blocksuite/extensions/font-config.ts | 13 ----- .../extensions/peek-view-service.ts | 36 ------------- .../src/blocksuite/extensions/telemetry.ts | 21 -------- .../src/blocksuite/manager/common-view.ts | 11 +--- .../src/blocksuite/manager/migrating-view.ts | 51 +++++++++++++++++++ 13 files changed, 126 insertions(+), 96 deletions(-) create mode 100644 blocksuite/affine/all/src/foundation/store.ts create mode 100644 blocksuite/affine/all/src/foundation/view.ts delete mode 100644 packages/frontend/core/src/blocksuite/extensions/font-config.ts delete mode 100644 packages/frontend/core/src/blocksuite/extensions/peek-view-service.ts delete mode 100644 packages/frontend/core/src/blocksuite/extensions/telemetry.ts diff --git a/blocksuite/affine/all/package.json b/blocksuite/affine/all/package.json index 7b504d08c9..46dbd62c4f 100644 --- a/blocksuite/affine/all/package.json +++ b/blocksuite/affine/all/package.json @@ -274,7 +274,9 @@ "./model": "./src/model/index.ts", "./sync": "./src/sync/index.ts", "./extensions/store": "./src/extensions/store.ts", - "./extensions/view": "./src/extensions/view.ts" + "./extensions/view": "./src/extensions/view.ts", + "./foundation/store": "./src/foundation/store.ts", + "./foundation/view": "./src/foundation/view.ts" }, "files": [ "src", diff --git a/blocksuite/affine/all/src/foundation/store.ts b/blocksuite/affine/all/src/foundation/store.ts new file mode 100644 index 0000000000..54ebe27f0c --- /dev/null +++ b/blocksuite/affine/all/src/foundation/store.ts @@ -0,0 +1 @@ +export * from '@blocksuite/affine-foundation/store'; diff --git a/blocksuite/affine/all/src/foundation/view.ts b/blocksuite/affine/all/src/foundation/view.ts new file mode 100644 index 0000000000..dbb9444ecd --- /dev/null +++ b/blocksuite/affine/all/src/foundation/view.ts @@ -0,0 +1 @@ +export * from '@blocksuite/affine-foundation/view'; diff --git a/blocksuite/affine/blocks/paragraph/src/view.ts b/blocksuite/affine/blocks/paragraph/src/view.ts index 87883b4d84..103625b7c5 100644 --- a/blocksuite/affine/blocks/paragraph/src/view.ts +++ b/blocksuite/affine/blocks/paragraph/src/view.ts @@ -28,10 +28,9 @@ import { z } from 'zod'; import { effects } from './effects'; const optionsSchema = z.object({ - getPlaceholder: z - .function() - .args(z.instanceof(ParagraphBlockModel)) - .returns(z.string()), + getPlaceholder: z.optional( + z.function().args(z.instanceof(ParagraphBlockModel)).returns(z.string()) + ), }); export class ParagraphViewExtension extends ViewExtensionProvider< @@ -50,7 +49,7 @@ export class ParagraphViewExtension extends ViewExtensionProvider< context: ViewExtensionContext, options?: z.infer ) { - super.setup(context); + super.setup(context, options); const getPlaceholder = options?.getPlaceholder ?? (model => placeholders[model.props.type]); diff --git a/blocksuite/affine/components/src/peek/service.ts b/blocksuite/affine/components/src/peek/service.ts index 9ef64a6c7e..cb9999a074 100644 --- a/blocksuite/affine/components/src/peek/service.ts +++ b/blocksuite/affine/components/src/peek/service.ts @@ -10,7 +10,7 @@ export const PeekViewProvider = createIdentifier( export function PeekViewExtension(service: PeekViewService): ExtensionType { return { setup: di => { - di.addImpl(PeekViewProvider, () => service); + di.override(PeekViewProvider, () => service); }, }; } diff --git a/blocksuite/affine/foundation/src/view.ts b/blocksuite/affine/foundation/src/view.ts index 56d2cdae6f..78c23f544b 100644 --- a/blocksuite/affine/foundation/src/view.ts +++ b/blocksuite/affine/foundation/src/view.ts @@ -1,4 +1,8 @@ import { FileDropExtension } from '@blocksuite/affine-components/drop-indicator'; +import { + PeekViewExtension, + type PeekViewService, +} from '@blocksuite/affine-components/peek'; import { type ViewExtensionContext, ViewExtensionProvider, @@ -12,28 +16,49 @@ import { EditPropsStore, EmbedOptionService, FileSizeLimitService, + FontConfigExtension, + fontConfigSchema, FontLoaderService, LinkPreviewCache, + LinkPreviewCacheConfigSchema, + LinkPreviewCacheExtension, LinkPreviewService, PageViewportServiceExtension, + TelemetryExtension, + type TelemetryService, ThemeService, ToolbarRegistryExtension, } from '@blocksuite/affine-shared/services'; import { InteractivityManager, ToolController } from '@blocksuite/std/gfx'; +import { z } from 'zod'; import { clipboardConfigs } from './clipboard'; import { effects } from './effects'; -export class FoundationViewExtension extends ViewExtensionProvider { +const optionsSchema = z.object({ + linkPreviewCacheConfig: z.optional(LinkPreviewCacheConfigSchema), + fontConfig: z.optional(z.array(fontConfigSchema)), + telemetry: z.optional(z.custom()), + peekView: z.optional(z.custom()), +}); + +export type FoundationViewExtensionOptions = z.infer; + +export class FoundationViewExtension extends ViewExtensionProvider { override name = 'foundation'; + override schema = optionsSchema; + override effect() { super.effect(); effects(); } - override setup(context: ViewExtensionContext) { - super.setup(context); + override setup( + context: ViewExtensionContext, + options?: FoundationViewExtensionOptions + ) { + super.setup(context, options); context.register([ DocDisplayMetaService, EditPropsStore, @@ -56,5 +81,21 @@ export class FoundationViewExtension extends ViewExtensionProvider { if (this.isEdgeless(context.scope)) { context.register([InteractivityManager, ToolController]); } + const fontConfig = options?.fontConfig; + if (fontConfig) { + context.register(FontConfigExtension(fontConfig)); + } + const linkPreviewCacheConfig = options?.linkPreviewCacheConfig; + if (linkPreviewCacheConfig) { + context.register(LinkPreviewCacheExtension(linkPreviewCacheConfig)); + } + const telemetry = options?.telemetry; + if (telemetry) { + context.register(TelemetryExtension(telemetry)); + } + const peekView = options?.peekView; + if (peekView) { + context.register(PeekViewExtension(peekView)); + } } } diff --git a/blocksuite/affine/shared/src/services/font-loader/config.ts b/blocksuite/affine/shared/src/services/font-loader/config.ts index 71c0d678f1..dae68a3ad2 100644 --- a/blocksuite/affine/shared/src/services/font-loader/config.ts +++ b/blocksuite/affine/shared/src/services/font-loader/config.ts @@ -1,11 +1,14 @@ import { FontFamily, FontStyle, FontWeight } from '@blocksuite/affine-model'; +import { z } from 'zod'; -export interface FontConfig { - font: string; - weight: string; - url: string; - style: string; -} +export const fontConfigSchema = z.object({ + font: z.string(), + weight: z.string(), + url: z.string(), + style: z.string(), +}); + +export type FontConfig = z.infer; export const AffineCanvasTextFonts: FontConfig[] = [ // Inter, https://fonts.cdnfonts.com/css/inter?styles=29139,29134,29135,29136,29140,29141 diff --git a/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts b/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts index 506e8590df..14735727a5 100644 --- a/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts +++ b/blocksuite/affine/shared/src/services/telemetry-service/telemetry-service.ts @@ -1,4 +1,5 @@ import { createIdentifier } from '@blocksuite/global/di'; +import type { ExtensionType } from '@blocksuite/store'; import type { OutDatabaseAllEvents } from './database.js'; import type { LinkToolbarEvents } from './link.js'; @@ -46,3 +47,13 @@ export interface TelemetryService { export const TelemetryProvider = createIdentifier( 'AffineTelemetryService' ); + +export const TelemetryExtension = ( + service: TelemetryService +): ExtensionType => { + return { + setup: di => { + di.override(TelemetryProvider, () => service); + }, + }; +}; diff --git a/packages/frontend/core/src/blocksuite/extensions/font-config.ts b/packages/frontend/core/src/blocksuite/extensions/font-config.ts deleted file mode 100644 index 517da14856..0000000000 --- a/packages/frontend/core/src/blocksuite/extensions/font-config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { - AffineCanvasTextFonts, - FontConfigExtension, -} from '@blocksuite/affine/shared/services'; - -export function getFontConfigExtension() { - return FontConfigExtension( - AffineCanvasTextFonts.map(font => ({ - ...font, - url: environment.publicPath + 'fonts/' + font.url.split('/').pop(), - })) - ); -} diff --git a/packages/frontend/core/src/blocksuite/extensions/peek-view-service.ts b/packages/frontend/core/src/blocksuite/extensions/peek-view-service.ts deleted file mode 100644 index 70feac5ed9..0000000000 --- a/packages/frontend/core/src/blocksuite/extensions/peek-view-service.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { PeekViewService } from '@affine/core/modules/peek-view'; -import { DebugLogger } from '@affine/debug'; -import type { - PeekOptions, - PeekViewService as BSPeekViewService, -} from '@blocksuite/affine/components/peek'; -import { PeekViewExtension } from '@blocksuite/affine/components/peek'; -import type { TemplateResult } from 'lit'; - -const logger = new DebugLogger('affine::patch-peek-view-service'); - -export function patchPeekViewService(service: PeekViewService) { - return PeekViewExtension({ - peek: ( - element: { - target: HTMLElement; - docId: string; - blockIds?: string[]; - template?: TemplateResult; - }, - options?: PeekOptions - ) => { - logger.debug('center peek', element); - const { template, target, ...props } = element; - - return service.peekView.open( - { - element: target, - docRef: props, - }, - template, - options?.abortSignal - ); - }, - } satisfies BSPeekViewService); -} diff --git a/packages/frontend/core/src/blocksuite/extensions/telemetry.ts b/packages/frontend/core/src/blocksuite/extensions/telemetry.ts deleted file mode 100644 index 5bebf8bc77..0000000000 --- a/packages/frontend/core/src/blocksuite/extensions/telemetry.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { mixpanel } from '@affine/track'; -import { - type TelemetryEventMap, - TelemetryProvider, -} from '@blocksuite/affine/shared/services'; -import type { ExtensionType } from '@blocksuite/affine/store'; - -export function getTelemetryExtension(): ExtensionType { - return { - setup: di => { - di.addImpl(TelemetryProvider, () => ({ - track: ( - eventName: T, - props: TelemetryEventMap[T] - ) => { - mixpanel.track(eventName as string, props as Record); - }, - })); - }, - }; -} diff --git a/packages/frontend/core/src/blocksuite/manager/common-view.ts b/packages/frontend/core/src/blocksuite/manager/common-view.ts index 9fad13c529..ed28ed76aa 100644 --- a/packages/frontend/core/src/blocksuite/manager/common-view.ts +++ b/packages/frontend/core/src/blocksuite/manager/common-view.ts @@ -1,9 +1,5 @@ import { buildDocDisplayMetaExtension } from '@affine/core/blocksuite/extensions/display-meta'; import { patchFileSizeLimitExtension } from '@affine/core/blocksuite/extensions/file-size-limit'; -import { getFontConfigExtension } from '@affine/core/blocksuite/extensions/font-config'; -import { patchPeekViewService } from '@affine/core/blocksuite/extensions/peek-view-service'; -import { getTelemetryExtension } from '@affine/core/blocksuite/extensions/telemetry'; -import { PeekViewService } from '@affine/core/modules/peek-view'; import { type ViewExtensionContext, ViewExtensionProvider, @@ -29,12 +25,7 @@ export class AffineCommonViewExtension extends ViewExtensionProvider< super.setup(context, options); const { framework } = options || {}; if (framework) { - context.register(patchPeekViewService(framework.get(PeekViewService))); - context.register([ - getFontConfigExtension(), - buildDocDisplayMetaExtension(framework), - ]); - context.register(getTelemetryExtension()); + context.register(buildDocDisplayMetaExtension(framework)); if (context.scope === 'edgeless' || context.scope === 'page') { context.register(patchFileSizeLimitExtension(framework)); } diff --git a/packages/frontend/core/src/blocksuite/manager/migrating-view.ts b/packages/frontend/core/src/blocksuite/manager/migrating-view.ts index e8a2e6fd93..ff74d60fcc 100644 --- a/packages/frontend/core/src/blocksuite/manager/migrating-view.ts +++ b/packages/frontend/core/src/blocksuite/manager/migrating-view.ts @@ -19,12 +19,22 @@ import { AffineEditorViewExtension, type AffineEditorViewOptions, } from '@affine/core/blocksuite/manager/editor-view'; +import { PeekViewService } from '@affine/core/modules/peek-view'; +import { DebugLogger } from '@affine/debug'; +import { mixpanel } from '@affine/track'; import { DatabaseViewExtension } from '@blocksuite/affine/blocks/database/view'; import { ParagraphViewExtension } from '@blocksuite/affine/blocks/paragraph/view'; +import type { + PeekOptions, + PeekViewService as BSPeekViewService, +} from '@blocksuite/affine/components/peek'; import { ViewExtensionManager } from '@blocksuite/affine/ext-loader'; import { getInternalViewExtensions } from '@blocksuite/affine/extensions/view'; +import { FoundationViewExtension } from '@blocksuite/affine/foundation/view'; +import { AffineCanvasTextFonts } from '@blocksuite/affine/shared/services'; import { LinkedDocViewExtension } from '@blocksuite/affine/widgets/linked-doc/view'; import type { FrameworkProvider } from '@toeverything/infra'; +import type { TemplateResult } from 'lit'; import { CodeBlockPreviewViewExtension } from './code-block-preview'; @@ -50,6 +60,8 @@ type Configure = { value: ViewExtensionManager; }; +const peekViewLogger = new DebugLogger('affine::patch-peek-view-service'); + class ViewProvider { static instance: ViewProvider | null = null; static getInstance() { @@ -129,6 +141,45 @@ class ViewProvider { }; private readonly _configureCommon = (framework?: FrameworkProvider) => { + const peekViewService = framework?.get(PeekViewService); + + this._manager.configure(FoundationViewExtension, { + telemetry: { + track: (eventName, props) => { + mixpanel.track(eventName, props); + }, + }, + fontConfig: AffineCanvasTextFonts.map(font => ({ + ...font, + url: environment.publicPath + 'fonts/' + font.url.split('/').pop(), + })), + peekView: !peekViewService + ? undefined + : ({ + peek: ( + element: { + target: HTMLElement; + docId: string; + blockIds?: string[]; + template?: TemplateResult; + }, + options?: PeekOptions + ) => { + peekViewLogger.debug('center peek', element); + const { template, target, ...props } = element; + + return peekViewService.peekView.open( + { + element: target, + docRef: props, + }, + template, + options?.abortSignal + ); + }, + } satisfies BSPeekViewService), + }); + this._manager.configure(AffineCommonViewExtension, { framework, });