| | import { browser } from "$app/environment"; |
| | import { invalidate } from "$app/navigation"; |
| | import { base } from "$app/paths"; |
| | import { UrlDependency } from "$lib/types/UrlDependency"; |
| | import type { ObjectId } from "mongodb"; |
| | import { getContext, setContext } from "svelte"; |
| | import { type Writable, writable, get } from "svelte/store"; |
| |
|
| | type SettingsStore = { |
| | shareConversationsWithModelAuthors: boolean; |
| | hideEmojiOnSidebar: boolean; |
| | ethicsModalAccepted: boolean; |
| | ethicsModalAcceptedAt: Date | null; |
| | activeModel: string; |
| | customPrompts: Record<string, string>; |
| | recentlySaved: boolean; |
| | assistants: Array<ObjectId | string>; |
| | }; |
| |
|
| | type SettingsStoreWritable = Writable<SettingsStore> & { |
| | instantSet: (settings: Partial<SettingsStore>) => Promise<void>; |
| | }; |
| |
|
| | export function useSettingsStore() { |
| | return getContext<SettingsStoreWritable>("settings"); |
| | } |
| |
|
| | export function createSettingsStore(initialValue: Omit<SettingsStore, "recentlySaved">) { |
| | const baseStore = writable({ ...initialValue, recentlySaved: false }); |
| |
|
| | let timeoutId: NodeJS.Timeout; |
| |
|
| | async function setSettings(settings: Partial<SettingsStore>) { |
| | baseStore.update((s) => ({ |
| | ...s, |
| | ...settings, |
| | })); |
| |
|
| | clearTimeout(timeoutId); |
| |
|
| | if (browser) { |
| | timeoutId = setTimeout(async () => { |
| | await fetch(`${base}/settings`, { |
| | method: "POST", |
| | headers: { |
| | "Content-Type": "application/json", |
| | }, |
| | body: JSON.stringify({ |
| | ...get(baseStore), |
| | ...settings, |
| | }), |
| | }); |
| |
|
| | invalidate(UrlDependency.ConversationList); |
| | |
| | baseStore.update((s) => ({ |
| | ...s, |
| | recentlySaved: true, |
| | })); |
| | setTimeout(() => { |
| | baseStore.update((s) => ({ |
| | ...s, |
| | recentlySaved: false, |
| | })); |
| | }, 3000); |
| | invalidate(UrlDependency.ConversationList); |
| | }, 300); |
| | |
| | } |
| | } |
| | async function instantSet(settings: Partial<SettingsStore>) { |
| | baseStore.update((s) => ({ |
| | ...s, |
| | ...settings, |
| | })); |
| |
|
| | if (browser) { |
| | await fetch(`${base}/settings`, { |
| | method: "POST", |
| | headers: { |
| | "Content-Type": "application/json", |
| | }, |
| | body: JSON.stringify({ |
| | ...get(baseStore), |
| | ...settings, |
| | }), |
| | }); |
| | invalidate(UrlDependency.ConversationList); |
| | } |
| | } |
| |
|
| | const newStore = { |
| | subscribe: baseStore.subscribe, |
| | set: setSettings, |
| | instantSet, |
| | update: (fn: (s: SettingsStore) => SettingsStore) => { |
| | setSettings(fn(get(baseStore))); |
| | }, |
| | } satisfies SettingsStoreWritable; |
| |
|
| | setContext("settings", newStore); |
| |
|
| | return newStore; |
| | } |
| |
|