Encapsulate logic into filters instead of spreading around

1395c0b8c6e4c1a59192051ecd72cd509dcdf709

Joe <joenunezb@gmail.com>

4 files changed, +84 -162Showing whitespace changes
docs/fuzzy_search_flow.md+0 -113
@@ -1,113 +0,0 @@
1## Input Sources to printCharacters
2
3`printCharacters` is the main function that triggers the fuzzy search process if fuzzy search is enabled.
4
5```mermaid
6%%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 50}}}%%
7flowchart TD
8 subgraph User Actions
9 UA1[Character Search Input]
10 UA2[Tag Filter Click]
11 UA3[Folder Navigation]
12 UA4[Character Delete]
13 UA5[Character Create]
14 UA6[Character Import]
15 UA7[Clear All Filters]
16 UA8[Bulk Edit Operations]
17 UA9[Persona Changes]
18 end
19
20 subgraph API Events
21 API1[Character List Update]
22 API2[Group Update]
23 API3[Tag Update]
24 end
25
26 subgraph System Events
27 SE1[Page Load]
28 SE2[Content Manager Update]
29 SE3[Extension Events]
30 end
31
32 UA1 -->|triggers| PCD[printCharactersDebounced]
33 UA2 -->|triggers| PCD
34 UA7 -->|triggers| PCD
35 UA8 -->|triggers| PCD
36 UA9 -->|triggers| PCD
37
38 UA3 -->|triggers| PC[printCharacters]
39 UA4 -->|triggers| PC
40 UA5 -->|triggers| PC
41 UA6 -->|triggers| PC
42
43 API1 -->|triggers| PC
44 API2 -->|triggers| PC
45 API3 -->|triggers| PC
46
47 SE1 -->|triggers| PC
48 SE2 -->|triggers| PC
49 SE3 -->|triggers| PC
50
51 PCD -->|debounced call| PC
52
53 style PC fill:#f96,stroke:#333
54 style PCD fill:#f96,stroke:#333
55```
56
57This diagram shows how `printCharacters` is called throughout the application:
58
591. User Actions that trigger character list updates:
60 - Search input (debounced)
61 - Tag filter clicks (debounced)
62 - Folder navigation (direct)
63 - Character management operations (direct)
64
652. API Events that require list refresh:
66 - Character list updates
67 - Group updates
68 - Tag system updates
69
703. System Events:
71 - Initial page load
72 - Content manager updates
73 - Extension-triggered refreshes
74
75
76
77## Fuzzy Search Flow
78
79
80This diagram shows the flow of fuzzy search operations:
81```mermaid
82sequenceDiagram
83 participant Data as Data Sources
84 participant PC as printCharacters
85 participant GEL as getEntitiesList
86 participant FH as FilterHelper
87 participant AF as applyFilters
88 participant FS as FuzzySearch Functions
89 participant Cache as FuzzySearchCaches
90
91 Note over Data: Changes from:<br/>- Tags<br/>- Personas<br/>- World Info<br/>- Groups
92
93 Data->>PC: All changes trigger printCharacters<br/>(direct or debounced)
94
95 PC->>GEL: Call with {doFilter: true}
96 GEL->>FH: filterByTagState(entities)
97 GEL->>AF: entitiesFilter.applyFilters(entities)
98
99 AF->>FH: Check scoreCache for existing results
100 FH-->>AF: Return cached scores if exist
101
102 Note over FS: Filter functions include:<br/>SEARCH, <br/>FAV, <br/>GROUP, <br/>FOLDER, <br/>TAG, <br/>WORLD_INFO_SEARCH, <br/>PERSONA_SEARCH
103 AF->>FS: fuzzySearchCharacters/Groups/Tags
104 FS->>Cache: Check/Store results
105
106 FS-->>AF: Return search results
107 AF->>FH: Cache new scores
108 AF-->>GEL: Return filtered entities
109 GEL-->>PC: Return final entities list
110
111 PC->>Cache: clearFuzzySearchCaches()
112 Note over Cache: Cache is cleared at the end of<br/>each printCharacters call,<br/>ensuring fresh results for next search
113```
public/script.js+5 -5
@@ -268,7 +268,6 @@ import { initServerHistory } from './scripts/server-history.js';
268import { initSettingsSearch } from './scripts/setting-search.js';268import { initSettingsSearch } from './scripts/setting-search.js';
269import { initBulkEdit } from './scripts/bulk-edit.js';269import { initBulkEdit } from './scripts/bulk-edit.js';
270import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js';270import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js';
271import { clearFuzzySearchCaches } from './scripts/power-user.js';
272271
273//exporting functions and vars for mods272//exporting functions and vars for mods
274export {273export {
@@ -1516,7 +1515,6 @@ export async function printCharacters(fullRefresh = false) {
1516 });1515 });
15171516
1518 favsToHotswap();1517 favsToHotswap();
1519 clearFuzzySearchCaches();
1520}1518}
15211519
1522/** Checks the state of the current search, and adds/removes the search sorting option accordingly */1520/** Checks the state of the current search, and adds/removes the search sorting option accordingly */
@@ -1623,7 +1621,7 @@ export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
1623 subEntities = filterByTagState(entities, { subForEntity: entity });1621 subEntities = filterByTagState(entities, { subForEntity: entity });
1624 if (doFilter) {1622 if (doFilter) {
1625 // sub entities filter "hacked" because folder filter should not be applied there, so even in "only folders" mode characters show up1623 // sub entities filter "hacked" because folder filter should not be applied there, so even in "only folders" mode characters show up
1626 subEntities = entitiesFilter.applyFilters(subEntities, { clearScoreCache: false, tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED } });1624 subEntities = entitiesFilter.applyFilters(subEntities, { clearScoreCache: false, tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED }, clearFuzzySearchCaches: false });
1627 }1625 }
1628 if (doSort) {1626 if (doSort) {
1629 sortEntitiesList(subEntities);1627 sortEntitiesList(subEntities);
@@ -1636,11 +1634,11 @@ export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
1636 // Second run filters, hiding whatever should be filtered later1634 // Second run filters, hiding whatever should be filtered later
1637 if (doFilter) {1635 if (doFilter) {
1638 const beforeFinalEntities = filterByTagState(entities, { globalDisplayFilters: true });1636 const beforeFinalEntities = filterByTagState(entities, { globalDisplayFilters: true });
1639 entities = entitiesFilter.applyFilters(beforeFinalEntities);1637 entities = entitiesFilter.applyFilters(beforeFinalEntities, { clearFuzzySearchCaches: false });
16401638
1641 // Magic for folder filter. If that one is enabled, and no folders are display anymore, we remove that filter to actually show the characters.1639 // Magic for folder filter. If that one is enabled, and no folders are display anymore, we remove that filter to actually show the characters.
1642 if (isFilterState(entitiesFilter.getFilterData(FILTER_TYPES.FOLDER), FILTER_STATES.SELECTED) && entities.filter(x => x.type == 'tag').length == 0) {1640 if (isFilterState(entitiesFilter.getFilterData(FILTER_TYPES.FOLDER), FILTER_STATES.SELECTED) && entities.filter(x => x.type == 'tag').length == 0) {
1643 entities = entitiesFilter.applyFilters(beforeFinalEntities, { tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED } });1641 entities = entitiesFilter.applyFilters(beforeFinalEntities, { tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED }, clearFuzzySearchCaches: false });
1644 }1642 }
1645 }1643 }
16461644
@@ -1656,6 +1654,7 @@ export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
1656 if (doSort) {1654 if (doSort) {
1657 sortEntitiesList(entities);1655 sortEntitiesList(entities);
1658 }1656 }
1657 entitiesFilter.clearFuzzySearchCaches();
1659 return entities;1658 return entities;
1660}1659}
16611660
@@ -1751,6 +1750,7 @@ export async function getCharacters() {
1751 }1750 }
17521751
1753 await getGroups();1752 await getGroups();
1753 // clearFuzzySearchCaches();
1754 await printCharacters(true);1754 await printCharacters(true);
1755 }1755 }
1756}1756}
public/scripts/filters.js+51 -6
@@ -56,6 +56,19 @@ export function isFilterState(a, b) {
56}56}
5757
58/**58/**
59 * The fuzzy search categories
60 * @type {{ characters: string, worldInfo: string, personas: string, tags: string, groups: string }}
61 */
62export const fuzzySearchCategories = Object.freeze({
63 characters: 'characters',
64 worldInfo: 'worldInfo',
65 personas: 'personas',
66 tags: 'tags',
67 groups: 'groups',
68});
69
70
71/**
59 * Helper class for filtering data.72 * Helper class for filtering data.
60 * @example73 * @example
61 * const filterHelper = new FilterHelper(() => console.log('data changed'));74 * const filterHelper = new FilterHelper(() => console.log('data changed'));
@@ -73,12 +86,25 @@ export class FilterHelper {
73 scoreCache;86 scoreCache;
7487
75 /**88 /**
89 * Cache for fuzzy search results per category.
90 * @type {Object.<string, { resultMap: Map<string, any> }>}
91 */
92 fuzzySearchCaches;
93
94 /**
76 * Creates a new FilterHelper95 * Creates a new FilterHelper
77 * @param {Function} onDataChanged Callback to trigger when the filter data changes96 * @param {Function} onDataChanged Callback to trigger when the filter data changes
78 */97 */
79 constructor(onDataChanged) {98 constructor(onDataChanged) {
80 this.onDataChanged = onDataChanged;99 this.onDataChanged = onDataChanged;
81 this.scoreCache = new Map();100 this.scoreCache = new Map();
101 this.fuzzySearchCaches = {
102 [fuzzySearchCategories.characters]: { resultMap: new Map() },
103 [fuzzySearchCategories.worldInfo]: { resultMap: new Map() },
104 [fuzzySearchCategories.personas]: { resultMap: new Map() },
105 [fuzzySearchCategories.tags]: { resultMap: new Map() },
106 [fuzzySearchCategories.groups]: { resultMap: new Map() },
107 };
82 }108 }
83109
84 /**110 /**
@@ -151,7 +177,7 @@ export class FilterHelper {
151 return data;177 return data;
152 }178 }
153179
154 const fuzzySearchResults = fuzzySearchWorldInfo(data, term);180 const fuzzySearchResults = fuzzySearchWorldInfo(data, term, this.fuzzySearchCaches);
155 this.cacheScores(FILTER_TYPES.WORLD_INFO_SEARCH, new Map(fuzzySearchResults.map(i => [i.item?.uid, i.score])));181 this.cacheScores(FILTER_TYPES.WORLD_INFO_SEARCH, new Map(fuzzySearchResults.map(i => [i.item?.uid, i.score])));
156182
157 const filteredData = data.filter(entity => fuzzySearchResults.find(x => x.item === entity));183 const filteredData = data.filter(entity => fuzzySearchResults.find(x => x.item === entity));
@@ -170,7 +196,7 @@ export class FilterHelper {
170 return data;196 return data;
171 }197 }
172198
173 const fuzzySearchResults = fuzzySearchPersonas(data, term);199 const fuzzySearchResults = fuzzySearchPersonas(data, term, this.fuzzySearchCaches);
174 this.cacheScores(FILTER_TYPES.PERSONA_SEARCH, new Map(fuzzySearchResults.map(i => [i.item.key, i.score])));200 this.cacheScores(FILTER_TYPES.PERSONA_SEARCH, new Map(fuzzySearchResults.map(i => [i.item.key, i.score])));
175201
176 const filteredData = data.filter(name => fuzzySearchResults.find(x => x.item.key === name));202 const filteredData = data.filter(name => fuzzySearchResults.find(x => x.item.key === name));
@@ -289,9 +315,9 @@ export class FilterHelper {
289315
290 // Save fuzzy search results and scores if enabled316 // Save fuzzy search results and scores if enabled
291 if (power_user.fuzzy_search) {317 if (power_user.fuzzy_search) {
292 const fuzzySearchCharactersResults = fuzzySearchCharacters(searchValue);318 const fuzzySearchCharactersResults = fuzzySearchCharacters(searchValue, this.fuzzySearchCaches);
293 const fuzzySearchGroupsResults = fuzzySearchGroups(searchValue);319 const fuzzySearchGroupsResults = fuzzySearchGroups(searchValue, this.fuzzySearchCaches);
294 const fuzzySearchTagsResult = fuzzySearchTags(searchValue);320 const fuzzySearchTagsResult = fuzzySearchTags(searchValue, this.fuzzySearchCaches);
295 this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchCharactersResults.map(i => [`character.${i.refIndex}`, i.score])));321 this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchCharactersResults.map(i => [`character.${i.refIndex}`, i.score])));
296 this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchGroupsResults.map(i => [`group.${i.item.id}`, i.score])));322 this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchGroupsResults.map(i => [`group.${i.item.id}`, i.score])));
297 this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchTagsResult.map(i => [`tag.${i.item.id}`, i.score])));323 this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchTagsResult.map(i => [`tag.${i.item.id}`, i.score])));
@@ -343,11 +369,14 @@ export class FilterHelper {
343 * @param {object} options - Optional call parameters369 * @param {object} options - Optional call parameters
344 * @param {boolean} [options.clearScoreCache=true] - Whether the score cache should be cleared.370 * @param {boolean} [options.clearScoreCache=true] - Whether the score cache should be cleared.
345 * @param {Object.<FilterType, any>} [options.tempOverrides={}] - Temporarily override specific filters for this filter application371 * @param {Object.<FilterType, any>} [options.tempOverrides={}] - Temporarily override specific filters for this filter application
372 * @param {boolean} [options.clearFuzzySearchCaches=true] - Whether the fuzzy search caches should be cleared.
346 * @returns {any[]} The filtered data.373 * @returns {any[]} The filtered data.
347 */374 */
348 applyFilters(data, { clearScoreCache = true, tempOverrides = {} } = {}) {375 applyFilters(data, { clearScoreCache = true, tempOverrides = {}, clearFuzzySearchCaches = true } = {}) {
349 if (clearScoreCache) this.clearScoreCache();376 if (clearScoreCache) this.clearScoreCache();
350377
378 if (clearFuzzySearchCaches) this.clearFuzzySearchCaches();
379
351 // Save original filter states380 // Save original filter states
352 const originalStates = {};381 const originalStates = {};
353 for (const key in tempOverrides) {382 for (const key in tempOverrides) {
@@ -411,4 +440,20 @@ export class FilterHelper {
411 this.scoreCache = new Map();440 this.scoreCache = new Map();
412 }441 }
413 }442 }
443
444 /**
445 * Clears fuzzy search caches
446 * @param {keyof typeof fuzzySearchCategories} [type] Optional cache type to clear. If not provided, clears all caches
447 */
448 clearFuzzySearchCaches(type = null) {
449 if (type && this.fuzzySearchCaches[type]) {
450 this.fuzzySearchCaches[type].resultMap.clear();
451 console.log(`Fuzzy search cache cleared for: ${type}`);
452 } else {
453 for (const cache of Object.values(this.fuzzySearchCaches)) {
454 cache.resultMap.clear();
455 }
456 console.log('All fuzzy search caches cleared');
457 }
458 }
414}459}
public/scripts/power-user.js+28 -38
@@ -53,6 +53,7 @@ import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandE
53import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';53import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
54import { POPUP_TYPE, callGenericPopup } from './popup.js';54import { POPUP_TYPE, callGenericPopup } from './popup.js';
55import { loadSystemPrompts } from './sysprompt.js';55import { loadSystemPrompts } from './sysprompt.js';
56import { fuzzySearchCategories } from './filters.js';
5657
57export {58export {
58 loadPowerUserSettings,59 loadPowerUserSettings,
@@ -328,22 +329,6 @@ const contextControls = [
328let browser_has_focus = true;329let browser_has_focus = true;
329const debug_functions = [];330const debug_functions = [];
330331
331const fuzzySearchCaches = {
332 characters: { resultMap: new Map() },
333 worldInfo: { resultMap: new Map() },
334 personas: { resultMap: new Map() },
335 tags: { resultMap: new Map() },
336 groups: { resultMap: new Map() },
337};
338
339const fuzzySearchCategories = {
340 characters: 'characters',
341 worldInfo: 'worldInfo',
342 personas: 'personas',
343 tags: 'tags',
344 groups: 'groups',
345};
346
347const setHotswapsDebounced = debounce(favsToHotswap);332const setHotswapsDebounced = debounce(favsToHotswap);
348333
349function playMessageSound() {334function playMessageSound() {
@@ -1845,19 +1830,26 @@ async function loadContextSettings() {
1845 });1830 });
1846}1831}
18471832
1833
1848/**1834/**
1849 * Common function to perform fuzzy search with caching1835 * Common function to perform fuzzy search with caching
1850 * @param {string} type - Type of search from fuzzySearchCategories1836 * @param {string} type - Type of search from fuzzySearchCategories
1851 * @param {any[]} data - Data array to search in1837 * @param {any[]} data - Data array to search in
1852 * @param {Array<{name: string, weight: number, getFn?: Function}>} keys - Fuse.js keys configuration1838 * @param {Array<{name: string, weight: number, getFn?: Function}>} keys - Fuse.js keys configuration
1853 * @param {string} searchValue - The search term1839 * @param {string} searchValue - The search term
1840 * @param {Object.<string, { resultMap: Map<string, any> }>} fuzzySearchCaches - Fuzzy search caches
1854 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1841 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1855 */1842 */
1856function performFuzzySearch(type, data, keys, searchValue) {1843function performFuzzySearch(type, data, keys, searchValue, fuzzySearchCaches) {
1844 let startTime = performance.now();
1857 const cache = fuzzySearchCaches[type];1845 const cache = fuzzySearchCaches[type];
18581846
1859 // Check cache for existing results1847 // Check cache for existing results
1860 if (cache.resultMap.has(searchValue)) {1848 if (cache.resultMap.has(searchValue)) {
1849 let endTime = performance.now();
1850 if (endTime - startTime > 1.0) {
1851 console.log(`Fuzzy search for ${type} took ${endTime - startTime}ms (cached)`);
1852 }
1861 return cache.resultMap.get(searchValue);1853 return cache.resultMap.get(searchValue);
1862 }1854 }
18631855
@@ -1872,26 +1864,20 @@ function performFuzzySearch(type, data, keys, searchValue) {
18721864
1873 const results = fuse.search(searchValue);1865 const results = fuse.search(searchValue);
1874 cache.resultMap.set(searchValue, results);1866 cache.resultMap.set(searchValue, results);
1875 return results;1867 let endTime = performance.now();
1868 if (endTime - startTime > 1.0) {
1869 console.log(`Fuzzy search for ${type} took ${endTime - startTime}ms`);
1876 }1870 }
18771871 return results;
1878
1879/**
1880 * Clears all fuzzy search caches
1881 */
1882export function clearFuzzySearchCaches() {
1883 for (const cache of Object.values(fuzzySearchCaches)) {
1884 cache.resultMap.clear();
1885 }
1886 console.log('Fuzzy search caches cleared');
1887}1872}
18881873
1889/**1874/**
1890 * Fuzzy search characters by a search term1875 * Fuzzy search characters by a search term
1891 * @param {string} searchValue - The search term1876 * @param {string} searchValue - The search term
1877 * @param {Object.<string, { resultMap: Map<string, any> }>} fuzzySearchCaches - Fuzzy search caches
1892 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1878 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1893 */1879 */
1894export function fuzzySearchCharacters(searchValue) {1880export function fuzzySearchCharacters(searchValue, fuzzySearchCaches) {
1895 const keys = [1881 const keys = [
1896 { name: 'data.name', weight: 20 },1882 { name: 'data.name', weight: 20 },
1897 { name: '#tags', weight: 10, getFn: (character) => getTagsList(character.avatar).map(x => x.name).join('||') },1883 { name: '#tags', weight: 10, getFn: (character) => getTagsList(character.avatar).map(x => x.name).join('||') },
@@ -1906,16 +1892,17 @@ export function fuzzySearchCharacters(searchValue) {
1906 { name: 'data.alternate_greetings', weight: 1 },1892 { name: 'data.alternate_greetings', weight: 1 },
1907 ];1893 ];
19081894
1909 return performFuzzySearch(fuzzySearchCategories.characters, characters, keys, searchValue);1895 return performFuzzySearch(fuzzySearchCategories.characters, characters, keys, searchValue, fuzzySearchCaches);
1910}1896}
19111897
1912/**1898/**
1913 * Fuzzy search world info entries by a search term1899 * Fuzzy search world info entries by a search term
1914 * @param {*[]} data - WI items data array1900 * @param {*[]} data - WI items data array
1915 * @param {string} searchValue - The search term1901 * @param {string} searchValue - The search term
1902 * @param {Object.<string, { resultMap: Map<string, any> }>} fuzzySearchCaches - Fuzzy search caches
1916 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1903 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1917 */1904 */
1918export function fuzzySearchWorldInfo(data, searchValue) {1905export function fuzzySearchWorldInfo(data, searchValue, fuzzySearchCaches) {
1919 const keys = [1906 const keys = [
1920 { name: 'key', weight: 20 },1907 { name: 'key', weight: 20 },
1921 { name: 'group', weight: 15 },1908 { name: 'group', weight: 15 },
@@ -1926,16 +1913,17 @@ export function fuzzySearchWorldInfo(data, searchValue) {
1926 { name: 'automationId', weight: 1 },1913 { name: 'automationId', weight: 1 },
1927 ];1914 ];
19281915
1929 return performFuzzySearch(fuzzySearchCategories.worldInfo, data, keys, searchValue);1916 return performFuzzySearch(fuzzySearchCategories.worldInfo, data, keys, searchValue, fuzzySearchCaches);
1930}1917}
19311918
1932/**1919/**
1933 * Fuzzy search persona entries by a search term1920 * Fuzzy search persona entries by a search term
1934 * @param {*[]} data - persona data array1921 * @param {*[]} data - persona data array
1935 * @param {string} searchValue - The search term1922 * @param {string} searchValue - The search term
1923 * @param {Object.<string, { resultMap: Map<string, any> }>} fuzzySearchCaches - Fuzzy search caches
1936 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1924 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1937 */1925 */
1938export function fuzzySearchPersonas(data, searchValue) {1926export function fuzzySearchPersonas(data, searchValue, fuzzySearchCaches) {
1939 const mappedData = data.map(x => ({1927 const mappedData = data.map(x => ({
1940 key: x,1928 key: x,
1941 name: power_user.personas[x] ?? '',1929 name: power_user.personas[x] ?? '',
@@ -1947,28 +1935,30 @@ export function fuzzySearchPersonas(data, searchValue) {
1947 { name: 'description', weight: 3 },1935 { name: 'description', weight: 3 },
1948 ];1936 ];
19491937
1950 return performFuzzySearch(fuzzySearchCategories.personas, mappedData, keys, searchValue);1938 return performFuzzySearch(fuzzySearchCategories.personas, mappedData, keys, searchValue, fuzzySearchCaches);
1951}1939}
19521940
1953/**1941/**
1954 * Fuzzy search tags by a search term1942 * Fuzzy search tags by a search term
1955 * @param {string} searchValue - The search term1943 * @param {string} searchValue - The search term
1944 * @param {Object.<string, { resultMap: Map<string, any> }>} fuzzySearchCaches - Fuzzy search caches
1956 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1945 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1957 */1946 */
1958export function fuzzySearchTags(searchValue) {1947export function fuzzySearchTags(searchValue, fuzzySearchCaches) {
1959 const keys = [1948 const keys = [
1960 { name: 'name', weight: 1 },1949 { name: 'name', weight: 1 },
1961 ];1950 ];
19621951
1963 return performFuzzySearch(fuzzySearchCategories.tags, tags, keys, searchValue);1952 return performFuzzySearch(fuzzySearchCategories.tags, tags, keys, searchValue, fuzzySearchCaches);
1964}1953}
19651954
1966/**1955/**
1967 * Fuzzy search groups by a search term1956 * Fuzzy search groups by a search term
1968 * @param {string} searchValue - The search term1957 * @param {string} searchValue - The search term
1958 * @param {Object.<string, { resultMap: Map<string, any> }>} fuzzySearchCaches - Fuzzy search caches
1969 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score1959 * @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
1970 */1960 */
1971export function fuzzySearchGroups(searchValue) {1961export function fuzzySearchGroups(searchValue, fuzzySearchCaches) {
1972 const keys = [1962 const keys = [
1973 { name: 'name', weight: 20 },1963 { name: 'name', weight: 20 },
1974 { name: 'members', weight: 15 },1964 { name: 'members', weight: 15 },
@@ -1976,7 +1966,7 @@ export function fuzzySearchGroups(searchValue) {
1976 { name: 'id', weight: 1 },1966 { name: 'id', weight: 1 },
1977 ];1967 ];
19781968
1979 return performFuzzySearch(fuzzySearchCategories.groups, groups, keys, searchValue);1969 return performFuzzySearch(fuzzySearchCategories.groups, groups, keys, searchValue, fuzzySearchCaches);
1980}1970}
19811971
1982/**1972/**