import type { CachedHistoryListRow } from '../storage/cachedHistoryStore'; import { initQueryHistoryDropdown } from './queryHistory'; /** IndexedDB MRU 列表在内存中的镜像,供 {@link initQueryHistoryDropdown} 的同步 `getHistoryEntries` 使用 */ export function createMruListMirror(loadList: () => Promise): { getEntries: () => CachedHistoryListRow[]; refresh: () => Promise; } { let rows: CachedHistoryListRow[] = []; return { getEntries: () => rows, refresh: async () => { rows = await loadList(); }, }; } export type CachedHistorySelectContext = { /** 刷新内存中的 MRU 列表镜像(与打开下拉时一致) */ refreshList: () => Promise; }; export type InitCachedHistoryQueryDropdownOptions = { dropdownId: string; historyButton: HTMLElement | null; clickOutsideRoot: HTMLElement | null; listMru: () => Promise; /** * 第一参为 {@link CachedHistoryListRow.contentKey}(与 `?content=` 一致)。 * 第二参 `shouldTouch` 与 {@link initQueryHistoryDropdown} 的 `onHistorySelect` 一致: * 是否应对关联 MRU 执行 touch(悬停为 false)。 */ onSelectEntry: ( contentKey: string, shouldTouch: boolean | undefined, ctx: CachedHistorySelectContext ) => void | Promise; onRemove: (contentKey: string) => void | Promise; onPromote: (contentKey: string) => void | Promise; }; /** * 三页 Cached history 共用的「无 input + MRU 异步刷新 + 悬停预览」接线。 * 返回 `refreshList` 供 URL hydrate 等与下拉无关的路径刷新内存列表。 */ export function initCachedHistoryQueryDropdown( options: InitCachedHistoryQueryDropdownOptions ): { refreshList: () => Promise } { const mirror = createMruListMirror(options.listMru); const ctx: CachedHistorySelectContext = { refreshList: () => mirror.refresh(), }; initQueryHistoryDropdown({ input: null, dropdownId: options.dropdownId, getHistoryEntries: () => mirror.getEntries().map((r) => ({ id: r.contentKey, label: r.listLabel })), refreshHistoryItems: () => mirror.refresh(), openDropdownOnFocusInput: false, filterHistoryByInput: false, onSelect: () => {}, fillInputOnSelect: false, onHistorySelect: (contentKey, shouldTouch) => { void Promise.resolve(options.onSelectEntry(contentKey, shouldTouch, ctx)); }, onRemove: options.onRemove, onPromote: options.onPromote, historyButton: options.historyButton, clickOutsideRoot: options.clickOutsideRoot, applyHistoryOnHover: true, }); void mirror.refresh(); return { refreshList: ctx.refreshList }; }