From 51429c957bd61d6c107bf735929eab4886e4b519 Mon Sep 17 00:00:00 2001 From: L-Sun Date: Thu, 6 Jun 2024 15:28:12 +0000 Subject: [PATCH] feat(core): update slash menu entries with quick search (#7167) Close BS-351 refactor `Link` and `Linked Doc` entry with `quickSearchService` --- .../specs/custom/spec-patchers.tsx | 131 +++++++++++++----- 1 file changed, 94 insertions(+), 37 deletions(-) diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx index d13dd97899..a9c36ad7d8 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx @@ -14,11 +14,12 @@ import type { import type { PeekViewService } from '@affine/core/modules/peek-view'; import type { ActivePeekView } from '@affine/core/modules/peek-view/entities/peek-view'; import { DebugLogger } from '@affine/debug'; -import type { BlockSpec } from '@blocksuite/block-std'; -import type { - AffineReference, - ParagraphBlockService, - RootService, +import type { BlockSpec, WidgetElement } from '@blocksuite/block-std'; +import { + type AffineReference, + AffineSlashMenuWidget, + type ParagraphBlockService, + type RootService, } from '@blocksuite/blocks'; import { LitElement, type TemplateResult } from 'lit'; import React, { createElement, type ReactNode } from 'react'; @@ -66,7 +67,8 @@ function patchSpecService( service: Spec extends BlockSpec ? BlockService : never - ) => (() => void) | void + ) => (() => void) | void, + onWidgetConnected?: (component: WidgetElement) => void ) { const oldSetup = spec.setup; spec.setup = (slots, disposableGroup) => { @@ -79,6 +81,13 @@ function patchSpecService( } }) ); + + onWidgetConnected && + disposableGroup.add( + slots.widgetConnected.on(({ component }) => { + onWidgetConnected(component); + }) + ); }; return spec; } @@ -271,45 +280,93 @@ export function patchQuickSearchService( return specs; } - patchSpecService(rootSpec, pageService => { - pageService.quickSearchService = { - async searchDoc(options) { - let searchResult: SearchCallbackResult | null = null; - if (options.skipSelection) { - const query = options.userInput; - if (!query) { - logger.error('No user input provided'); + patchSpecService( + rootSpec, + pageService => { + pageService.quickSearchService = { + async searchDoc(options) { + let searchResult: SearchCallbackResult | null = null; + if (options.skipSelection) { + const query = options.userInput; + if (!query) { + logger.error('No user input provided'); + } else { + const searchedDoc = service.quickSearch + .getSearchedDocs(query) + .at(0); + if (searchedDoc) { + searchResult = { + docId: searchedDoc.doc.id, + blockId: searchedDoc.blockId, + action: 'insert', + query, + }; + } + } } else { - const searchedDoc = service.quickSearch - .getSearchedDocs(query) - .at(0); - if (searchedDoc) { - searchResult = { - docId: searchedDoc.doc.id, - blockId: searchedDoc.blockId, + searchResult = await service.quickSearch.search(options.userInput); + } + + if (searchResult) { + if ('docId' in searchResult) { + return searchResult; + } else { + return { + userInput: searchResult.query, action: 'insert', - query, }; } } - } else { - searchResult = await service.quickSearch.search(options.userInput); - } + return null; + }, + }; + }, + (component: WidgetElement) => { + if (component instanceof AffineSlashMenuWidget) { + component.config.items.forEach(item => { + if ( + 'action' in item && + (item.name === 'Linked Doc' || item.name === 'Link') + ) { + const oldAction = item.action; + item.action = async ({ model, rootElement }) => { + const { host, service, std } = rootElement; + const { quickSearchService } = service; - if (searchResult) { - if ('docId' in searchResult) { - return searchResult; - } else { - return { - userInput: searchResult.query, - action: 'insert', + if (!quickSearchService) return oldAction({ model, rootElement }); + + const result = await quickSearchService.searchDoc({}); + if (result === null) return; + + if ('docId' in result) { + const linkedDoc = std.collection.getDoc(result.docId); + if (!linkedDoc) return; + + host.doc.addSiblingBlocks(model, [ + { + flavour: 'affine:embed-linked-doc', + pageId: linkedDoc.id, + }, + ]); + } else if ('userInput' in result) { + const embedOptions = service.getEmbedBlockOptions( + result.userInput + ); + if (!embedOptions) return; + + host.doc.addSiblingBlocks(model, [ + { + flavour: embedOptions.flavour, + url: result.userInput, + }, + ]); + } }; } - } - return null; - }, - }; - }); + }); + } + } + ); return specs; }