feat(core): update slash menu entries with quick search (#7167)

Close BS-351

refactor `Link` and `Linked Doc` entry with `quickSearchService`
This commit is contained in:
L-Sun
2024-06-06 15:28:12 +00:00
parent f78416021a
commit 51429c957b

View File

@@ -14,11 +14,12 @@ import type {
import type { PeekViewService } from '@affine/core/modules/peek-view'; import type { PeekViewService } from '@affine/core/modules/peek-view';
import type { ActivePeekView } from '@affine/core/modules/peek-view/entities/peek-view'; import type { ActivePeekView } from '@affine/core/modules/peek-view/entities/peek-view';
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import type { BlockSpec } from '@blocksuite/block-std'; import type { BlockSpec, WidgetElement } from '@blocksuite/block-std';
import type { import {
AffineReference, type AffineReference,
ParagraphBlockService, AffineSlashMenuWidget,
RootService, type ParagraphBlockService,
type RootService,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { LitElement, type TemplateResult } from 'lit'; import { LitElement, type TemplateResult } from 'lit';
import React, { createElement, type ReactNode } from 'react'; import React, { createElement, type ReactNode } from 'react';
@@ -66,7 +67,8 @@ function patchSpecService<Spec extends BlockSpec>(
service: Spec extends BlockSpec<any, infer BlockService> service: Spec extends BlockSpec<any, infer BlockService>
? BlockService ? BlockService
: never : never
) => (() => void) | void ) => (() => void) | void,
onWidgetConnected?: (component: WidgetElement) => void
) { ) {
const oldSetup = spec.setup; const oldSetup = spec.setup;
spec.setup = (slots, disposableGroup) => { spec.setup = (slots, disposableGroup) => {
@@ -79,6 +81,13 @@ function patchSpecService<Spec extends BlockSpec>(
} }
}) })
); );
onWidgetConnected &&
disposableGroup.add(
slots.widgetConnected.on(({ component }) => {
onWidgetConnected(component);
})
);
}; };
return spec; return spec;
} }
@@ -271,45 +280,93 @@ export function patchQuickSearchService(
return specs; return specs;
} }
patchSpecService(rootSpec, pageService => { patchSpecService(
pageService.quickSearchService = { rootSpec,
async searchDoc(options) { pageService => {
let searchResult: SearchCallbackResult | null = null; pageService.quickSearchService = {
if (options.skipSelection) { async searchDoc(options) {
const query = options.userInput; let searchResult: SearchCallbackResult | null = null;
if (!query) { if (options.skipSelection) {
logger.error('No user input provided'); 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 { } else {
const searchedDoc = service.quickSearch searchResult = await service.quickSearch.search(options.userInput);
.getSearchedDocs(query) }
.at(0);
if (searchedDoc) { if (searchResult) {
searchResult = { if ('docId' in searchResult) {
docId: searchedDoc.doc.id, return searchResult;
blockId: searchedDoc.blockId, } else {
return {
userInput: searchResult.query,
action: 'insert', action: 'insert',
query,
}; };
} }
} }
} else { return null;
searchResult = await service.quickSearch.search(options.userInput); },
} };
},
(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 (!quickSearchService) return oldAction({ model, rootElement });
if ('docId' in searchResult) {
return searchResult; const result = await quickSearchService.searchDoc({});
} else { if (result === null) return;
return {
userInput: searchResult.query, if ('docId' in result) {
action: 'insert', 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; return specs;
} }