prompt.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { create } from "zustand";
  2. import { persist } from "zustand/middleware";
  3. import Fuse from "fuse.js";
  4. import { showToast } from "../components/ui-lib";
  5. export interface Prompt {
  6. id?: number;
  7. title: string;
  8. content: string;
  9. }
  10. export interface PromptStore {
  11. latestId: number;
  12. prompts: Map<number, Prompt>;
  13. add: (prompt: Prompt) => number;
  14. remove: (id: number) => void;
  15. search: (text: string) => Prompt[];
  16. }
  17. export const PROMPT_KEY = "prompt-store";
  18. export const SearchService = {
  19. ready: false,
  20. engine: new Fuse<Prompt>([], { keys: ["title"] }),
  21. count: {
  22. builtin: 0,
  23. },
  24. init(prompts: Prompt[]) {
  25. if (this.ready) {
  26. return;
  27. }
  28. this.engine.setCollection(prompts);
  29. this.ready = true;
  30. },
  31. remove(id: number) {
  32. this.engine.remove((doc) => doc.id === id);
  33. },
  34. add(prompt: Prompt) {
  35. this.engine.add(prompt);
  36. },
  37. search(text: string) {
  38. const results = this.engine.search(text);
  39. return results.map((v) => v.item);
  40. },
  41. };
  42. export const usePromptStore = create<PromptStore>()(
  43. persist(
  44. (set, get) => ({
  45. latestId: 0,
  46. prompts: new Map(),
  47. add(prompt) {
  48. const prompts = get().prompts;
  49. prompt.id = get().latestId + 1;
  50. prompts.set(prompt.id, prompt);
  51. set(() => ({
  52. latestId: prompt.id!,
  53. prompts: prompts,
  54. }));
  55. return prompt.id!;
  56. },
  57. remove(id) {
  58. const prompts = get().prompts;
  59. prompts.delete(id);
  60. SearchService.remove(id);
  61. set(() => ({
  62. prompts,
  63. }));
  64. },
  65. search(text) {
  66. return SearchService.search(text) as Prompt[];
  67. },
  68. }),
  69. {
  70. name: PROMPT_KEY,
  71. version: 1,
  72. onRehydrateStorage(state) {
  73. const PROMPT_URL = "./prompts.json";
  74. type PromptList = Array<[string, string]>;
  75. fetch(PROMPT_URL)
  76. .then((res) => res.json())
  77. .then((res) => {
  78. const builtinPrompts = [res.en, res.cn]
  79. .map((promptList: PromptList) => {
  80. return promptList.map(
  81. ([title, content]) =>
  82. ({
  83. title,
  84. content,
  85. } as Prompt)
  86. );
  87. })
  88. .concat([...(state?.prompts?.values() ?? [])]);
  89. const allPromptsForSearch = builtinPrompts.reduce(
  90. (pre, cur) => pre.concat(cur),
  91. []
  92. );
  93. SearchService.count.builtin = res.en.length + res.cn.length;
  94. SearchService.init(allPromptsForSearch);
  95. showToast(`已加载 ${allPromptsForSearch.length} 条 Prompts`);
  96. });
  97. },
  98. }
  99. )
  100. );