mirror of
https://codeberg.org/yeentown/barkey.git
synced 2025-07-07 04:26:58 +00:00
refactor serach index generator code (#15772)
* refactor: flatten search index * chore: use Function() to simplify parsing attribute * chore: remove comment handling * chore: simplify processing SearchLabel and SearchKeyword element * chore: use SearchLabel in mutedUsers * chore: small improvements * chore: remove a fallback path and simplify the entire code * fix: result path is not correct * chore: inline function
This commit is contained in:
parent
2349a5d20e
commit
85a7b10fcd
5 changed files with 380 additions and 1160 deletions
File diff suppressed because it is too large
Load diff
|
@ -93,11 +93,11 @@ export type SuperMenuDef = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useTemplateRef, ref, watch, nextTick } from 'vue';
|
import { useTemplateRef, ref, watch, nextTick, computed } from 'vue';
|
||||||
|
import { getScrollContainer } from '@@/js/scroll.js';
|
||||||
import type { SearchIndexItem } from '@/utility/settings-search-index.js';
|
import type { SearchIndexItem } from '@/utility/settings-search-index.js';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { getScrollContainer } from '@@/js/scroll.js';
|
|
||||||
import { useRouter } from '@/router.js';
|
import { useRouter } from '@/router.js';
|
||||||
import { initIntlString, compareStringIncludes } from '@/utility/intl-string.js';
|
import { initIntlString, compareStringIncludes } from '@/utility/intl-string.js';
|
||||||
|
|
||||||
|
@ -124,6 +124,7 @@ const searchResult = ref<{
|
||||||
isRoot: boolean;
|
isRoot: boolean;
|
||||||
parentLabels: string[];
|
parentLabels: string[];
|
||||||
}[]>([]);
|
}[]>([]);
|
||||||
|
const searchIndexItemByIdComputed = computed(() => props.searchIndex && new Map<string, SearchIndexItem>(props.searchIndex.map(i => [i.id, i])));
|
||||||
|
|
||||||
watch(searchQuery, (value) => {
|
watch(searchQuery, (value) => {
|
||||||
rawSearchQuery.value = value;
|
rawSearchQuery.value = value;
|
||||||
|
@ -137,32 +138,41 @@ watch(rawSearchQuery, (value) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dive = (items: SearchIndexItem[], parents: SearchIndexItem[] = []) => {
|
const searchIndexItemById = searchIndexItemByIdComputed.value;
|
||||||
for (const item of items) {
|
if (searchIndexItemById != null) {
|
||||||
const matched = (
|
const addSearchResult = (item: SearchIndexItem) => {
|
||||||
|
let path: string | undefined = item.path;
|
||||||
|
let icon: string | undefined = item.icon;
|
||||||
|
const parentLabels: string[] = [];
|
||||||
|
|
||||||
|
for (let current = searchIndexItemById.get(item.parentId ?? '');
|
||||||
|
current != null;
|
||||||
|
current = searchIndexItemById.get(current.parentId ?? '')) {
|
||||||
|
path ??= current.path;
|
||||||
|
icon ??= current.icon;
|
||||||
|
parentLabels.push(current.label);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_DEV_ && path == null) throw new Error('path is null for ' + item.id);
|
||||||
|
|
||||||
|
searchResult.value.push({
|
||||||
|
id: item.id,
|
||||||
|
path: path ?? '/', // never gets `/`
|
||||||
|
label: item.label,
|
||||||
|
parentLabels: parentLabels.toReversed(),
|
||||||
|
icon,
|
||||||
|
isRoot: item.parentId == null,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const item of searchIndexItemById.values()) {
|
||||||
|
if (
|
||||||
compareStringIncludes(item.label, value) ||
|
compareStringIncludes(item.label, value) ||
|
||||||
item.keywords.some((x) => compareStringIncludes(x, value))
|
item.keywords.some((x) => compareStringIncludes(x, value))
|
||||||
);
|
) {
|
||||||
|
addSearchResult(item);
|
||||||
if (matched) {
|
|
||||||
searchResult.value.push({
|
|
||||||
id: item.id,
|
|
||||||
path: item.path ?? parents.find((x) => x.path != null)?.path ?? '/', // never gets `/`
|
|
||||||
label: item.label,
|
|
||||||
parentLabels: parents.map((x) => x.label).toReversed(),
|
|
||||||
icon: item.icon ?? parents.find((x) => x.icon != null)?.icon,
|
|
||||||
isRoot: parents.length === 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.children) {
|
|
||||||
dive(item.children, [item, ...parents]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if (props.searchIndex) {
|
|
||||||
dive(props.searchIndex);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -62,12 +62,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</SearchMarker>
|
</SearchMarker>
|
||||||
|
|
||||||
<SearchMarker
|
<SearchMarker
|
||||||
:label="`${i18n.ts.mutedUsers} (${ i18n.ts.renote })`"
|
|
||||||
:keywords="['renote', 'mute', 'hide', 'user']"
|
:keywords="['renote', 'mute', 'hide', 'user']"
|
||||||
>
|
>
|
||||||
<MkFolder>
|
<MkFolder>
|
||||||
<template #icon><i class="ti ti-repeat-off"></i></template>
|
<template #icon><i class="ti ti-repeat-off"></i></template>
|
||||||
<template #label>{{ i18n.ts.mutedUsers }} ({{ i18n.ts.renote }})</template>
|
<template #label><SearchLabel>{{ i18n.ts.mutedUsers }} ({{ i18n.ts.renote }})</SearchLabel></template>
|
||||||
|
|
||||||
<MkPagination :pagination="renoteMutingPagination">
|
<MkPagination :pagination="renoteMutingPagination">
|
||||||
<template #empty>
|
<template #empty>
|
||||||
|
|
|
@ -8,35 +8,27 @@ import type { GeneratedSearchIndexItem } from 'search-index:settings';
|
||||||
|
|
||||||
export type SearchIndexItem = {
|
export type SearchIndexItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
parentId?: string;
|
||||||
path?: string;
|
path?: string;
|
||||||
label: string;
|
label: string;
|
||||||
keywords: string[];
|
keywords: string[];
|
||||||
icon?: string;
|
icon?: string;
|
||||||
children?: SearchIndexItem[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const rootMods = new Map(generated.map(item => [item.id, item]));
|
const rootMods = new Map(generated.map(item => [item.id, item]));
|
||||||
|
|
||||||
function walk(item: GeneratedSearchIndexItem) {
|
// link inlining here
|
||||||
|
for (const item of generated) {
|
||||||
if (item.inlining) {
|
if (item.inlining) {
|
||||||
for (const id of item.inlining) {
|
for (const id of item.inlining) {
|
||||||
const inline = rootMods.get(id);
|
const inline = rootMods.get(id);
|
||||||
if (inline) {
|
if (inline) {
|
||||||
(item.children ??= []).push(inline);
|
inline.parentId = item.id;
|
||||||
rootMods.delete(id);
|
|
||||||
} else {
|
} else {
|
||||||
console.log('[Settings Search Index] Failed to inline', id);
|
console.log('[Settings Search Index] Failed to inline', id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const child of item.children ?? []) {
|
|
||||||
walk(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const item of generated) {
|
|
||||||
walk(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const searchIndexes: SearchIndexItem[] = generated;
|
export const searchIndexes: SearchIndexItem[] = generated;
|
||||||
|
|
2
packages/frontend/src/utility/virtual.d.ts
vendored
2
packages/frontend/src/utility/virtual.d.ts
vendored
|
@ -6,12 +6,12 @@
|
||||||
declare module 'search-index:settings' {
|
declare module 'search-index:settings' {
|
||||||
export type GeneratedSearchIndexItem = {
|
export type GeneratedSearchIndexItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
parentId?: string;
|
||||||
path?: string;
|
path?: string;
|
||||||
label: string;
|
label: string;
|
||||||
keywords: string[];
|
keywords: string[];
|
||||||
icon?: string;
|
icon?: string;
|
||||||
inlining?: string[];
|
inlining?: string[];
|
||||||
children?: GeneratedSearchIndexItem[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const searchIndexes: GeneratedSearchIndexItem[];
|
export const searchIndexes: GeneratedSearchIndexItem[];
|
||||||
|
|
Loading…
Add table
Reference in a new issue