prompt.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { create } from "zustand";
  2. import { persist } from "zustand/middleware";
  3. import Fuse from "fuse.js";
  4. import { getLang } from "../locales";
  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. allBuiltInPrompts: [] as Prompt[],
  25. init(prompts: Prompt[]) {
  26. if (this.ready) {
  27. return;
  28. }
  29. this.allBuiltInPrompts = prompts;
  30. this.engine.setCollection(prompts);
  31. this.ready = true;
  32. },
  33. remove(id: number) {
  34. this.engine.remove((doc) => doc.id === id);
  35. },
  36. add(prompt: Prompt) {
  37. this.engine.add(prompt);
  38. },
  39. search(text: string) {
  40. const results = this.engine.search(text);
  41. return results.map((v) => v.item);
  42. },
  43. };
  44. export const usePromptStore = create<PromptStore>()(
  45. persist(
  46. (set, get) => ({
  47. latestId: 0,
  48. prompts: new Map(),
  49. add(prompt) {
  50. const prompts = get().prompts;
  51. prompt.id = get().latestId + 1;
  52. prompts.set(prompt.id, prompt);
  53. set(() => ({
  54. latestId: prompt.id!,
  55. prompts: prompts,
  56. }));
  57. return prompt.id!;
  58. },
  59. remove(id) {
  60. const prompts = get().prompts;
  61. prompts.delete(id);
  62. SearchService.remove(id);
  63. set(() => ({
  64. prompts,
  65. }));
  66. },
  67. search(text) {
  68. if (text.length === 0) {
  69. // return all prompts
  70. const userPrompts = get().prompts?.values?.() ?? [];
  71. return SearchService.allBuiltInPrompts.concat([...userPrompts]);
  72. }
  73. return SearchService.search(text) as Prompt[];
  74. },
  75. }),
  76. {
  77. name: PROMPT_KEY,
  78. version: 1,
  79. onRehydrateStorage(state) {
  80. const PROMPT_URL = "./prompts.json";
  81. type PromptList = Array<[string, string]>;
  82. fetch(PROMPT_URL)
  83. .then((res) => res.json())
  84. .then((res) => {
  85. let fetchPrompts = [res.en, res.cn];
  86. if (getLang() === "cn") {
  87. fetchPrompts = fetchPrompts.reverse();
  88. }
  89. const builtinPrompts = fetchPrompts
  90. .map((promptList: PromptList) => {
  91. return promptList.map(
  92. ([title, content]) =>
  93. ({
  94. title,
  95. content,
  96. } as Prompt),
  97. );
  98. })
  99. .concat([...(state?.prompts?.values() ?? [])]);
  100. const allPromptsForSearch = builtinPrompts
  101. .reduce((pre, cur) => pre.concat(cur), [])
  102. .filter((v) => !!v.title && !!v.content);
  103. SearchService.count.builtin = res.en.length + res.cn.length;
  104. SearchService.init(allPromptsForSearch);
  105. });
  106. },
  107. },
  108. ),
  109. );