From 59f4f1e51daa4381c0c3f5f48d035954935c9546 Mon Sep 17 00:00:00 2001 From: pengx17 Date: Thu, 12 Dec 2024 10:17:15 +0000 Subject: [PATCH] fix(core): at menu results use indexer data source (#9123) fix AF-1942 ![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/51f7d691-4e6c-44e7-92ac-944b0d886683.png) --- .../core/src/modules/at-menu-config/index.ts | 2 + .../modules/at-menu-config/services/index.ts | 101 +++++++++++++++--- 2 files changed, 87 insertions(+), 16 deletions(-) diff --git a/packages/frontend/core/src/modules/at-menu-config/index.ts b/packages/frontend/core/src/modules/at-menu-config/index.ts index d6500afa16..32a89961b5 100644 --- a/packages/frontend/core/src/modules/at-menu-config/index.ts +++ b/packages/frontend/core/src/modules/at-menu-config/index.ts @@ -7,6 +7,7 @@ import { import { WorkspaceDialogService } from '../dialogs'; import { DocDisplayMetaService } from '../doc-display-meta'; +import { DocsSearchService } from '../docs-search'; import { EditorSettingService } from '../editor-setting'; import { JournalService } from '../journal'; import { RecentDocsService } from '../quicksearch'; @@ -23,5 +24,6 @@ export function configAtMenuConfigModule(framework: Framework) { RecentDocsService, EditorSettingService, DocsService, + DocsSearchService, ]); } diff --git a/packages/frontend/core/src/modules/at-menu-config/services/index.ts b/packages/frontend/core/src/modules/at-menu-config/services/index.ts index e55c45205e..6679d8fa94 100644 --- a/packages/frontend/core/src/modules/at-menu-config/services/index.ts +++ b/packages/frontend/core/src/modules/at-menu-config/services/index.ts @@ -22,9 +22,11 @@ import type { DocsService, WorkspaceService } from '@toeverything/infra'; import { Service } from '@toeverything/infra'; import { cssVarV2 } from '@toeverything/theme/v2'; import { html } from 'lit'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import type { WorkspaceDialogService } from '../../dialogs'; import type { DocDisplayMetaService } from '../../doc-display-meta'; +import type { DocsSearchService } from '../../docs-search'; import type { EditorSettingService } from '../../editor-setting'; import { type JournalService, suggestJournalDate } from '../../journal'; import type { RecentDocsService } from '../../quicksearch'; @@ -39,7 +41,8 @@ export class AtMenuConfigService extends Service { private readonly dialogService: WorkspaceDialogService, private readonly recentDocsService: RecentDocsService, private readonly editorSettingService: EditorSettingService, - private readonly docsService: DocsService + private readonly docsService: DocsService, + private readonly docsSearch: DocsSearchService ) { super(); } @@ -72,22 +75,14 @@ export class AtMenuConfigService extends Service { !!this.journalService.journalDate$(d.id).value; const docItems = signal([]); - const showRecent = query.trim().length === 0; - - // recent docs should be at the top - const docMetas = showRecent - ? this.recentDocsService - .getRecentDocs() - .map(record => { - return rawMetas.find(meta => meta.id === record.id); - }) - .filter((m): m is DocMeta => !!m) - : rawMetas; - const docDisplayMetaService = this.docDisplayMetaService; - const toDocItem = (meta: DocMeta): LinkedMenuItem | null => { - if (isJournal(meta) && !meta.updatedDate) { + type DocMetaWithHighlights = DocMeta & { + highlights: string | undefined; + }; + + const toDocItem = (meta: DocMetaWithHighlights): LinkedMenuItem | null => { + if (isJournal(meta)) { return null; } @@ -108,7 +103,7 @@ export class AtMenuConfigService extends Service { } return { - name: title, + name: meta.highlights ? html`${unsafeHTML(meta.highlights)}` : title, key: meta.id, icon: docDisplayMetaService .icon$(meta.id, { @@ -124,7 +119,29 @@ export class AtMenuConfigService extends Service { }; }; + const showRecent = query.trim().length === 0; + (async () => { + const docMetas = ( + showRecent + ? this.recentDocsService.getRecentDocs() + : await this.searchDocs(query) + ) + .map(doc => { + const meta = rawMetas.find(meta => meta.id === doc.id); + + if (!meta) { + return null; + } + + const highlights = 'highlights' in doc ? doc.highlights : undefined; + return { + ...meta, + highlights, + }; + }) + .filter((m): m is DocMetaWithHighlights => !!m); + for (const [index, meta] of docMetas.entries()) { if (abortSignal.aborted) { return; @@ -370,4 +387,56 @@ export class AtMenuConfigService extends Service { }, }; } + + // only search docs by title, excluding blocks + private async searchDocs(query: string) { + const { buckets } = await this.docsSearch.indexer.blockIndex.aggregate( + { + type: 'boolean', + occur: 'must', + queries: [ + { + type: 'match', + field: 'content', + match: query, + }, + { + type: 'boolean', + occur: 'should', + queries: [ + { + type: 'match', + field: 'flavour', + match: 'affine:page', + }, + ], + }, + ], + }, + 'docId', + { + hits: { + fields: ['docId', 'content'], + pagination: { + limit: 1, + }, + highlights: [ + { + field: 'content', + before: ``, + end: '', + }, + ], + }, + } + ); + const result = buckets.map(bucket => { + return { + id: bucket.key, + title: bucket.hits.nodes[0].fields.content, + highlights: bucket.hits.nodes[0].highlights.content[0], + }; + }); + return result; + } }