-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
Copy pathatoms.ts
135 lines (113 loc) · 5.34 KB
/
atoms.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { atom, SetStateAction } from 'jotai'
import { Session, Toast, Settings, CopilotDetail, Message, SettingWindowTab, SessionsDump } from '../../shared/types'
import { selectAtom, atomWithStorage } from 'jotai/utils'
import { focusAtom } from 'jotai-optics'
import * as defaults from '../../shared/defaults'
import storage, { StorageKey } from '../storage'
import platform from '../packages/platform'
import { scheduleSaveSessionsToBackend } from '../packages/sync-sessions'
const _settingsAtom = atomWithStorage<Settings>(StorageKey.Settings, defaults.settings(), storage)
export const settingsAtom = atom(
(get) => {
const settings = get(_settingsAtom)
return Object.assign({}, defaults.settings(), settings)
},
(get, set, update: SetStateAction<Settings>) => {
const settings = get(_settingsAtom)
let newSettings = typeof update === 'function' ? update(settings) : update
if (newSettings.proxy !== settings.proxy) {
platform.ensureProxyConfig({ proxy: newSettings.proxy })
}
set(_settingsAtom, newSettings)
}
)
export const languageAtom = focusAtom(settingsAtom, (optic) => optic.prop('language'))
export const showWordCountAtom = focusAtom(settingsAtom, (optic) => optic.prop('showWordCount'))
export const showTokenCountAtom = focusAtom(settingsAtom, (optic) => optic.prop('showTokenCount'))
export const showTokenUsedAtom = focusAtom(settingsAtom, (optic) => optic.prop('showTokenUsed'))
export const showModelNameAtom = focusAtom(settingsAtom, (optic) => optic.prop('showModelName'))
export const showMessageTimestampAtom = focusAtom(settingsAtom, (optic) => optic.prop('showMessageTimestamp'))
export const themeAtom = focusAtom(settingsAtom, (optic) => optic.prop('theme'))
export const fontSizeAtom = focusAtom(settingsAtom, (optic) => optic.prop('fontSize'))
export const spellCheckAtom = focusAtom(settingsAtom, (optic) => optic.prop('spellCheck'))
export const allowReportingAndTrackingAtom = focusAtom(settingsAtom, (optic) => optic.prop('allowReportingAndTracking'))
export const enableMarkdownRenderingAtom = focusAtom(settingsAtom, (optic) => optic.prop('enableMarkdownRendering'))
export const autoGenerateTitleAtom = focusAtom(settingsAtom, (optic) => optic.prop('autoGenerateTitle'))
export const licenseDetailAtom = focusAtom(settingsAtom, (optic) => optic.prop('licenseDetail'))
// myCopilots
export const myCopilotsAtom = atomWithStorage<CopilotDetail[]>(StorageKey.MyCopilots, [], storage)
// sessions
const _sessionsTsAtom = atomWithStorage<number>(StorageKey.ChatSessionsTs, 0, storage)
const _sessionsAtom = atomWithStorage<Session[]>(StorageKey.ChatSessions, [], storage)
export const sessionsAtom = atom(
(get) => {
let sessions = get(_sessionsAtom)
if (sessions.length === 0) {
sessions = defaults.sessions()
}
return {
ts: get(_sessionsTsAtom),
sessions,
}
},
(get, set, update: SetStateAction<SessionsDump>) => {
let newDump =
typeof update === 'function' ? update({ ts: get(_sessionsTsAtom), sessions: get(_sessionsAtom) }) : update
if (newDump.sessions.length === 0) {
newDump = {
ts: Date.now(),
sessions: defaults.sessions(),
}
}
set(_sessionsTsAtom, newDump.ts)
set(_sessionsAtom, newDump.sessions)
scheduleSaveSessionsToBackend(newDump)
}
)
export const sortedSessionsAtom = atom((get) => {
return sortSessions(get(sessionsAtom).sessions)
})
export function sortSessions(sessions: Session[]): Session[] {
return [...sessions].reverse()
}
const _currentSessionIdCachedAtom = atomWithStorage<string | null>('_currentSessionIdCachedAtom', null)
export const currentSessionIdAtom = atom(
(get) => {
const idCached = get(_currentSessionIdCachedAtom)
const sessions = get(sortedSessionsAtom)
if (idCached && sessions.some((session) => session.id === idCached)) {
return idCached
}
return sessions[0].id
},
(_get, set, update: string) => {
set(_currentSessionIdCachedAtom, update)
}
)
export const currentSessionAtom = atom((get) => {
const id = get(currentSessionIdAtom)
const { sessions } = get(sessionsAtom)
let current = sessions.find((session) => session.id === id)
if (!current) {
return sessions[sessions.length - 1] // fallback to the last session
}
return current
})
export const currentSessionNameAtom = selectAtom(currentSessionAtom, (s) => s.name)
export const currsentSessionPicUrlAtom = selectAtom(currentSessionAtom, (s) => s.picUrl)
export const currentMessageListAtom = selectAtom(currentSessionAtom, (s) => {
let messageContext: Message[] = []
if (s.messages) {
messageContext = messageContext.concat(s.messages)
}
return messageContext
})
// toasts
export const toastsAtom = atom<Toast[]>([])
// theme
export const activeThemeAtom = atom<'light' | 'dark'>('light')
export const configVersionAtom = atomWithStorage<number>(StorageKey.ConfigVersion, 0, storage)
export const messageListRefAtom = atom<null | React.MutableRefObject<HTMLDivElement | null>>(null)
export const openSettingDialogAtom = atom<SettingWindowTab | null>(null)
export const sessionCleanDialogAtom = atom<Session | null>(null)
export const chatConfigDialogAtom = atom<Session | null>(null)