diff --git a/app/store/chat.ts b/app/store/chat.ts index 653926d1b02..de2a6307850 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -27,6 +27,7 @@ import { createPersistStore } from "../utils/store"; import { collectModelsWithDefaultModel } from "../utils/model"; import { useAccessStore } from "./access"; import { isDalle3 } from "../utils"; +import { indexedDBStorage } from "@/app/utils/indexedDB-storage"; export type ChatMessage = RequestMessage & { date: string; @@ -665,7 +666,8 @@ export const useChatStore = createPersistStore( set(() => ({ sessions })); }, - clearAllData() { + async clearAllData() { + await indexedDBStorage.clear(); localStorage.clear(); location.reload(); }, diff --git a/app/utils/indexedDB-storage.ts b/app/utils/indexedDB-storage.ts new file mode 100644 index 00000000000..51ee92b8185 --- /dev/null +++ b/app/utils/indexedDB-storage.ts @@ -0,0 +1,38 @@ +import { StateStorage } from "zustand/middleware"; +import { get, set, del, clear } from "idb-keyval"; + +class IndexedDBStorage implements StateStorage { + public async getItem(name: string): Promise { + try { + return (await get(name)) || localStorage.getItem(name); + } catch (error) { + return localStorage.getItem(name); + } + } + + public async setItem(name: string, value: string): Promise { + try { + await set(name, value); + } catch (error) { + localStorage.setItem(name, value); + } + } + + public async removeItem(name: string): Promise { + try { + await del(name); + } catch (error) { + localStorage.removeItem(name); + } + } + + public async clear(): Promise { + try { + await clear(); + } catch (error) { + localStorage.clear(); + } + } +} + +export const indexedDBStorage = new IndexedDBStorage(); diff --git a/app/utils/store.ts b/app/utils/store.ts index 684a1911279..13bef6d5dfe 100644 --- a/app/utils/store.ts +++ b/app/utils/store.ts @@ -1,7 +1,8 @@ import { create } from "zustand"; -import { combine, persist } from "zustand/middleware"; +import { combine, persist, createJSONStorage } from "zustand/middleware"; import { Updater } from "../typing"; import { deepClone } from "./clone"; +import { indexedDBStorage } from "@/app/utils/indexedDB-storage"; type SecondParam = T extends ( _f: infer _F, @@ -31,6 +32,7 @@ export function createPersistStore( ) => M, persistOptions: SecondParam>>, ) { + persistOptions.storage = createJSONStorage(() => indexedDBStorage); return create( persist( combine( diff --git a/package.json b/package.json index eb0a5ef6735..1c6d78c208e 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "fuse.js": "^7.0.0", "heic2any": "^0.0.4", "html-to-image": "^1.11.11", + "idb-keyval": "^6.2.1", "lodash-es": "^4.17.21", "mermaid": "^10.6.1", "nanoid": "^5.0.3", diff --git a/yarn.lock b/yarn.lock index 793c845d722..1c7f834e876 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3926,6 +3926,11 @@ iconv-lite@0.6: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +idb-keyval@^6.2.1: + version "6.2.1" + resolved "https://registry.npmmirror.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" + integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== + ignore@^5.2.0: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"