From 6353e72078089d2bf6362819f274868348d0d434 Mon Sep 17 00:00:00 2001 From: Saul-Mirone Date: Sat, 1 Mar 2025 16:40:18 +0000 Subject: [PATCH] feat(editor): add embed option config extension (#10540) This PR implements a significant refactoring of the embed block services across multiple components (Figma, GitHub, Loom, and YouTube) in the BlockSuite codebase. Here are the key changes: 1. **Architecture Change**: - Moves from a dynamic registration pattern to a more declarative configuration approach - Replaces `EmbedOptionProvider.registerEmbedBlockOptions()` calls with a new `EmbedOptionConfig` factory function 2. **Service Refactoring**: - For each embed block type (Figma, GitHub, Loom, YouTube): - Separates configuration from service logic - Creates new `EmbedBlockOptionConfig` constants using the new `EmbedOptionConfig` factory - Removes the `mounted()` lifecycle hook from services where it was only used for registration 3. **Core Changes**: - In `embed-option-service.ts`: - Introduces new `EmbedOptionConfigIdentifier` for dependency injection - Adds `EmbedOptionConfig` factory function for creating embed configurations - Updates `EmbedOptionService` constructor to automatically register configurations - Modifies DI setup to include `StdIdentifier` dependency 4. **Spec Updates**: - Updates all block specs to include the new configuration objects - Maintains existing functionality while using the new pattern The main benefit of this refactoring is: - More declarative configuration approach - Better separation of concerns - Reduced runtime registration code - More predictable initialization of embed options --- .../embed-figma-block/embed-figma-block.ts | 6 +---- .../embed-figma-block/embed-figma-service.ts | 23 ++++++----------- .../src/embed-figma-block/embed-figma-spec.ts | 4 +-- .../embed-github-service.ts | 20 ++++++--------- .../embed-github-block/embed-github-spec.ts | 6 ++++- .../embed-loom-block/embed-loom-service.ts | 20 ++++++--------- .../src/embed-loom-block/embed-loom-spec.ts | 6 ++++- .../embed-youtube-service.ts | 20 ++++++--------- .../embed-youtube-block/embed-youtube-spec.ts | 6 ++++- .../src/services/embed-option-service.ts | 25 +++++++++++++++++-- 10 files changed, 72 insertions(+), 64 deletions(-) diff --git a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts index 91df6d9e3..c52d8be42 100644 --- a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts +++ b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts @@ -10,13 +10,9 @@ import { classMap } from 'lit/directives/class-map.js'; import { styleMap } from 'lit/directives/style-map.js'; import { EmbedBlockComponent } from '../common/embed-block-element.js'; -import type { EmbedFigmaBlockService } from './embed-figma-service.js'; import { FigmaIcon, styles } from './styles.js'; -export class EmbedFigmaBlockComponent extends EmbedBlockComponent< - EmbedFigmaModel, - EmbedFigmaBlockService -> { +export class EmbedFigmaBlockComponent extends EmbedBlockComponent { static override styles = styles; override _cardStyle: (typeof EmbedFigmaStyles)[number] = 'figma'; diff --git a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-service.ts b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-service.ts index 9847f472b..6b34da6f8 100644 --- a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-service.ts +++ b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-service.ts @@ -2,22 +2,13 @@ import { EmbedFigmaBlockSchema, EmbedFigmaStyles, } from '@blocksuite/affine-model'; -import { EmbedOptionProvider } from '@blocksuite/affine-shared/services'; -import { BlockService } from '@blocksuite/block-std'; +import { EmbedOptionConfig } from '@blocksuite/affine-shared/services'; import { figmaUrlRegex } from './embed-figma-model.js'; -export class EmbedFigmaBlockService extends BlockService { - static override readonly flavour = EmbedFigmaBlockSchema.model.flavour; - - override mounted() { - super.mounted(); - - this.std.get(EmbedOptionProvider).registerEmbedBlockOptions({ - flavour: this.flavour, - urlRegex: figmaUrlRegex, - styles: EmbedFigmaStyles, - viewType: 'embed', - }); - } -} +export const EmbedFigmaBlockOptionConfig = EmbedOptionConfig({ + flavour: EmbedFigmaBlockSchema.model.flavour, + urlRegex: figmaUrlRegex, + styles: EmbedFigmaStyles, + viewType: 'embed', +}); diff --git a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-spec.ts b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-spec.ts index 7aab6f8b2..680c1aeb1 100644 --- a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-spec.ts +++ b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-spec.ts @@ -3,15 +3,15 @@ import type { ExtensionType } from '@blocksuite/store'; import { literal } from 'lit/static-html.js'; import { EmbedFigmaBlockAdapterExtensions } from './adapters/extension.js'; -import { EmbedFigmaBlockService } from './embed-figma-service.js'; +import { EmbedFigmaBlockOptionConfig } from './embed-figma-service.js'; export const EmbedFigmaBlockSpec: ExtensionType[] = [ FlavourExtension('affine:embed-figma'), - EmbedFigmaBlockService, BlockViewExtension('affine:embed-figma', model => { return model.parent?.flavour === 'affine:surface' ? literal`affine-embed-edgeless-figma-block` : literal`affine-embed-figma-block`; }), EmbedFigmaBlockAdapterExtensions, + EmbedFigmaBlockOptionConfig, ].flat(); diff --git a/blocksuite/affine/block-embed/src/embed-github-block/embed-github-service.ts b/blocksuite/affine/block-embed/src/embed-github-block/embed-github-service.ts index 4f28bd6a5..0f3d257b8 100644 --- a/blocksuite/affine/block-embed/src/embed-github-block/embed-github-service.ts +++ b/blocksuite/affine/block-embed/src/embed-github-block/embed-github-service.ts @@ -4,7 +4,7 @@ import { EmbedGithubStyles, } from '@blocksuite/affine-model'; import { - EmbedOptionProvider, + EmbedOptionConfig, LinkPreviewerService, } from '@blocksuite/affine-shared/services'; import { BlockService } from '@blocksuite/block-std'; @@ -26,15 +26,11 @@ export class EmbedGithubBlockService extends BlockService { signal ); }; - - override mounted() { - super.mounted(); - - this.std.get(EmbedOptionProvider).registerEmbedBlockOptions({ - flavour: this.flavour, - urlRegex: githubUrlRegex, - styles: EmbedGithubStyles, - viewType: 'card', - }); - } } + +export const EmbedGithubBlockOptionConfig = EmbedOptionConfig({ + flavour: EmbedGithubBlockSchema.model.flavour, + urlRegex: githubUrlRegex, + styles: EmbedGithubStyles, + viewType: 'card', +}); diff --git a/blocksuite/affine/block-embed/src/embed-github-block/embed-github-spec.ts b/blocksuite/affine/block-embed/src/embed-github-block/embed-github-spec.ts index ac8834d22..90635abbb 100644 --- a/blocksuite/affine/block-embed/src/embed-github-block/embed-github-spec.ts +++ b/blocksuite/affine/block-embed/src/embed-github-block/embed-github-spec.ts @@ -3,7 +3,10 @@ import type { ExtensionType } from '@blocksuite/store'; import { literal } from 'lit/static-html.js'; import { EmbedGithubBlockAdapterExtensions } from './adapters/extension.js'; -import { EmbedGithubBlockService } from './embed-github-service.js'; +import { + EmbedGithubBlockOptionConfig, + EmbedGithubBlockService, +} from './embed-github-service.js'; export const EmbedGithubBlockSpec: ExtensionType[] = [ FlavourExtension('affine:embed-github'), @@ -14,4 +17,5 @@ export const EmbedGithubBlockSpec: ExtensionType[] = [ : literal`affine-embed-github-block`; }), EmbedGithubBlockAdapterExtensions, + EmbedGithubBlockOptionConfig, ].flat(); diff --git a/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-service.ts b/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-service.ts index 4a83b2a51..830bc75ff 100644 --- a/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-service.ts +++ b/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-service.ts @@ -3,7 +3,7 @@ import { type EmbedLoomModel, EmbedLoomStyles, } from '@blocksuite/affine-model'; -import { EmbedOptionProvider } from '@blocksuite/affine-shared/services'; +import { EmbedOptionConfig } from '@blocksuite/affine-shared/services'; import { BlockService } from '@blocksuite/block-std'; import { loomUrlRegex } from './embed-loom-model.js'; @@ -15,15 +15,11 @@ export class EmbedLoomBlockService extends BlockService { queryUrlData = (embedLoomModel: EmbedLoomModel, signal?: AbortSignal) => { return queryEmbedLoomData(embedLoomModel, signal); }; - - override mounted() { - super.mounted(); - - this.std.get(EmbedOptionProvider).registerEmbedBlockOptions({ - flavour: this.flavour, - urlRegex: loomUrlRegex, - styles: EmbedLoomStyles, - viewType: 'embed', - }); - } } + +export const EmbedLoomBlockOptionConfig = EmbedOptionConfig({ + flavour: EmbedLoomBlockSchema.model.flavour, + urlRegex: loomUrlRegex, + styles: EmbedLoomStyles, + viewType: 'embed', +}); diff --git a/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-spec.ts b/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-spec.ts index 0d873ad41..4a1668a0f 100644 --- a/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-spec.ts +++ b/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-spec.ts @@ -3,7 +3,10 @@ import type { ExtensionType } from '@blocksuite/store'; import { literal } from 'lit/static-html.js'; import { EmbedLoomBlockAdapterExtensions } from './adapters/extension.js'; -import { EmbedLoomBlockService } from './embed-loom-service.js'; +import { + EmbedLoomBlockOptionConfig, + EmbedLoomBlockService, +} from './embed-loom-service.js'; export const EmbedLoomBlockSpec: ExtensionType[] = [ FlavourExtension('affine:embed-loom'), @@ -14,4 +17,5 @@ export const EmbedLoomBlockSpec: ExtensionType[] = [ : literal`affine-embed-loom-block`; }), EmbedLoomBlockAdapterExtensions, + EmbedLoomBlockOptionConfig, ].flat(); diff --git a/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-service.ts b/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-service.ts index 944e5b2e3..316c75212 100644 --- a/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-service.ts +++ b/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-service.ts @@ -4,7 +4,7 @@ import { EmbedYoutubeStyles, } from '@blocksuite/affine-model'; import { - EmbedOptionProvider, + EmbedOptionConfig, LinkPreviewerService, } from '@blocksuite/affine-shared/services'; import { BlockService } from '@blocksuite/block-std'; @@ -25,15 +25,11 @@ export class EmbedYoutubeBlockService extends BlockService { signal ); }; - - override mounted() { - super.mounted(); - - this.std.get(EmbedOptionProvider).registerEmbedBlockOptions({ - flavour: this.flavour, - urlRegex: youtubeUrlRegex, - styles: EmbedYoutubeStyles, - viewType: 'embed', - }); - } } + +export const EmbedYoutubeBlockOptionConfig = EmbedOptionConfig({ + flavour: EmbedYoutubeBlockSchema.model.flavour, + urlRegex: youtubeUrlRegex, + styles: EmbedYoutubeStyles, + viewType: 'embed', +}); diff --git a/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-spec.ts b/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-spec.ts index a306c2fc3..f10e9fb94 100644 --- a/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-spec.ts +++ b/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-spec.ts @@ -3,7 +3,10 @@ import type { ExtensionType } from '@blocksuite/store'; import { literal } from 'lit/static-html.js'; import { EmbedYoutubeBlockAdapterExtensions } from './adapters/extension.js'; -import { EmbedYoutubeBlockService } from './embed-youtube-service.js'; +import { + EmbedYoutubeBlockOptionConfig, + EmbedYoutubeBlockService, +} from './embed-youtube-service.js'; export const EmbedYoutubeBlockSpec: ExtensionType[] = [ FlavourExtension('affine:embed-youtube'), @@ -14,4 +17,5 @@ export const EmbedYoutubeBlockSpec: ExtensionType[] = [ : literal`affine-embed-youtube-block`; }), EmbedYoutubeBlockAdapterExtensions, + EmbedYoutubeBlockOptionConfig, ].flat(); diff --git a/blocksuite/affine/shared/src/services/embed-option-service.ts b/blocksuite/affine/shared/src/services/embed-option-service.ts index aa0202161..1dd0a1237 100644 --- a/blocksuite/affine/shared/src/services/embed-option-service.ts +++ b/blocksuite/affine/shared/src/services/embed-option-service.ts @@ -1,7 +1,8 @@ import type { EmbedCardStyle } from '@blocksuite/affine-model'; +import { type BlockStdScope, StdIdentifier } from '@blocksuite/block-std'; import type { Container } from '@blocksuite/global/di'; import { createIdentifier } from '@blocksuite/global/di'; -import { Extension } from '@blocksuite/store'; +import { Extension, type ExtensionType } from '@blocksuite/store'; export type EmbedOptions = { flavour: string; @@ -19,12 +20,32 @@ export const EmbedOptionProvider = createIdentifier( 'AffineEmbedOptionProvider' ); +export const EmbedOptionConfigIdentifier = createIdentifier( + 'AffineEmbedOptionConfig' +); + +export const EmbedOptionConfig = (options: EmbedOptions): ExtensionType => { + return { + setup: di => { + di.addImpl(EmbedOptionConfigIdentifier(options.flavour), options); + }, + }; +}; + export class EmbedOptionService extends Extension implements EmbedOptionProvider { private readonly _embedBlockRegistry = new Set(); + constructor(readonly std: BlockStdScope) { + super(); + const configs = this.std.provider.getAll(EmbedOptionConfigIdentifier); + configs.forEach(value => { + this.registerEmbedBlockOptions(value); + }); + } + getEmbedBlockOptions = (url: string): EmbedOptions | null => { const entries = this._embedBlockRegistry.entries(); for (const [options] of entries) { @@ -39,6 +60,6 @@ export class EmbedOptionService }; static override setup(di: Container) { - di.addImpl(EmbedOptionProvider, EmbedOptionService); + di.addImpl(EmbedOptionProvider, EmbedOptionService, [StdIdentifier]); } }