From 4bd43a698c9bf178061b537be3c09a4c5cd84060 Mon Sep 17 00:00:00 2001 From: donteatfriedrice Date: Mon, 20 Jan 2025 04:18:00 +0000 Subject: [PATCH] refactor(editor): refactor linkPreviewer as an extension and remove bookmark service (#9754) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [BS-2427](https://linear.app/affine-design/issue/BS-2427/移除-bookmark-block-service) [BS-2418](https://linear.app/affine-design/issue/BS-2418/linkpreviewer-重构成插件) --- .../block-bookmark/src/bookmark-block.ts | 6 +---- .../block-bookmark/src/bookmark-service.ts | 16 ------------ .../block-bookmark/src/bookmark-spec.ts | 2 -- .../affine/block-bookmark/src/effects.ts | 4 --- blocksuite/affine/block-bookmark/src/index.ts | 1 - blocksuite/affine/block-bookmark/src/utils.ts | 8 +++--- .../embed-github-service.ts | 13 ++++------ .../src/embed-github-block/utils.ts | 4 +-- .../embed-loom-block/embed-loom-service.ts | 6 ----- .../embed-youtube-service.ts | 13 ++++------ .../src/embed-youtube-block/utils.ts | 4 +-- blocksuite/affine/block-embed/src/index.ts | 4 --- .../affine/shared/src/services/index.ts | 1 + .../src/services/link-previewer-service.ts} | 26 +++++++++---------- blocksuite/blocks/src/_specs/common.ts | 2 ++ .../block-suite-editor/blocksuite-editor.tsx | 21 +++------------ .../workspace/detail/mobile-detail-page.tsx | 16 +++--------- 17 files changed, 42 insertions(+), 105 deletions(-) delete mode 100644 blocksuite/affine/block-bookmark/src/bookmark-service.ts rename blocksuite/affine/{block-embed/src/common/link-previewer.ts => shared/src/services/link-previewer-service.ts} (82%) diff --git a/blocksuite/affine/block-bookmark/src/bookmark-block.ts b/blocksuite/affine/block-bookmark/src/bookmark-block.ts index ab2d52a8b9..7a6404c65b 100644 --- a/blocksuite/affine/block-bookmark/src/bookmark-block.ts +++ b/blocksuite/affine/block-bookmark/src/bookmark-block.ts @@ -10,15 +10,11 @@ import { property, query } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; import { type StyleInfo, styleMap } from 'lit/directives/style-map.js'; -import type { BookmarkBlockService } from './bookmark-service.js'; import { refreshBookmarkUrlData } from './utils.js'; export const BOOKMARK_MIN_WIDTH = 450; -export class BookmarkBlockComponent extends CaptionedBlockComponent< - BookmarkBlockModel, - BookmarkBlockService -> { +export class BookmarkBlockComponent extends CaptionedBlockComponent { private _fetchAbortController?: AbortController; blockDraggable = true; diff --git a/blocksuite/affine/block-bookmark/src/bookmark-service.ts b/blocksuite/affine/block-bookmark/src/bookmark-service.ts deleted file mode 100644 index 9a72eb9e68..0000000000 --- a/blocksuite/affine/block-bookmark/src/bookmark-service.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { LinkPreviewer } from '@blocksuite/affine-block-embed'; -import { BookmarkBlockSchema } from '@blocksuite/affine-model'; -import { BlockService } from '@blocksuite/block-std'; - -export class BookmarkBlockService extends BlockService { - static override readonly flavour = BookmarkBlockSchema.model.flavour; - - private static readonly linkPreviewer = new LinkPreviewer(); - - static setLinkPreviewEndpoint = - BookmarkBlockService.linkPreviewer.setEndpoint; - - queryUrlData = (url: string, signal?: AbortSignal) => { - return BookmarkBlockService.linkPreviewer.query(url, signal); - }; -} diff --git a/blocksuite/affine/block-bookmark/src/bookmark-spec.ts b/blocksuite/affine/block-bookmark/src/bookmark-spec.ts index 9b2ef554a1..ec870ba6aa 100644 --- a/blocksuite/affine/block-bookmark/src/bookmark-spec.ts +++ b/blocksuite/affine/block-bookmark/src/bookmark-spec.ts @@ -7,12 +7,10 @@ import type { ExtensionType } from '@blocksuite/store'; import { literal } from 'lit/static-html.js'; import { BookmarkBlockAdapterExtensions } from './adapters/extension.js'; -import { BookmarkBlockService } from './bookmark-service.js'; import { commands } from './commands/index.js'; export const BookmarkBlockSpec: ExtensionType[] = [ FlavourExtension('affine:bookmark'), - BookmarkBlockService, CommandExtension(commands), BlockViewExtension('affine:bookmark', model => { return model.parent?.flavour === 'affine:surface' diff --git a/blocksuite/affine/block-bookmark/src/effects.ts b/blocksuite/affine/block-bookmark/src/effects.ts index 3f0751a2b9..6bcab7a6d0 100644 --- a/blocksuite/affine/block-bookmark/src/effects.ts +++ b/blocksuite/affine/block-bookmark/src/effects.ts @@ -1,6 +1,5 @@ import { BookmarkBlockComponent } from './bookmark-block'; import { BookmarkEdgelessBlockComponent } from './bookmark-edgeless-block'; -import type { BookmarkBlockService } from './bookmark-service'; import type { insertBookmarkCommand } from './commands/insert-bookmark'; import type { insertLinkByQuickSearchCommand } from './commands/insert-link-by-quick-search'; import { BookmarkCard } from './components/bookmark-card'; @@ -32,8 +31,5 @@ declare global { insertBookmark: typeof insertBookmarkCommand; insertLinkByQuickSearch: typeof insertLinkByQuickSearchCommand; } - interface BlockServices { - 'affine:bookmark': BookmarkBlockService; - } } } diff --git a/blocksuite/affine/block-bookmark/src/index.ts b/blocksuite/affine/block-bookmark/src/index.ts index e0162267ca..1698b867dc 100644 --- a/blocksuite/affine/block-bookmark/src/index.ts +++ b/blocksuite/affine/block-bookmark/src/index.ts @@ -1,5 +1,4 @@ export * from './adapters'; export * from './bookmark-block'; -export * from './bookmark-service'; export * from './bookmark-spec'; export * from './components'; diff --git a/blocksuite/affine/block-bookmark/src/utils.ts b/blocksuite/affine/block-bookmark/src/utils.ts index aa7d69856b..75fb44c73b 100644 --- a/blocksuite/affine/block-bookmark/src/utils.ts +++ b/blocksuite/affine/block-bookmark/src/utils.ts @@ -1,5 +1,5 @@ +import { LinkPreviewerService } from '@blocksuite/affine-shared/services'; import { isAbortError } from '@blocksuite/affine-shared/utils'; -import { assertExists } from '@blocksuite/global/utils'; import type { BookmarkBlockComponent } from './bookmark-block.js'; @@ -15,10 +15,8 @@ export async function refreshBookmarkUrlData( try { bookmarkElement.loading = true; - const queryUrlData = bookmarkElement.service?.queryUrlData; - assertExists(queryUrlData); - - const bookmarkUrlData = await queryUrlData( + const linkPreviewer = bookmarkElement.doc.get(LinkPreviewerService); + const bookmarkUrlData = await linkPreviewer.query( bookmarkElement.model.url, signal ); 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 7a619062c6..4f28bd6a5c 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 @@ -3,21 +3,18 @@ import { type EmbedGithubModel, EmbedGithubStyles, } from '@blocksuite/affine-model'; -import { EmbedOptionProvider } from '@blocksuite/affine-shared/services'; +import { + EmbedOptionProvider, + LinkPreviewerService, +} from '@blocksuite/affine-shared/services'; import { BlockService } from '@blocksuite/block-std'; -import { LinkPreviewer } from '../common/link-previewer.js'; import { githubUrlRegex } from './embed-github-model.js'; import { queryEmbedGithubApiData, queryEmbedGithubData } from './utils.js'; export class EmbedGithubBlockService extends BlockService { static override readonly flavour = EmbedGithubBlockSchema.model.flavour; - private static readonly linkPreviewer = new LinkPreviewer(); - - static setLinkPreviewEndpoint = - EmbedGithubBlockService.linkPreviewer.setEndpoint; - queryApiData = (embedGithubModel: EmbedGithubModel, signal?: AbortSignal) => { return queryEmbedGithubApiData(embedGithubModel, signal); }; @@ -25,7 +22,7 @@ export class EmbedGithubBlockService extends BlockService { queryUrlData = (embedGithubModel: EmbedGithubModel, signal?: AbortSignal) => { return queryEmbedGithubData( embedGithubModel, - EmbedGithubBlockService.linkPreviewer, + this.doc.get(LinkPreviewerService), signal ); }; diff --git a/blocksuite/affine/block-embed/src/embed-github-block/utils.ts b/blocksuite/affine/block-embed/src/embed-github-block/utils.ts index 9aca6a945c..b21f9ea8e7 100644 --- a/blocksuite/affine/block-embed/src/embed-github-block/utils.ts +++ b/blocksuite/affine/block-embed/src/embed-github-block/utils.ts @@ -2,11 +2,11 @@ import type { EmbedGithubBlockUrlData, EmbedGithubModel, } from '@blocksuite/affine-model'; +import type { LinkPreviewerService } from '@blocksuite/affine-shared/services'; import { isAbortError } from '@blocksuite/affine-shared/utils'; import { assertExists } from '@blocksuite/global/utils'; import { nothing } from 'lit'; -import type { LinkPreviewer } from '../common/link-previewer.js'; import type { EmbedGithubBlockComponent } from './embed-github-block.js'; import { GithubIssueClosedFailureIcon, @@ -20,7 +20,7 @@ import { export async function queryEmbedGithubData( embedGithubModel: EmbedGithubModel, - linkPreviewer: LinkPreviewer, + linkPreviewer: LinkPreviewerService, signal?: AbortSignal ): Promise> { const [githubApiData, openGraphData] = await Promise.all([ 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 1ff401afd8..4a83b2a511 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 @@ -6,18 +6,12 @@ import { import { EmbedOptionProvider } from '@blocksuite/affine-shared/services'; import { BlockService } from '@blocksuite/block-std'; -import { LinkPreviewer } from '../common/link-previewer.js'; import { loomUrlRegex } from './embed-loom-model.js'; import { queryEmbedLoomData } from './utils.js'; export class EmbedLoomBlockService extends BlockService { static override readonly flavour = EmbedLoomBlockSchema.model.flavour; - private static readonly linkPreviewer = new LinkPreviewer(); - - static setLinkPreviewEndpoint = - EmbedLoomBlockService.linkPreviewer.setEndpoint; - queryUrlData = (embedLoomModel: EmbedLoomModel, signal?: AbortSignal) => { return queryEmbedLoomData(embedLoomModel, signal); }; 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 4500a45998..944e5b2e3f 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 @@ -3,28 +3,25 @@ import { type EmbedYoutubeModel, EmbedYoutubeStyles, } from '@blocksuite/affine-model'; -import { EmbedOptionProvider } from '@blocksuite/affine-shared/services'; +import { + EmbedOptionProvider, + LinkPreviewerService, +} from '@blocksuite/affine-shared/services'; import { BlockService } from '@blocksuite/block-std'; -import { LinkPreviewer } from '../common/link-previewer.js'; import { youtubeUrlRegex } from './embed-youtube-model.js'; import { queryEmbedYoutubeData } from './utils.js'; export class EmbedYoutubeBlockService extends BlockService { static override readonly flavour = EmbedYoutubeBlockSchema.model.flavour; - private static readonly linkPreviewer = new LinkPreviewer(); - - static setLinkPreviewEndpoint = - EmbedYoutubeBlockService.linkPreviewer.setEndpoint; - queryUrlData = ( embedYoutubeModel: EmbedYoutubeModel, signal?: AbortSignal ) => { return queryEmbedYoutubeData( embedYoutubeModel, - EmbedYoutubeBlockService.linkPreviewer, + this.doc.get(LinkPreviewerService), signal ); }; diff --git a/blocksuite/affine/block-embed/src/embed-youtube-block/utils.ts b/blocksuite/affine/block-embed/src/embed-youtube-block/utils.ts index 5432dbb65b..d2349a5259 100644 --- a/blocksuite/affine/block-embed/src/embed-youtube-block/utils.ts +++ b/blocksuite/affine/block-embed/src/embed-youtube-block/utils.ts @@ -2,15 +2,15 @@ import type { EmbedYoutubeBlockUrlData, EmbedYoutubeModel, } from '@blocksuite/affine-model'; +import type { LinkPreviewerService } from '@blocksuite/affine-shared/services'; import { isAbortError } from '@blocksuite/affine-shared/utils'; import { assertExists } from '@blocksuite/global/utils'; -import type { LinkPreviewer } from '../common/link-previewer.js'; import type { EmbedYoutubeBlockComponent } from './embed-youtube-block.js'; export async function queryEmbedYoutubeData( embedYoutubeModel: EmbedYoutubeModel, - linkPreviewer: LinkPreviewer, + linkPreviewer: LinkPreviewerService, signal?: AbortSignal ): Promise> { const url = embedYoutubeModel.url; diff --git a/blocksuite/affine/block-embed/src/index.ts b/blocksuite/affine/block-embed/src/index.ts index faa54643da..3ceed9ecd5 100644 --- a/blocksuite/affine/block-embed/src/index.ts +++ b/blocksuite/affine/block-embed/src/index.ts @@ -23,10 +23,6 @@ export { createEmbedBlockMarkdownAdapterMatcher } from './common/adapters/markdo export { createEmbedBlockPlainTextAdapterMatcher } from './common/adapters/plain-text'; export { EmbedBlockComponent } from './common/embed-block-element'; export { insertEmbedCard } from './common/insert-embed-card.js'; -export { - LinkPreviewer, - type LinkPreviewResponseData, -} from './common/link-previewer.js'; export * from './common/render-linked-doc'; export { toEdgelessEmbedBlock } from './common/to-edgeless-embed-block'; export * from './common/utils'; diff --git a/blocksuite/affine/shared/src/services/index.ts b/blocksuite/affine/shared/src/services/index.ts index b0f2da307c..6cf3f6630f 100644 --- a/blocksuite/affine/shared/src/services/index.ts +++ b/blocksuite/affine/shared/src/services/index.ts @@ -7,6 +7,7 @@ export * from './embed-option-service'; export * from './feature-flag-service'; export * from './font-loader'; export * from './generate-url-service'; +export * from './link-previewer-service'; export * from './native-clipboard-service'; export * from './notification-service'; export * from './open-doc-config'; diff --git a/blocksuite/affine/block-embed/src/common/link-previewer.ts b/blocksuite/affine/shared/src/services/link-previewer-service.ts similarity index 82% rename from blocksuite/affine/block-embed/src/common/link-previewer.ts rename to blocksuite/affine/shared/src/services/link-previewer-service.ts index 45a6c26461..bef4fc1dfd 100644 --- a/blocksuite/affine/block-embed/src/common/link-previewer.ts +++ b/blocksuite/affine/shared/src/services/link-previewer-service.ts @@ -1,7 +1,9 @@ import type { LinkPreviewData } from '@blocksuite/affine-model'; -import { DEFAULT_LINK_PREVIEW_ENDPOINT } from '@blocksuite/affine-shared/consts'; -import { isAbortError } from '@blocksuite/affine-shared/utils'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; +import { StoreExtension } from '@blocksuite/store'; + +import { DEFAULT_LINK_PREVIEW_ENDPOINT } from '../consts'; +import { isAbortError } from '../utils/is-abort-error'; export type LinkPreviewResponseData = { url: string; @@ -16,7 +18,9 @@ export type LinkPreviewResponseData = { favicons?: string[]; }; -export class LinkPreviewer { +export class LinkPreviewerService extends StoreExtension { + static override key = 'link-previewer'; + private _endpoint = DEFAULT_LINK_PREVIEW_ENDPOINT; query = async ( @@ -77,23 +81,19 @@ export class LinkPreviewer { const data: LinkPreviewResponseData = await response.json(); return { - title: data.title ? this._getStringFromHTML(data.title) : null, - description: data.description - ? this._getStringFromHTML(data.description) - : null, + title: data.title ?? null, + description: data.description ?? null, icon: data.favicons?.[0], image: data.images?.[0], }; } }; + get endpoint() { + return this._endpoint; + } + setEndpoint = (endpoint: string) => { this._endpoint = endpoint; }; - - private _getStringFromHTML(html: string) { - const div = document.createElement('div'); - div.innerHTML = html; - return div.textContent; - } } diff --git a/blocksuite/blocks/src/_specs/common.ts b/blocksuite/blocks/src/_specs/common.ts index fed967cf4d..cd925ae912 100644 --- a/blocksuite/blocks/src/_specs/common.ts +++ b/blocksuite/blocks/src/_specs/common.ts @@ -40,6 +40,7 @@ import { EditPropsStore, FeatureFlagService, FontLoaderService, + LinkPreviewerService, } from '@blocksuite/affine-shared/services'; import { BlockSelectionExtension, @@ -99,4 +100,5 @@ export const StoreExtensions: ExtensionType[] = [ HighlightSelectionExtension, ImageSelectionExtension, DatabaseSelectionExtension, + LinkPreviewerService, ]; diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/blocksuite-editor.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-editor/blocksuite-editor.tsx index 237fd53567..9d9207b1bb 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/blocksuite-editor.tsx +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/blocksuite-editor.tsx @@ -1,13 +1,10 @@ import { useRefEffect } from '@affine/component'; import { EditorLoading } from '@affine/component/page-detail-skeleton'; import { - BookmarkBlockService, customImageProxyMiddleware, type DocMode, - EmbedGithubBlockService, - EmbedLoomBlockService, - EmbedYoutubeBlockService, ImageBlockService, + LinkPreviewerService, } from '@blocksuite/affine/blocks'; import { DisposableGroup } from '@blocksuite/affine/global/utils'; import type { AffineEditorContainer } from '@blocksuite/affine/presets'; @@ -71,19 +68,9 @@ const BlockSuiteEditorImpl = ({ ); ImageBlockService.setImageProxyURL(BUILD_CONFIG.imageProxyUrl); - // provide link preview endpoint to blocksuite - BookmarkBlockService.setLinkPreviewEndpoint( - BUILD_CONFIG.linkPreviewUrl - ); - EmbedGithubBlockService.setLinkPreviewEndpoint( - BUILD_CONFIG.linkPreviewUrl - ); - EmbedYoutubeBlockService.setLinkPreviewEndpoint( - BUILD_CONFIG.linkPreviewUrl - ); - EmbedLoomBlockService.setLinkPreviewEndpoint( - BUILD_CONFIG.linkPreviewUrl - ); + editor.host?.doc + .get(LinkPreviewerService) + .setEndpoint(BUILD_CONFIG.linkPreviewUrl); return editor.host?.updateComplete; }) diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx index c53680ecbe..fe123051cd 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx @@ -22,12 +22,9 @@ import { ViewService } from '@affine/core/modules/workbench/services/view'; import { WorkspaceService } from '@affine/core/modules/workspace'; import { i18nTime } from '@affine/i18n'; import { - BookmarkBlockService, customImageProxyMiddleware, - EmbedGithubBlockService, - EmbedLoomBlockService, - EmbedYoutubeBlockService, ImageBlockService, + LinkPreviewerService, RefNodeSlotsProvider, } from '@blocksuite/affine/blocks'; import { DisposableGroup } from '@blocksuite/affine/global/utils'; @@ -159,14 +156,9 @@ const DetailPageImpl = () => { ImageBlockService.setImageProxyURL(BUILD_CONFIG.imageProxyUrl); // provide link preview endpoint to blocksuite - BookmarkBlockService.setLinkPreviewEndpoint(BUILD_CONFIG.linkPreviewUrl); - EmbedGithubBlockService.setLinkPreviewEndpoint( - BUILD_CONFIG.linkPreviewUrl - ); - EmbedYoutubeBlockService.setLinkPreviewEndpoint( - BUILD_CONFIG.linkPreviewUrl - ); - EmbedLoomBlockService.setLinkPreviewEndpoint(BUILD_CONFIG.linkPreviewUrl); + editorHost?.doc + .get(LinkPreviewerService) + .setEndpoint(BUILD_CONFIG.linkPreviewUrl); // provide page mode and updated date to blocksuite const refNodeService = editorHost?.std.getOptional(RefNodeSlotsProvider);