|
import { create } from "zustand"; |
|
import { persist } from "zustand/middleware"; |
|
import Fuse from "fuse.js"; |
|
import { getLang } from "../locales"; |
|
import { StoreKey } from "../constant"; |
|
|
|
export interface Prompt { |
|
id?: number; |
|
isUser?: boolean; |
|
title: string; |
|
content: string; |
|
} |
|
|
|
export interface PromptStore { |
|
counter: number; |
|
latestId: number; |
|
prompts: Record<number, Prompt>; |
|
|
|
add: (prompt: Prompt) => number; |
|
get: (id: number) => Prompt | undefined; |
|
remove: (id: number) => void; |
|
search: (text: string) => Prompt[]; |
|
update: (id: number, updater: (prompt: Prompt) => void) => void; |
|
|
|
getUserPrompts: () => Prompt[]; |
|
} |
|
|
|
export const SearchService = { |
|
ready: false, |
|
builtinEngine: new Fuse<Prompt>([], { keys: ["title"] }), |
|
userEngine: new Fuse<Prompt>([], { keys: ["title"] }), |
|
count: { |
|
builtin: 0, |
|
}, |
|
allPrompts: [] as Prompt[], |
|
builtinPrompts: [] as Prompt[], |
|
|
|
init(builtinPrompts: Prompt[], userPrompts: Prompt[]) { |
|
if (this.ready) { |
|
return; |
|
} |
|
this.allPrompts = userPrompts.concat(builtinPrompts); |
|
this.builtinPrompts = builtinPrompts.slice(); |
|
this.builtinEngine.setCollection(builtinPrompts); |
|
this.userEngine.setCollection(userPrompts); |
|
this.ready = true; |
|
}, |
|
|
|
remove(id: number) { |
|
this.userEngine.remove((doc) => doc.id === id); |
|
}, |
|
|
|
add(prompt: Prompt) { |
|
this.userEngine.add(prompt); |
|
}, |
|
|
|
search(text: string) { |
|
const userResults = this.userEngine.search(text); |
|
const builtinResults = this.builtinEngine.search(text); |
|
return userResults.concat(builtinResults).map((v) => v.item); |
|
}, |
|
}; |
|
|
|
export const usePromptStore = create<PromptStore>()( |
|
persist( |
|
(set, get) => ({ |
|
counter: 0, |
|
latestId: 0, |
|
prompts: {}, |
|
|
|
add(prompt) { |
|
const prompts = get().prompts; |
|
prompt.id = get().latestId + 1; |
|
prompt.isUser = true; |
|
prompts[prompt.id] = prompt; |
|
|
|
set(() => ({ |
|
latestId: prompt.id!, |
|
prompts: prompts, |
|
})); |
|
|
|
return prompt.id!; |
|
}, |
|
|
|
get(id) { |
|
const targetPrompt = get().prompts[id]; |
|
|
|
if (!targetPrompt) { |
|
return SearchService.builtinPrompts.find((v) => v.id === id); |
|
} |
|
|
|
return targetPrompt; |
|
}, |
|
|
|
remove(id) { |
|
const prompts = get().prompts; |
|
delete prompts[id]; |
|
SearchService.remove(id); |
|
|
|
set(() => ({ |
|
prompts, |
|
counter: get().counter + 1, |
|
})); |
|
}, |
|
|
|
getUserPrompts() { |
|
const userPrompts = Object.values(get().prompts ?? {}); |
|
userPrompts.sort((a, b) => (b.id && a.id ? b.id - a.id : 0)); |
|
return userPrompts; |
|
}, |
|
|
|
update(id: number, updater) { |
|
const prompt = get().prompts[id] ?? { |
|
title: "", |
|
content: "", |
|
id, |
|
}; |
|
|
|
SearchService.remove(id); |
|
updater(prompt); |
|
const prompts = get().prompts; |
|
prompts[id] = prompt; |
|
set(() => ({ prompts })); |
|
SearchService.add(prompt); |
|
}, |
|
|
|
search(text) { |
|
if (text.length === 0) { |
|
|
|
return SearchService.allPrompts.concat([...get().getUserPrompts()]); |
|
} |
|
return SearchService.search(text) as Prompt[]; |
|
}, |
|
}), |
|
{ |
|
name: StoreKey.Prompt, |
|
version: 1, |
|
onRehydrateStorage(state) { |
|
const PROMPT_URL = "./prompts.json"; |
|
|
|
type PromptList = Array<[string, string]>; |
|
|
|
fetch(PROMPT_URL) |
|
.then((res) => res.json()) |
|
.then((res) => { |
|
let fetchPrompts = [res.en, res.cn]; |
|
if (getLang() === "cn") { |
|
fetchPrompts = fetchPrompts.reverse(); |
|
} |
|
const builtinPrompts = fetchPrompts.map( |
|
(promptList: PromptList) => { |
|
return promptList.map( |
|
([title, content]) => |
|
({ |
|
id: Math.random(), |
|
title, |
|
content, |
|
} as Prompt), |
|
); |
|
}, |
|
); |
|
|
|
const userPrompts = |
|
usePromptStore.getState().getUserPrompts() ?? []; |
|
|
|
const allPromptsForSearch = builtinPrompts |
|
.reduce((pre, cur) => pre.concat(cur), []) |
|
.filter((v) => !!v.title && !!v.content); |
|
SearchService.count.builtin = res.en.length + res.cn.length; |
|
SearchService.init(allPromptsForSearch, userPrompts); |
|
}); |
|
}, |
|
}, |
|
), |
|
); |
|
|