diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index f4cf14518c..b99060e234 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -72,7 +72,7 @@ const SessionRoute = () => { return ( {(_) => { - const persisted = tabs.store.filter((item) => item.type === "session") + const persisted = tabs.store().filter((item) => item.type === "session") return }} @@ -140,7 +140,7 @@ function DraftRoute() { return ( tab.type === "draft" && tab.draftID === search.draftId)} + when={tabs.store().find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === search.draftId)} keyed fallback={} > @@ -568,7 +568,7 @@ function LegacyTargetSessionRoute() { item.type === "session"), + tabs.store().filter((item) => item.type === "session"), params.id, server.key, ), diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 75ec3b7be5..b9f6febb33 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -11,6 +11,7 @@ import { createResource, Switch, Match, + type Accessor, type JSX, } from "solid-js" import { createStore, type SetStoreFunction, type Store } from "solid-js/store" @@ -117,21 +118,21 @@ export type PromptInputControls = { export function createPromptInputHistory(): PromptInputHistory { const [normal, setNormal] = createStore({ entries: [] }) const [shell, setShell] = createStore({ entries: [] }) - return createPromptInputHistoryStore(normal, setNormal, shell, setShell) + return createPromptInputHistoryStore(() => normal, setNormal, () => shell, setShell) } type PromptHistoryState = { entries: PromptHistoryStoredEntry[] } function createPromptInputHistoryStore( - normal: Store, + normal: Accessor, setNormal: SetStoreFunction, - shell: Store, + shell: Accessor, setShell: SetStoreFunction, ): PromptInputHistory { return { - entries: (mode) => (mode === "shell" ? shell.entries : normal.entries), + entries: (mode) => (mode === "shell" ? shell().entries : normal().entries), add(prompt, mode, comments) { - const current = mode === "shell" ? shell : normal + const current = mode === "shell" ? shell() : normal() const setCurrent = mode === "shell" ? setShell : setNormal const next = prependHistoryEntry(current.entries, prompt, comments) if (next === current.entries) return diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index 500cce7def..256d34969b 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -229,7 +229,7 @@ export function SessionHeader() { const canOpen = createMemo(() => platform.platform === "desktop" && !!platform.openPath && server.isLocal()) const current = createMemo( () => - options().find((o) => o.id === prefs.app) ?? + options().find((o) => o.id === prefs().app) ?? options()[0] ?? ({ id: "finder", label: fileManager().label, icon: fileManager().icon } as const), ) diff --git a/packages/app/src/components/titlebar-tab-strip.tsx b/packages/app/src/components/titlebar-tab-strip.tsx index 7ef53324cd..e2718e7e36 100644 --- a/packages/app/src/components/titlebar-tab-strip.tsx +++ b/packages/app/src/components/titlebar-tab-strip.tsx @@ -40,7 +40,7 @@ function SessionTabSlot(props: { let ref!: HTMLDivElement const sdk = createMemo(() => props.serverCtx()?.sdk ?? null) const cachedSession = createMemo(() => props.serverCtx()?.sync.session.peek(props.tab.sessionId)) - const persisted = createMemo(() => tabs.info[props.id]) + const persisted = createMemo(() => tabs.info()[props.id]) const [loadedSession] = createResource( () => { const ctx = props.serverCtx() diff --git a/packages/app/src/components/titlebar.tsx b/packages/app/src/components/titlebar.tsx index 2a818d565d..c86f6ab1de 100644 --- a/packages/app/src/components/titlebar.tsx +++ b/packages/app/src/components/titlebar.tsx @@ -275,10 +275,10 @@ export function Titlebar(props: { update?: TitlebarUpdate }) { const matchRoute = (route: LayoutRoute) => { if (route.type === "home") return if (route.type === "draft") { - return tabsStore.find((item) => item.type === "draft" && item.draftID === route.draftID) + return tabsStore().find((item) => item.type === "draft" && item.draftID === route.draftID) } if (route.type === "session") { - const main = tabsStore.find( + const main = tabsStore().find( (item) => item.type === "session" && item.server === route.server && item.sessionId === route.sessionId, ) @@ -286,7 +286,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) { const s = session() if (s?.parentID) { const parentID = s.parentID - const parent = tabsStore.find( + const parent = tabsStore().find( (item) => item.type === "session" && item.server === route.server && item.sessionId === parentID, ) if (parent) return parent @@ -395,7 +395,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) { keybind: "mod+w", hidden: true, onSelect: () => { - tabsStoreActions.closeTab(tabsStore.findIndex((tab) => current === tab)) + tabsStoreActions.closeTab(tabsStore().findIndex((tab) => current === tab)) }, }, { @@ -412,13 +412,13 @@ export function Titlebar(props: { update?: TitlebarUpdate }) { keybind: `mod+option+ArrowLeft,ctrl+shift+tab`, hidden: true, onSelect: () => { - let index = tabsStore.findIndex((tab) => tab === currentTab()) + let index = tabsStore().findIndex((tab) => tab === currentTab()) if (index === -1) return index -= 1 - if (index === -1) index = tabsStore.length - 1 + if (index === -1) index = tabsStore().length - 1 - const next = tabsStore[index] + const next = tabsStore()[index] if (next) tabs.select(next) }, }, @@ -429,13 +429,13 @@ export function Titlebar(props: { update?: TitlebarUpdate }) { keybind: `mod+option+ArrowRight,ctrl+tab`, hidden: true, onSelect: () => { - let index = tabsStore.findIndex((tab) => tab === currentTab()) + let index = tabsStore().findIndex((tab) => tab === currentTab()) if (index === -1) return index += 1 - if (index === tabsStore.length) index = 0 + if (index === tabsStore().length) index = 0 - const next = tabsStore[index] + const next = tabsStore()[index] if (next) tabs.select(next) }, }, @@ -482,7 +482,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) { { - const index = tabsStore.findIndex((item) => tabKey(item) === tabKey(tab)) + const index = tabsStore().findIndex((item) => tabKey(item) === tabKey(tab)) if (index !== -1) tabsStoreActions.closeTab(index) }} onReorder={(keys) => tabsStoreActions.reorder(keys)} diff --git a/packages/app/src/context/command.tsx b/packages/app/src/context/command.tsx index 0c935307ad..d46d740064 100644 --- a/packages/app/src/context/command.tsx +++ b/packages/app/src/context/command.tsx @@ -253,8 +253,8 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex const warnedDuplicates = new Set() type CommandCatalog = Record - const [catalog, setCatalog, _, catalogReady] = persisted( - Persist.global("command.catalog.v1"), + const [catalog, setCatalog, catalogReady] = persisted( + Persist.global("command.catalog().v1"), createStore({}), ) @@ -416,7 +416,7 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex const keybindConfig = (id: string) => { if (id === PALETTE_ID) return settings.keybinds.get(PALETTE_ID) ?? DEFAULT_PALETTE_KEYBIND const base = actionId(id) - return options().find((x) => actionId(x.id) === base)?.keybind ?? bind(base, catalog[base]?.keybind) + return options().find((x) => actionId(x.id) === base)?.keybind ?? bind(base, catalog()[base]?.keybind) } return { diff --git a/packages/app/src/context/comments.tsx b/packages/app/src/context/comments.tsx index 09e890a5e5..19581a3c00 100644 --- a/packages/app/src/context/comments.tsx +++ b/packages/app/src/context/comments.tsx @@ -181,13 +181,13 @@ export function createCommentSessionForTest(comments: Record({ comments: {}, }), ) - const session = createCommentSessionState(store, setStore) + const session = createCommentSessionState(store(), setStore) return { ready, diff --git a/packages/app/src/context/file/view-cache.ts b/packages/app/src/context/file/view-cache.ts index 87b859dea8..027cc300c2 100644 --- a/packages/app/src/context/file/view-cache.ts +++ b/packages/app/src/context/file/view-cache.ts @@ -37,7 +37,7 @@ function equalSelectedLines(a: SelectedLineRange | null | undefined, b: Selected function createViewSession(scope: ServerScope, dir: string, id: string | undefined) { const legacyViewKey = `${dir}/file${id ? "/" + id : ""}.v1` - const [view, setView, _, ready] = persisted( + const [view, setView, ready] = persisted( Persist.serverScoped(scope, dir, id, "file-view", [legacyViewKey]), createStore<{ file: Record @@ -49,7 +49,7 @@ function createViewSession(scope: ServerScope, dir: string, id: string | undefin const meta = { pruned: false } const pruneView = (keep?: string) => { - const keys = Object.keys(view.file) + const keys = Object.keys(view().file) if (keys.length <= MAX_VIEW_FILES) return const drop = keys.filter((key) => key !== keep).slice(0, keys.length - MAX_VIEW_FILES) @@ -71,9 +71,9 @@ function createViewSession(scope: ServerScope, dir: string, id: string | undefin pruneView() }) - const scrollTop = (path: string) => view.file[path]?.scrollTop - const scrollLeft = (path: string) => view.file[path]?.scrollLeft - const selectedLines = (path: string) => view.file[path]?.selectedLines + const scrollTop = (path: string) => view().file[path]?.scrollTop + const scrollLeft = (path: string) => view().file[path]?.scrollLeft + const selectedLines = (path: string) => view().file[path]?.selectedLines const setScrollTop = (path: string, top: number) => { setView( diff --git a/packages/app/src/context/global-sync/child-store.test.ts b/packages/app/src/context/global-sync/child-store.test.ts index ddbfffe1ad..a116b4eaa4 100644 --- a/packages/app/src/context/global-sync/child-store.test.ts +++ b/packages/app/src/context/global-sync/child-store.test.ts @@ -9,9 +9,8 @@ import { ServerScope } from "@/utils/server-scope" let createChildStoreManager: typeof import("./child-store").createChildStoreManager const querySingles: Array<() => { queryKey?: unknown[]; enabled?: boolean }> = [] const persist: typeof import("@/utils/persist").persisted = (_target, store) => [ - store[0], + () => store[0], store[1], - null, Object.assign(() => true, { promise: undefined }), ] diff --git a/packages/app/src/context/global-sync/child-store.ts b/packages/app/src/context/global-sync/child-store.ts index 53b9536182..05ddd82b67 100644 --- a/packages/app/src/context/global-sync/child-store.ts +++ b/packages/app/src/context/global-sync/child-store.ts @@ -1,4 +1,4 @@ -import { createRoot, createSignal, getOwner, onCleanup, runWithOwner, type Owner } from "solid-js" +import { createRoot, createSignal, getOwner, onCleanup, runWithOwner, type Accessor, type Owner } from "solid-js" import { createStore, type SetStoreFunction, type Store } from "solid-js/store" import { Persist, persisted } from "@/utils/persist" import type { VcsInfo } from "@opencode-ai/sdk/v2/client" @@ -157,7 +157,7 @@ export function createChildStoreManager(input: { ) if (!vcs) throw new Error(input.translate("error.childStore.persistedCacheCreateFailed")) const vcsStore = vcs[0] - vcsCache.set(key, { store: vcsStore, setStore: vcs[1], ready: vcs[3] }) + vcsCache.set(key, { store: vcsStore, setStore: vcs[1], ready: vcs[2] }) const meta = runWithOwner(input.owner, () => input.persist( @@ -166,7 +166,7 @@ export function createChildStoreManager(input: { ), ) if (!meta) throw new Error(input.translate("error.childStore.persistedProjectMetadataCreateFailed")) - metaCache.set(key, { store: meta[0], setStore: meta[1], ready: meta[3] }) + metaCache.set(key, { store: meta[0], setStore: meta[1], ready: meta[2] }) const icon = runWithOwner(input.owner, () => input.persist( @@ -175,12 +175,12 @@ export function createChildStoreManager(input: { ), ) if (!icon) throw new Error(input.translate("error.childStore.persistedProjectIconCreateFailed")) - iconCache.set(key, { store: icon[0], setStore: icon[1], ready: icon[3] }) + iconCache.set(key, { store: icon[0], setStore: icon[1], ready: icon[2] }) const init = () => createRoot((dispose) => { - const initialMeta = meta[0].value - const initialIcon = icon[0].value + const initialMeta = meta[0]().value + const initialIcon = icon[0]().value const [mcpEnabled, setMcpEnabled] = createSignal(false) const pathQuery = useQuery(() => input.queryOptions.path(key)) @@ -241,7 +241,7 @@ export function createChildStoreManager(input: { get lsp() { return lspQuery.isLoading ? [] : (lspQuery.data ?? []) }, - vcs: vcsStore.value, + vcs: vcsStore().value, limit: 5, message: {}, part: {}, @@ -251,28 +251,28 @@ export function createChildStoreManager(input: { disposers.set(key, dispose) mcpToggles.set(key, setMcpEnabled) - const onPersistedInit = (init: Promise | string | null, run: () => void) => { - if (!(init instanceof Promise)) return - void init.then(() => { + const onPersistedInit = (ready: Accessor & { promise: undefined | Promise }, run: () => void) => { + if (!ready.promise) return + void ready.promise.then(() => { if (children[key] !== child) return run() }) } onPersistedInit(vcs[2], () => { - const cached = vcsStore.value + const cached = vcsStore().value if (!cached?.branch) return child[1]("vcs", (value) => value ?? cached) }) onPersistedInit(meta[2], () => { if (child[0].projectMeta !== initialMeta) return - child[1]("projectMeta", meta[0].value) + child[1]("projectMeta", meta[0]().value) }) onPersistedInit(icon[2], () => { if (child[0].icon !== initialIcon) return - child[1]("icon", icon[0].value) + child[1]("icon", icon[0]().value) }) }) diff --git a/packages/app/src/context/global-sync/event-reducer.test.ts b/packages/app/src/context/global-sync/event-reducer.test.ts index 2811e6e3c6..a715e710bf 100644 --- a/packages/app/src/context/global-sync/event-reducer.test.ts +++ b/packages/app/src/context/global-sync/event-reducer.test.ts @@ -549,7 +549,7 @@ describe("applyDirectoryEvent", () => { directory: "/tmp", loadLsp() {}, vcsCache: { - store: cacheStore, + store: () => cacheStore, setStore: setCacheStore, ready: () => true, }, diff --git a/packages/app/src/context/global-sync/types.ts b/packages/app/src/context/global-sync/types.ts index 86b489cd09..085ad94044 100644 --- a/packages/app/src/context/global-sync/types.ts +++ b/packages/app/src/context/global-sync/types.ts @@ -19,7 +19,7 @@ import type { } from "@opencode-ai/sdk/v2/client" import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context" import type { Accessor } from "solid-js" -import type { SetStoreFunction, Store } from "solid-js/store" +import type { SetStoreFunction } from "solid-js/store" export type ProjectMeta = { name?: string @@ -85,19 +85,19 @@ export type State = { } export type VcsCache = { - store: Store<{ value: VcsInfo | undefined }> + store: Accessor<{ value: VcsInfo | undefined }> setStore: SetStoreFunction<{ value: VcsInfo | undefined }> ready: Accessor } export type MetaCache = { - store: Store<{ value: ProjectMeta | undefined }> + store: Accessor<{ value: ProjectMeta | undefined }> setStore: SetStoreFunction<{ value: ProjectMeta | undefined }> ready: Accessor } export type IconCache = { - store: Store<{ value: string | undefined }> + store: Accessor<{ value: string | undefined }> setStore: SetStoreFunction<{ value: string | undefined }> ready: Accessor } diff --git a/packages/app/src/context/highlights.tsx b/packages/app/src/context/highlights.tsx index 058f7cc4b6..8e6300f680 100644 --- a/packages/app/src/context/highlights.tsx +++ b/packages/app/src/context/highlights.tsx @@ -144,7 +144,7 @@ export const { use: useHighlights, provider: HighlightsProvider } = createSimple const platform = usePlatform() const dialog = useDialog() const settings = useSettings() - const [store, setStore, _, ready] = persisted("highlights.v1", createStore({ version: undefined })) + const [store, setStore, ready] = persisted("highlights.v1", createStore({ version: undefined })) const [range, setRange] = createStore({ from: undefined as string | undefined, @@ -208,7 +208,7 @@ export const { use: useHighlights, provider: HighlightsProvider } = createSimple if (!platform.version) return state.started = true - const previous = store.version + const previous = store().version if (!previous) { setStore("version", platform.version) return @@ -225,7 +225,7 @@ export const { use: useHighlights, provider: HighlightsProvider } = createSimple from: () => range.from, to: () => range.to, get last() { - return store.version + return store().version }, markSeen, } diff --git a/packages/app/src/context/language.tsx b/packages/app/src/context/language.tsx index 6b2eb314c8..38835e780d 100644 --- a/packages/app/src/context/language.tsx +++ b/packages/app/src/context/language.tsx @@ -201,14 +201,14 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont gate: false, init: (props: { locale?: Locale }) => { const initial = props.locale ?? readStoredLocale() ?? detectLocale() - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( Persist.global("language", ["language.v1"]), createStore({ locale: initial, }), ) - const locale = createMemo(() => normalizeLocale(store.locale)) + const locale = createMemo(() => normalizeLocale(store().locale)) const intl = createMemo(() => INTL[locale()]) const [dict] = createResource(locale, loadDict, { diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx index b09a77eb33..1f7c172b63 100644 --- a/packages/app/src/context/layout.tsx +++ b/packages/app/src/context/layout.tsx @@ -171,7 +171,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( if (value.type === "home") return value if (value.server) return value if (value.type === "draft") { - const draft = tabs.store.find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === value.draftID) + const draft = tabs.store().find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === value.draftID) if (draft) return { ...value, server: draft.server } } return { ...value, server: server.key } @@ -268,7 +268,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( } const target = Persist.serverGlobal(serverSdk().scope, "layout", ["layout.v6"]) - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( { ...target, migrate }, createStore({ sidebar: { @@ -350,8 +350,8 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( keep, max: MAX_SESSION_KEYS, used: usage.used, - view: Object.keys(store.sessionView), - tabs: Object.keys(store.sessionTabs), + view: Object.keys(store().sessionView), + tabs: Object.keys(store().sessionTabs), }) if (drop.length === 0) return @@ -385,9 +385,9 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( const scroll = createScrollPersistence({ debounceMs: 250, - getSnapshot: (sessionKey) => store.sessionView[sessionKey]?.scroll, + getSnapshot: (sessionKey) => store().sessionView[sessionKey]?.scroll, onFlush: (sessionKey, next) => { - const current = store.sessionView[sessionKey] + const current = store().sessionView[sessionKey] const keep = usage.active ?? sessionKey if (!current) { setStore("sessionView", sessionKey, { scroll: next }) @@ -597,18 +597,18 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( route, ready, home: { - selection: createMemo(() => store.home.selection), + selection: createMemo(() => store().home.selection), setSelection(selection: HomeProjectSelection) { setStore("home", "selection", reconcile(selection)) }, }, handoff: { - tabs: createMemo(() => store.handoff?.tabs), + tabs: createMemo(() => store().handoff?.tabs), setTabs(dir: string, id: string) { setStore("handoff", "tabs", { scope: serverSdk().scope, dir, id, at: Date.now() }) }, clearTabs() { - if (!store.handoff?.tabs) return + if (!store().handoff?.tabs) return setStore("handoff", "tabs", undefined) }, }, @@ -642,7 +642,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, }, sidebar: { - opened: createMemo(() => store.sidebar.opened), + opened: createMemo(() => store().sidebar.opened), open() { setStore("sidebar", "opened", true) }, @@ -652,31 +652,31 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( toggle() { setStore("sidebar", "opened", (x) => !x) }, - width: createMemo(() => store.sidebar.width), + width: createMemo(() => store().sidebar.width), resize(width: number) { setStore("sidebar", "width", width) }, workspaces(directory: string) { - return () => store.sidebar.workspaces[directory] ?? store.sidebar.workspacesDefault ?? false + return () => store().sidebar.workspaces[directory] ?? store().sidebar.workspacesDefault ?? false }, setWorkspaces(directory: string, value: boolean) { setStore("sidebar", "workspaces", directory, value) }, toggleWorkspaces(directory: string) { - const current = store.sidebar.workspaces[directory] ?? store.sidebar.workspacesDefault ?? false + const current = store().sidebar.workspaces[directory] ?? store().sidebar.workspacesDefault ?? false setStore("sidebar", "workspaces", directory, !current) }, }, terminal: { - height: createMemo(() => store.terminal.height), + height: createMemo(() => store().terminal.height), resize(height: number) { setStore("terminal", "height", height) }, }, review: { - diffStyle: createMemo(() => store.review?.diffStyle ?? "split"), + diffStyle: createMemo(() => store().review?.diffStyle ?? "split"), setDiffStyle(diffStyle: ReviewDiffStyle) { - if (!store.review) { + if (!store().review) { setStore("review", { diffStyle, panelOpened: DEFAULT_REVIEW_PANEL_OPENED }) return } @@ -684,39 +684,39 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, }, fileTree: { - opened: createMemo(() => store.fileTree?.opened ?? true), - width: createMemo(() => store.fileTree?.width ?? DEFAULT_FILE_TREE_WIDTH), - tab: createMemo(() => store.fileTree?.tab ?? "changes"), + opened: createMemo(() => store().fileTree?.opened ?? true), + width: createMemo(() => store().fileTree?.width ?? DEFAULT_FILE_TREE_WIDTH), + tab: createMemo(() => store().fileTree?.tab ?? "changes"), setTab(tab: "changes" | "all") { - if (!store.fileTree) { + if (!store().fileTree) { setStore("fileTree", { opened: true, width: DEFAULT_FILE_TREE_WIDTH, tab }) return } setStore("fileTree", "tab", tab) }, open() { - if (!store.fileTree) { + if (!store().fileTree) { setStore("fileTree", { opened: true, width: DEFAULT_FILE_TREE_WIDTH, tab: "changes" }) return } setStore("fileTree", "opened", true) }, close() { - if (!store.fileTree) { + if (!store().fileTree) { setStore("fileTree", { opened: false, width: DEFAULT_FILE_TREE_WIDTH, tab: "changes" }) return } setStore("fileTree", "opened", false) }, toggle() { - if (!store.fileTree) { + if (!store().fileTree) { setStore("fileTree", { opened: true, width: DEFAULT_FILE_TREE_WIDTH, tab: "changes" }) return } setStore("fileTree", "opened", (x) => !x) }, resize(width: number) { - if (!store.fileTree) { + if (!store().fileTree) { setStore("fileTree", { opened: true, width, tab: "changes" }) return } @@ -724,9 +724,9 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, }, session: { - width: createMemo(() => store.session?.width ?? DEFAULT_SESSION_WIDTH), + width: createMemo(() => store().session?.width ?? DEFAULT_SESSION_WIDTH), resize(width: number) { - if (!store.session) { + if (!store().session) { setStore("session", { width }) return } @@ -734,7 +734,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, }, mobileSidebar: { - opened: createMemo(() => store.mobileSidebar?.opened ?? false), + opened: createMemo(() => store().mobileSidebar?.opened ?? false), show() { setStore("mobileSidebar", "opened", true) }, @@ -749,7 +749,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( set(sessionKey: string, messageID: string) { const at = Date.now() touch(sessionKey) - const current = store.sessionView[sessionKey] + const current = store().sessionView[sessionKey] if (!current) { setStore("sessionView", sessionKey, { scroll: {}, @@ -770,7 +770,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( ) }, consume(sessionKey: string) { - const current = store.sessionView[sessionKey] + const current = store().sessionView[sessionKey] const message = current?.pendingMessage const at = current?.pendingMessageAt if (!message || !at) return @@ -790,13 +790,13 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, view(sessionKey: string | Accessor) { const key = createSessionKeyReader(sessionKey, ensureKey) - const s = createMemo(() => store.sessionView[key()] ?? { scroll: {} }) - const terminalOpened = createMemo(() => store.terminal?.opened ?? false) - const reviewPanelOpened = createMemo(() => store.review?.panelOpened ?? DEFAULT_REVIEW_PANEL_OPENED) + const s = createMemo(() => store().sessionView[key()] ?? { scroll: {} }) + const terminalOpened = createMemo(() => store().terminal?.opened ?? false) + const reviewPanelOpened = createMemo(() => store().review?.panelOpened ?? DEFAULT_REVIEW_PANEL_OPENED) const reviewPanelSource = createMemo(() => (reviewPanelOpened() ? ephemeral.reviewPanelSource : "other")) function setTerminalOpened(next: boolean) { - const current = store.terminal + const current = store().terminal if (!current) { setStore("terminal", { height: DEFAULT_TERMINAL_HEIGHT, opened: next }) return @@ -809,7 +809,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( function setReviewPanelOpened(next: boolean, source: ReviewPanelSource) { const nextSource = next ? source : "other" - const current = store.review + const current = store().review if (!current) { batch(() => { setStore("review", { diffStyle: "split" as ReviewDiffStyle, panelOpened: next }) @@ -840,7 +840,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( get: () => s().todoCollapsed ?? false, set(collapsed: boolean) { const session = key() - const current = store.sessionView[session] + const current = store().sessionView[session] if (!current) { setStore("sessionView", session, { scroll: {}, todoCollapsed: collapsed }) } else { @@ -878,7 +878,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setOpen(open: string[]) { const session = key() const next = Array.from(new Set(open)) - const current = store.sessionView[session] + const current = store().sessionView[session] if (!current) { setStore("sessionView", session, { scroll: {}, @@ -892,7 +892,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, openPath(path: string) { const session = key() - const current = store.sessionView[session] + const current = store().sessionView[session] if (!current) { setStore("sessionView", session, { scroll: {}, @@ -911,7 +911,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, closePath(path: string) { const session = key() - const current = store.sessionView[session]?.reviewOpen + const current = store().sessionView[session]?.reviewOpen if (!current) return const index = current.indexOf(path) @@ -928,7 +928,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, togglePath(path: string) { const session = key() - const current = store.sessionView[session]?.reviewOpen + const current = store().sessionView[session]?.reviewOpen if (!current || !current.includes(path)) { this.openPath(path) return @@ -942,7 +942,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( tabs(sessionKey: string | Accessor) { const key = createSessionKeyReader(sessionKey, ensureKey) const path = createMemo(() => sessionPath(key())) - const tabs = createMemo(() => store.sessionTabs[key()] ?? { all: [] }) + const tabs = createMemo(() => store().sessionTabs[key()] ?? { all: [] }) const normalize = (tab: string) => normalizeSessionTab(path(), tab) const normalizeAll = (all: string[]) => normalizeSessionTabList(path(), all) return { @@ -952,7 +952,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setActive(tab: string | undefined) { const session = key() const next = tab ? normalize(tab) : tab - if (!store.sessionTabs[session]) { + if (!store().sessionTabs[session]) { setStore("sessionTabs", session, { all: [], active: next }) } else { setStore("sessionTabs", session, "active", next) @@ -961,7 +961,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setAll(all: string[]) { const session = key() const next = normalizeAll(all).filter((tab) => tab !== "review") - if (!store.sessionTabs[session]) { + if (!store().sessionTabs[session]) { setStore("sessionTabs", session, { all: next, active: undefined }) } else { setStore("sessionTabs", session, "all", next) @@ -969,12 +969,12 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, async open(tab: string) { const session = key() - const next = nextSessionTabsForOpen(store.sessionTabs[session], normalize(tab)) + const next = nextSessionTabsForOpen(store().sessionTabs[session], normalize(tab)) setStore("sessionTabs", session, next) }, close(tab: string) { const session = key() - const current = store.sessionTabs[session] + const current = store().sessionTabs[session] if (!current) return if (tab === "review") { @@ -998,7 +998,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, move(tab: string, to: number) { const session = key() - const current = store.sessionTabs[session] + const current = store().sessionTabs[session] if (!current) return const index = current.all.findIndex((f) => f === tab) if (index === -1) return diff --git a/packages/app/src/context/local.tsx b/packages/app/src/context/local.tsx index 415da747e0..9f832cb8d1 100644 --- a/packages/app/src/context/local.tsx +++ b/packages/app/src/context/local.tsx @@ -125,7 +125,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const scope = createMemo(() => { const session = id() if (!session) return store.draft ?? store.promoting - return saved.session[session] ?? handoff.get(handoffKey(serverSDK().scope, sdk().directory, session)) + return saved().session[session] ?? handoff.get(handoffKey(serverSDK().scope, sdk().directory, session)) }) createEffect(() => { @@ -135,7 +135,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const key = handoffKey(serverSDK().scope, sdk().directory, session) const next = handoff.get(key) if (!next) return - if (saved.session[session] !== undefined) { + if (saved().session[session] !== undefined) { handoff.delete(key) setStore("promoting", undefined) return @@ -395,7 +395,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const session = id() if (!session) return if (msg.sessionID !== session) return - if (saved.session[session] !== undefined) return + if (saved().session[session] !== undefined) return if (handoff.has(handoffKey(serverSDK().scope, sdk().directory, session))) return setSaved("session", session, { diff --git a/packages/app/src/context/models.tsx b/packages/app/src/context/models.tsx index 736dc3a7c5..16c620e5c3 100644 --- a/packages/app/src/context/models.tsx +++ b/packages/app/src/context/models.tsx @@ -28,7 +28,7 @@ export const { use: useModels, provider: ModelsProvider } = createSimpleContext( init: (props: { directory?: Accessor } = {}) => { const providers = useProviders(props.directory) - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( Persist.global("model", ["model.v1"]), createStore({ user: [], @@ -89,7 +89,7 @@ export const { use: useModels, provider: ModelsProvider } = createSimpleContext( const visibility = createMemo(() => { const map = new Map() - for (const item of store.user) map.set(`${item.providerID}:${item.modelID}`, item.visibility) + for (const item of store().user) map.set(`${item.providerID}:${item.modelID}`, item.visibility) return map }) @@ -104,12 +104,12 @@ export const { use: useModels, provider: ModelsProvider } = createSimpleContext( const find = (key: ModelKey) => list().find((m) => m.id === key.modelID && m.provider.id === key.providerID) function update(model: ModelKey, state: Visibility) { - const index = store.user.findIndex((x) => x.modelID === model.modelID && x.providerID === model.providerID) + const index = store().user.findIndex((x) => x.modelID === model.modelID && x.providerID === model.providerID) if (index >= 0) { setStore("user", index, (current) => ({ ...current, visibility: state })) return } - setStore("user", store.user.length, { ...model, visibility: state }) + setStore("user", store().user.length, { ...model, visibility: state }) } const visible = (model: ModelKey) => { @@ -128,17 +128,17 @@ export const { use: useModels, provider: ModelsProvider } = createSimpleContext( } const push = (model: ModelKey) => { - const uniq = uniqueBy([model, ...store.recent], (x) => `${x.providerID}:${x.modelID}`) + const uniq = uniqueBy([model, ...store().recent], (x) => `${x.providerID}:${x.modelID}`) if (uniq.length > RECENT_LIMIT) uniq.pop() setStore("recent", uniq) } const variantKey = (model: ModelKey) => `${model.providerID}/${model.modelID}` - const getVariant = (model: ModelKey) => store.variant?.[variantKey(model)] + const getVariant = (model: ModelKey) => store().variant?.[variantKey(model)] const setVariant = (model: ModelKey, value: string | undefined) => { const key = variantKey(model) - if (!store.variant) { + if (!store().variant) { setStore("variant", { [key]: value }) return } @@ -147,7 +147,7 @@ export const { use: useModels, provider: ModelsProvider } = createSimpleContext( const [recentModels] = createResource( async () => { - const recent = store.recent + const recent = store().recent await ready.promise return recent }, diff --git a/packages/app/src/context/notification.tsx b/packages/app/src/context/notification.tsx index e12f8f1250..9ea30dbda9 100644 --- a/packages/app/src/context/notification.tsx +++ b/packages/app/src/context/notification.tsx @@ -127,7 +127,7 @@ export const { use: useNotification, provider: NotificationProvider } = createSi const activeServer = createMemo(() => { if (params.serverKey) return requireServerKey(params.serverKey) if (search.draftId) { - const draft = tabs.store.find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === search.draftId) + const draft = tabs.store().find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === search.draftId) if (draft) return draft.server } return server.key @@ -222,13 +222,13 @@ function createServerNotificationState(input: { const currentDirectory = input.directory const currentSession = input.sessionID - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( Persist.serverGlobal(serverSDK().scope, "notification", ["notification.v1"]), createStore({ list: [] as Notification[], }), ) - const [index, setIndex] = createStore(buildNotificationIndex(store.list)) + const [index, setIndex] = createStore(buildNotificationIndex(store().list)) const meta = { pruned: false, disposed: false } @@ -285,7 +285,7 @@ function createServerNotificationState(input: { if (!ready()) return if (meta.pruned) return meta.pruned = true - const list = pruneNotifications(store.list) + const list = pruneNotifications(store().list) batch(() => { setStore("list", list) setIndex(reconcile(buildNotificationIndex(list), { merge: false })) @@ -293,9 +293,9 @@ function createServerNotificationState(input: { }) const append = (notification: Notification) => { - const list = pruneNotifications([...store.list, notification]) + const list = pruneNotifications([...store().list, notification]) const keep = new Set(list) - const removed = store.list.filter((n) => !keep.has(n)) + const removed = store().list.filter((n) => !keep.has(n)) batch(() => { if (keep.has(notification)) appendToIndex(notification) diff --git a/packages/app/src/context/permission.tsx b/packages/app/src/context/permission.tsx index ff43638bbc..0a379d6156 100644 --- a/packages/app/src/context/permission.tsx +++ b/packages/app/src/context/permission.tsx @@ -59,7 +59,7 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple return hasPermissionPromptRules(store.config.permission) }) - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( { ...Persist.serverGlobal(serverSDK().scope, "permission", ["permission.v3"]), migrate(value) { @@ -91,7 +91,7 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple const perm = childStore.config.permission if (typeof perm === "string" && perm === "allow") { const key = directoryAcceptKey(directory) - if (store.autoAccept[key] === undefined) { + if (store().autoAccept[key] === undefined) { setStore( produce((draft) => { draft.autoAccept[key] = true @@ -143,16 +143,16 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple function isAutoAccepting(sessionID: string, directory?: string) { const session = directory ? serverSync().child(directory, { bootstrap: false })[0].session : [] - return autoRespondsPermission(store.autoAccept, session, { sessionID }, directory) + return autoRespondsPermission(store().autoAccept, session, { sessionID }, directory) } function isAutoAcceptingDirectory(directory: string) { - return isDirectoryAutoAccepting(store.autoAccept, directory) + return isDirectoryAutoAccepting(store().autoAccept, directory) } function shouldAutoRespond(permission: PermissionRequest, directory?: string) { const session = directory ? serverSync().child(directory, { bootstrap: false })[0].session : [] - return autoRespondsPermission(store.autoAccept, session, permission, directory) + return autoRespondsPermission(store().autoAccept, session, permission, directory) } function bumpEnableVersion(sessionID: string, directory?: string) { diff --git a/packages/app/src/context/prompt.tsx b/packages/app/src/context/prompt.tsx index c361493516..1e7a390f2e 100644 --- a/packages/app/src/context/prompt.tsx +++ b/packages/app/src/context/prompt.tsx @@ -206,12 +206,12 @@ function promptTarget(serverScope: ServerScope, scope: Scope) { } export function createPromptSession(serverScope: ServerScope, scope: Scope) { - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( promptTarget(serverScope, scope), createStore(promptStore()), ) - return { ready, ...createPromptStateValue(store, setStore) } + return { ready, ...createPromptStateValue(store(), setStore) } } export function createPromptReady(session: Accessor) { @@ -327,7 +327,7 @@ export const { use: usePrompt, provider: PromptProvider } = createSimpleContext( const scope = () => search.draftId ? { draftID: search.draftId } : { dir: base64Encode(sdk().directory), id: params.id } const load = (scope: Scope) => { - const current = settings.general.newLayoutDesigns() ? selectPromptTab(tabs.store, scope, serverKey()) : undefined + const current = settings.general.newLayoutDesigns() ? selectPromptTab(tabs.store(), scope, serverKey()) : undefined if (current) { return createTabPromptState(tabs, current, serverSDK().scope, scope) } diff --git a/packages/app/src/context/server.tsx b/packages/app/src/context/server.tsx index 450129f458..7226c84510 100644 --- a/packages/app/src/context/server.tsx +++ b/packages/app/src/context/server.tsx @@ -260,7 +260,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( canonicalLocalServer?: ServerConnection.Key servers?: Array }) => { - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( { ...Persist.global("server", ["server.v3"]), migrate: (value) => migrateCanonicalLocalServerState(value, props.canonicalLocalServer), @@ -276,7 +276,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( const url = (x: StoredServer) => (typeof x === "string" ? x : "type" in x ? x.http.url : x.url) const allServers = createMemo((): Array => { - return resolveServerList({ stored: store.list, props: props.servers }) + return resolveServerList({ stored: store().list, props: props.servers }) }) const [state, setState] = createStore({ @@ -292,11 +292,11 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( if (!url_) return const conn: ServerConnection.Http = { ...input, authToken: undefined, http: { ...input.http, url: url_ } } return batch(() => { - const existing = store.list.findIndex((x) => url(x) === url_) + const existing = store().list.findIndex((x) => url(x) === url_) if (existing !== -1) { setStore("list", existing, conn) } else { - setStore("list", store.list.length, conn) + setStore("list", store().list.length, conn) } setState("active", ServerConnection.key(conn)) return conn @@ -305,7 +305,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( function remove(key: ServerConnection.Key) { const next = nextServerAfterRemoval(allServers(), key, props.defaultServer) - const list = store.list.filter((x) => url(x) !== key) + const list = store().list.filter((x) => url(x) !== key) batch(() => { setStore("list", list) if (state.active === key) setState("active", next) @@ -318,12 +318,12 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( ) const scope = (key = state.active) => ServerScope.fromServerKey(key, props.canonicalLocalServer) - const projects = createServerProjects({ scope, store, setStore }) + const projects = createServerProjects({ scope, store: store(), setStore }) const projectStores = new Map>() const projectsForServer = (key: ServerConnection.Key) => { const existing = projectStores.get(key) if (existing) return existing - const next = createServerProjects({ scope: () => scope(key), store, setStore }) + const next = createServerProjects({ scope: () => scope(key), store: store(), setStore }) projectStores.set(key, next) return next } diff --git a/packages/app/src/context/settings.tsx b/packages/app/src/context/settings.tsx index 8d4f61079c..3ecf117d3f 100644 --- a/packages/app/src/context/settings.tsx +++ b/packages/app/src/context/settings.tsx @@ -152,45 +152,45 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont name: "Settings", gate: false, init: () => { - const [store, setStore, _, ready] = persisted("settings.v3", createStore(defaultSettings)) - const showFileTree = withFallback(() => store.general?.showFileTree, defaultSettings.general.showFileTree) - const showSearch = withFallback(() => store.general?.showSearch, defaultSettings.general.showSearch) - const showStatus = withFallback(() => store.general?.showStatus, defaultSettings.general.showStatus) + const [store, setStore, ready] = persisted("settings.v3", createStore(defaultSettings)) + const showFileTree = withFallback(() => store().general?.showFileTree, defaultSettings.general.showFileTree) + const showSearch = withFallback(() => store().general?.showSearch, defaultSettings.general.showSearch) + const showStatus = withFallback(() => store().general?.showStatus, defaultSettings.general.showStatus) const showCustomAgents = withFallback( - () => store.general?.showCustomAgents, + () => store().general?.showCustomAgents, defaultSettings.general.showCustomAgents, ) - const newLayoutDesigns = withFallback(() => store.general?.newLayoutDesigns, newLayoutDesignsDefault) + const newLayoutDesigns = withFallback(() => store().general?.newLayoutDesigns, newLayoutDesignsDefault) const visible = (preference: () => boolean) => createMemo(() => !newLayoutDesigns() || preference()) createEffect(() => { if (typeof document === "undefined") return const root = document.documentElement - root.style.setProperty("--font-family-mono", monoFontFamily(store.appearance?.mono)) - root.style.setProperty("--font-family-sans", sansFontFamily(store.appearance?.sans)) + root.style.setProperty("--font-family-mono", monoFontFamily(store().appearance?.mono)) + root.style.setProperty("--font-family-sans", sansFontFamily(store().appearance?.sans)) }) createEffect(() => { - if (store.general?.followup !== "queue") return + if (store().general?.followup !== "queue") return setStore("general", "followup", "steer") }) return { ready, get current() { - return store + return store() }, general: { - autoSave: withFallback(() => store.general?.autoSave, defaultSettings.general.autoSave), + autoSave: withFallback(() => store().general?.autoSave, defaultSettings.general.autoSave), setAutoSave(value: boolean) { setStore("general", "autoSave", value) }, - releaseNotes: withFallback(() => store.general?.releaseNotes, defaultSettings.general.releaseNotes), + releaseNotes: withFallback(() => store().general?.releaseNotes, defaultSettings.general.releaseNotes), setReleaseNotes(value: boolean) { setStore("general", "releaseNotes", value) }, followup: withFallback( - () => (store.general?.followup === "queue" ? "steer" : store.general?.followup), + () => (store().general?.followup === "queue" ? "steer" : store().general?.followup), defaultSettings.general.followup, ), setFollowup(value: "queue" | "steer") { @@ -200,7 +200,7 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont setShowFileTree(value: boolean) { setStore("general", "showFileTree", value) }, - showNavigation: withFallback(() => store.general?.showNavigation, defaultSettings.general.showNavigation), + showNavigation: withFallback(() => store().general?.showNavigation, defaultSettings.general.showNavigation), setShowNavigation(value: boolean) { setStore("general", "showNavigation", value) }, @@ -212,26 +212,26 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont setShowStatus(value: boolean) { setStore("general", "showStatus", value) }, - showTerminal: withFallback(() => store.general?.showTerminal, defaultSettings.general.showTerminal), + showTerminal: withFallback(() => store().general?.showTerminal, defaultSettings.general.showTerminal), setShowTerminal(value: boolean) { setStore("general", "showTerminal", value) }, showReasoningSummaries: withFallback( - () => store.general?.showReasoningSummaries, + () => store().general?.showReasoningSummaries, defaultSettings.general.showReasoningSummaries, ), setShowReasoningSummaries(value: boolean) { setStore("general", "showReasoningSummaries", value) }, shellToolPartsExpanded: withFallback( - () => store.general?.shellToolPartsExpanded, + () => store().general?.shellToolPartsExpanded, defaultSettings.general.shellToolPartsExpanded, ), setShellToolPartsExpanded(value: boolean) { setStore("general", "shellToolPartsExpanded", value) }, editToolPartsExpanded: withFallback( - () => store.general?.editToolPartsExpanded, + () => store().general?.editToolPartsExpanded, defaultSettings.general.editToolPartsExpanded, ), setEditToolPartsExpanded(value: boolean) { @@ -242,7 +242,7 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont setStore("general", "showCustomAgents", value) }, mobileTitlebarPosition: withFallback( - () => store.general?.mobileTitlebarPosition, + () => store().general?.mobileTitlebarPosition, defaultSettings.general.mobileTitlebarPosition, ), setMobileTitlebarPosition(value: "top" | "bottom") { @@ -260,25 +260,25 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont customAgents: visible(showCustomAgents), }, appearance: { - fontSize: withFallback(() => store.appearance?.fontSize, defaultSettings.appearance.fontSize), + fontSize: withFallback(() => store().appearance?.fontSize, defaultSettings.appearance.fontSize), setFontSize(value: number) { setStore("appearance", "fontSize", value) }, - font: withFallback(() => store.appearance?.mono, defaultSettings.appearance.mono), + font: withFallback(() => store().appearance?.mono, defaultSettings.appearance.mono), setFont(value: string) { setStore("appearance", "mono", value.trim() ? value : "") }, - uiFont: withFallback(() => store.appearance?.sans, defaultSettings.appearance.sans), + uiFont: withFallback(() => store().appearance?.sans, defaultSettings.appearance.sans), setUIFont(value: string) { setStore("appearance", "sans", value.trim() ? value : "") }, - terminalFont: withFallback(() => store.appearance?.terminal, defaultSettings.appearance.terminal), + terminalFont: withFallback(() => store().appearance?.terminal, defaultSettings.appearance.terminal), setTerminalFont(value: string) { setStore("appearance", "terminal", value.trim() ? value : "") }, }, keybinds: { - get: (action: string) => store.keybinds?.[action], + get: (action: string) => store().keybinds?.[action], set(action: string, keybind: string) { setStore("keybinds", action, keybind) }, @@ -295,50 +295,50 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont }, }, permissions: { - autoApprove: withFallback(() => store.permissions?.autoApprove, defaultSettings.permissions.autoApprove), + autoApprove: withFallback(() => store().permissions?.autoApprove, defaultSettings.permissions.autoApprove), setAutoApprove(value: boolean) { setStore("permissions", "autoApprove", value) }, }, notifications: { - agent: withFallback(() => store.notifications?.agent, defaultSettings.notifications.agent), + agent: withFallback(() => store().notifications?.agent, defaultSettings.notifications.agent), setAgent(value: boolean) { setStore("notifications", "agent", value) }, - permissions: withFallback(() => store.notifications?.permissions, defaultSettings.notifications.permissions), + permissions: withFallback(() => store().notifications?.permissions, defaultSettings.notifications.permissions), setPermissions(value: boolean) { setStore("notifications", "permissions", value) }, - errors: withFallback(() => store.notifications?.errors, defaultSettings.notifications.errors), + errors: withFallback(() => store().notifications?.errors, defaultSettings.notifications.errors), setErrors(value: boolean) { setStore("notifications", "errors", value) }, }, sounds: { - agentEnabled: withFallback(() => store.sounds?.agentEnabled, defaultSettings.sounds.agentEnabled), + agentEnabled: withFallback(() => store().sounds?.agentEnabled, defaultSettings.sounds.agentEnabled), setAgentEnabled(value: boolean) { setStore("sounds", "agentEnabled", value) }, - agent: withFallback(() => store.sounds?.agent, defaultSettings.sounds.agent), + agent: withFallback(() => store().sounds?.agent, defaultSettings.sounds.agent), setAgent(value: string) { setStore("sounds", "agent", value) }, permissionsEnabled: withFallback( - () => store.sounds?.permissionsEnabled, + () => store().sounds?.permissionsEnabled, defaultSettings.sounds.permissionsEnabled, ), setPermissionsEnabled(value: boolean) { setStore("sounds", "permissionsEnabled", value) }, - permissions: withFallback(() => store.sounds?.permissions, defaultSettings.sounds.permissions), + permissions: withFallback(() => store().sounds?.permissions, defaultSettings.sounds.permissions), setPermissions(value: string) { setStore("sounds", "permissions", value) }, - errorsEnabled: withFallback(() => store.sounds?.errorsEnabled, defaultSettings.sounds.errorsEnabled), + errorsEnabled: withFallback(() => store().sounds?.errorsEnabled, defaultSettings.sounds.errorsEnabled), setErrorsEnabled(value: boolean) { setStore("sounds", "errorsEnabled", value) }, - errors: withFallback(() => store.sounds?.errors, defaultSettings.sounds.errors), + errors: withFallback(() => store().sounds?.errors, defaultSettings.sounds.errors), setErrors(value: string) { setStore("sounds", "errors", value) }, diff --git a/packages/app/src/context/tabs.tsx b/packages/app/src/context/tabs.tsx index 47ed77e781..e2a7cf84f4 100644 --- a/packages/app/src/context/tabs.tsx +++ b/packages/app/src/context/tabs.tsx @@ -55,7 +55,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ const server = useServer() const platform = usePlatform() const fallback = server.key - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( { ...Persist.window("tabs"), migrate: (value: unknown) => { @@ -68,9 +68,9 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ }, createStore([]), ) - const [recent, setRecent, , recentReady] = persisted(Persist.window("tabs.recent"), createStore({})) + const [recent, setRecent, recentReady] = persisted(Persist.window("tabs.recent"), createStore({})) const [info, setInfo] = persisted(Persist.window("tabs.info"), createStore>({})) - const [closed, setClosed, , closedReady] = persisted(Persist.window("tabs.closed"), createStore([])) + const [closed, setClosed, closedReady] = persisted(Persist.window("tabs.closed"), createStore([])) const params = useParams() const navigate = useNavigate() @@ -81,7 +81,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ let recentWrite = 0 let recentValue: string | undefined - const recentKey = () => (recentWrite ? recentValue : recent.key) + const recentKey = () => (recentWrite ? recentValue : recent().key) const setRecentKey = (key: string | undefined) => { const write = ++recentWrite @@ -109,7 +109,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ } const removeInfo = (key: string) => { - if (!info[key]) return + if (!info()[key]) return setInfo( produce((draft) => { delete draft[key] @@ -122,9 +122,9 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ createEffect(() => { if (!ready() || !recentReady()) return const servers = new Set(server.list.map(ServerConnection.key)) - const next = store.filter((tab) => servers.has(tab.server)) - if (next.length !== store.length) { - for (const tab of store) { + const next = store().filter((tab) => servers.has(tab.server)) + if (next.length !== store().length) { + for (const tab of store()) { if (!servers.has(tab.server)) { const key = tabKey(tab) memory.remove(key) @@ -133,9 +133,9 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ } setStore(() => next) } - if (recent.key && !next.some((tab) => tabKey(tab) === recent.key)) setRecentKey(undefined) + if (recent().key && !next.some((tab) => tabKey(tab) === recent().key)) setRecentKey(undefined) const keys = new Set(next.map(tabKey)) - for (const key of Object.keys(info)) { + for (const key of Object.keys(info())) { if (!keys.has(key)) removeInfo(key) } }) @@ -143,8 +143,8 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ createEffect(() => { if (!closedReady()) return const servers = new Set(server.list.map(ServerConnection.key)) - const next = closed.filter((entry) => servers.has(entry.tab.server)) - if (next.length !== closed.length) setClosed(() => next) + const next = closed().filter((entry) => servers.has(entry.tab.server)) + if (next.length !== closed().length) setClosed(() => next) }) const navigateTab = (tab: Tab) => { @@ -154,11 +154,11 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ } const removeTab = (index: number) => { - const tab = store[index] + const tab = store()[index] if (!tab) return const key = tabKey(tab) const draftID = tab.type === "draft" ? tab.draftID : undefined - const nextTab = nextTabAfterClose(store, index, recentKey() === key && location.pathname !== "/") + const nextTab = nextTabAfterClose(store(), index, recentKey() === key && location.pathname !== "/") closing.add(key) void startTransition(() => { setStore( @@ -180,7 +180,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ const actions = { addSessionTab: (tab: Omit) => { const next = { type: "session" as const, ...tab } - const existing = store.find((item) => tabKey(item) === tabKey(next)) + const existing = store().find((item) => tabKey(item) === tabKey(next)) if (existing) return existing void startTransition(() => { setStore( @@ -203,7 +203,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ ) }, draft(draftID: string) { - const tab = store.find((item) => item.type === "draft" && item.draftID === draftID) + const tab = store().find((item) => item.type === "draft" && item.draftID === draftID) if (!tab || tab.type !== "draft") throw new Error(`Draft not found: ${draftID}`) return tab }, @@ -228,7 +228,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ }, promoteDraft(draftID: string, session: Omit) { // Keep the replacement and navigation atomic so /new-session never renders - // after its backing draft tab has been removed from the store. + // after its backing draft tab has been removed from the store(). const active = location.pathname === "/new-session" && location.query.draftId === draftID const next = { type: "session" as const, ...session } void startTransition(() => { @@ -238,7 +238,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ if (index !== -1) tabs[index] = next }), ) - if (recent.key === `draft:${draftID}`) setRecentKey(tabKey(next)) + if (recent().key === `draft:${draftID}`) setRecentKey(tabKey(next)) if (active) navigateTab(next) }) memory.remove(`draft:${draftID}`) @@ -249,7 +249,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ // Cleanup paths (missing sessions, archive, server removal) go through // removeTab and friends directly and are not recorded. closeTab(index: number) { - const tab = store[index] + const tab = store()[index] if (!tab) return if (tab.type === "session") updateClosed((stack) => pushClosedTab(stack, tab, index)) removeTab(index) @@ -259,12 +259,12 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ void closedReady.promise?.then(() => actions.reopenClosedTab()) return } - const result = takeClosedTab(closed, store) - if (result.stack.length === closed.length) return + const result = takeClosedTab(closed(), store()) + if (result.stack.length === closed().length) return setClosed(() => result.stack) const entry = result.entry if (!entry) return - const index = Math.min(entry.index, store.length) + const index = Math.min(entry.index, store().length) void startTransition(() => { setStore( produce((tabs) => { @@ -277,26 +277,27 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ }, removeSessionTab(input: Omit) { updateClosed((stack) => removeClosedTabs(stack, input.server, [input.sessionId])) - const index = store.findIndex( + const index = store().findIndex( (tab) => tab.type === "session" && tab.server === input.server && tab.sessionId === input.sessionId, ) if (index !== -1) removeTab(index) }, removeServer(key: ServerConnection.Key) { updateClosed((stack) => stack.filter((entry) => entry.tab.server !== key)) - const drafts = store.flatMap((tab) => (tab.type === "draft" && tab.server === key ? [tab.draftID] : [])) - const removed = store.filter((tab) => tab.server === key).map(tabKey) + const drafts = store().flatMap((tab) => (tab.type === "draft" && tab.server === key ? [tab.draftID] : [])) + const removed = store().filter((tab) => tab.server === key).map(tabKey) setStore((tabs) => tabs.filter((tab) => tab.server !== key)) for (const key of removed) memory.remove(key) for (const key of removed) removeInfo(key) - if (recent.key && removed.includes(recent.key)) setRecentKey(undefined) + const recentKey = recent().key + if (recentKey && removed.includes(recentKey)) setRecentKey(undefined) for (const draftID of drafts) removeDraftPersisted(draftID) if (server.key === key) navigate("/") }, removeSessions: (input: SessionTabsRemovedDetail) => { const targetServer = input.server ?? server.key updateClosed((stack) => removeClosedTabs(stack, targetServer, input.sessionIDs)) - const removed = store + const removed = store() .filter( (tab) => tab.type === "session" && tab.server === targetServer && input.sessionIDs.includes(tab.sessionId), ) @@ -340,7 +341,8 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ else navigate("/") }), ) - if (recent.key && removed.includes(recent.key)) setRecentKey(undefined) + const recentKey = recent().key + if (recentKey && removed.includes(recentKey)) setRecentKey(undefined) }) for (const key of removed) memory.remove(key) for (const key of removed) removeInfo(key) @@ -348,7 +350,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ rememberSessionInfo(tab: SessionTab, session: Session) { const key = tabKey(tab) const next = { title: session.title, directory: session.directory } - const current = info[key] + const current = info()[key] if (current?.title === next.title && current.directory === next.directory) return setInfo(key, next) }, @@ -359,7 +361,7 @@ export const { use: useTabs, provider: TabsProvider } = createSimpleContext({ }, toggleHome(input: { home: boolean; current?: Tab }) { if (input.home) { - const tab = store.find((tab) => tabKey(tab) === recentKey()) + const tab = store().find((tab) => tabKey(tab) === recentKey()) if (tab) navigateTab(tab) return } diff --git a/packages/app/src/context/terminal.tsx b/packages/app/src/context/terminal.tsx index a9c66c4833..2cbd2725d0 100644 --- a/packages/app/src/context/terminal.tsx +++ b/packages/app/src/context/terminal.tsx @@ -151,7 +151,7 @@ function createWorkspaceTerminalSession( ) { const legacy = scope === ServerScope.local ? getLegacyTerminalStorageKeys(dir, legacySessionID) : [] - const [store, setStore, _, ready] = persisted( + const [store, setStore, ready] = persisted( { ...terminalPersistTarget(scope, dir, legacy), migrate: migrateTerminalState, @@ -166,7 +166,7 @@ function createWorkspaceTerminalSession( const pickNextTerminalNumber = () => { const existingTitleNumbers = new Set( - store.all.flatMap((pty) => { + store().all.flatMap((pty) => { const direct = Number.isFinite(pty.titleNumber) && pty.titleNumber > 0 ? pty.titleNumber : undefined if (direct !== undefined) return [direct] const parsed = numberFromTitle(pty.title) @@ -183,10 +183,10 @@ function createWorkspaceTerminalSession( } const removeExited = (id: string) => { - const all = store.all + const all = store().all const index = all.findIndex((x) => x.id === id) if (index === -1) return - const active = store.active === id ? (index === 0 ? all[1]?.id : all[0]?.id) : store.active + const active = store().active === id ? (index === 0 ? all[1]?.id : all[0]?.id) : store().active batch(() => { setStore("active", active) setStore( @@ -204,8 +204,8 @@ function createWorkspaceTerminalSession( onCleanup(unsub) const update = (client: DirectorySDK["client"], pty: Partial & { id: string }) => { - const index = store.all.findIndex((x) => x.id === pty.id) - const previous = index >= 0 ? store.all[index] : undefined + const index = store().all.findIndex((x) => x.id === pty.id) + const previous = index >= 0 ? store().all[index] : undefined if (index >= 0) { setStore("all", index, (item) => ({ ...item, ...pty })) } @@ -217,7 +217,7 @@ function createWorkspaceTerminalSession( }) .catch((error: unknown) => { if (previous) { - const currentIndex = store.all.findIndex((item) => item.id === pty.id) + const currentIndex = store().all.findIndex((item) => item.id === pty.id) if (currentIndex >= 0) setStore("all", currentIndex, previous) } console.error("Failed to update terminal", error) @@ -225,8 +225,8 @@ function createWorkspaceTerminalSession( } const clone = async (client: DirectorySDK["client"], id: string) => { - const index = store.all.findIndex((x) => x.id === id) - const pty = store.all[index] + const index = store().all.findIndex((x) => x.id === id) + const pty = store().all[index] if (!pty) return const next = await client.pty .create({ @@ -238,7 +238,7 @@ function createWorkspaceTerminalSession( }) if (!next?.data) return - const active = store.active === pty.id + const active = store().active === pty.id batch(() => { setStore("all", index, { @@ -259,8 +259,8 @@ function createWorkspaceTerminalSession( return { ready, - all: createMemo(() => store.all), - active: createMemo(() => store.active), + all: createMemo(() => store().all), + active: createMemo(() => store().active), clear() { batch(() => { setStore("active", undefined) @@ -280,7 +280,7 @@ function createWorkspaceTerminalSession( title: pty.data?.title ?? defaultTitle(nextNumber), titleNumber: nextNumber, } - setStore("all", store.all.length, newTerminal) + setStore("all", store().all.length, newTerminal) setStore("active", id) }) .catch((error: unknown) => { @@ -291,7 +291,7 @@ function createWorkspaceTerminalSession( update(sdk.client, pty) }, trim(id: string) { - const index = store.all.findIndex((x) => x.id === id) + const index = store().all.findIndex((x) => x.id === id) if (index === -1) return setStore("all", index, (pty) => trimTerminal(pty)) }, @@ -309,7 +309,7 @@ function createWorkspaceTerminalSession( const client = sdk.client return { trim(id: string) { - const index = store.all.findIndex((x) => x.id === id) + const index = store().all.findIndex((x) => x.id === id) if (index === -1) return setStore("all", index, (pty) => trimTerminal(pty)) }, @@ -325,23 +325,23 @@ function createWorkspaceTerminalSession( setStore("active", id) }, next() { - const index = store.all.findIndex((x) => x.id === store.active) + const index = store().all.findIndex((x) => x.id === store().active) if (index === -1) return - const nextIndex = (index + 1) % store.all.length - setStore("active", store.all[nextIndex]?.id) + const nextIndex = (index + 1) % store().all.length + setStore("active", store().all[nextIndex]?.id) }, previous() { - const index = store.all.findIndex((x) => x.id === store.active) + const index = store().all.findIndex((x) => x.id === store().active) if (index === -1) return - const prevIndex = index === 0 ? store.all.length - 1 : index - 1 - setStore("active", store.all[prevIndex]?.id) + const prevIndex = index === 0 ? store().all.length - 1 : index - 1 + setStore("active", store().all[prevIndex]?.id) }, async close(id: string) { - const index = store.all.findIndex((f) => f.id === id) + const index = store().all.findIndex((f) => f.id === id) if (index !== -1) { batch(() => { - if (store.active === id) { - const next = index > 0 ? store.all[index - 1]?.id : store.all[1]?.id + if (store().active === id) { + const next = index > 0 ? store().all[index - 1]?.id : store().all[1]?.id setStore("active", next) } setStore( @@ -358,7 +358,7 @@ function createWorkspaceTerminalSession( }) }, move(id: string, to: number) { - const index = store.all.findIndex((f) => f.id === id) + const index = store().all.findIndex((f) => f.id === id) if (index === -1) return setStore( "all", diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx index 762b8b2c8e..d4ce764b40 100644 --- a/packages/app/src/pages/home.tsx +++ b/packages/app/src/pages/home.tsx @@ -685,14 +685,14 @@ function HomeProjectColumn(props: { const global = useGlobal() const dialog = useDialog() const controller = useServerManagementController({ navigateOnAdd: false }) - const [_state, setState, _, ready] = persisted( + const [_state, setState, ready] = persisted( Persist.global("home.servers", ["home.servers.v1"]), createStore({ collapsed: {} as Record }), ) const [state] = createResource( () => ready.promise ?? Promise.resolve(), - (p) => p.then(() => _state), - { initialValue: _state }, + (p) => p.then(() => _state()), + { initialValue: _state() }, ) return ( @@ -1117,7 +1117,7 @@ function HomeSessionLeading(props: { revealProjectOnHover: boolean }) { const tabs = useTabs() - const hasOpenTab = createMemo(() => sessionHasOpenTab(tabs.store, props.server, props.session)) + const hasOpenTab = createMemo(() => sessionHasOpenTab(tabs.store(), props.server, props.session)) return (
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index fd9d16b90a..805a1bae70 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -85,7 +85,7 @@ import { SidebarContent } from "./layout/sidebar-shell" export default function LegacyLayout(props: ParentProps) { const serverSDK = useServerSDK() - const [store, setStore, , ready] = persisted( + const [store, setStore, ready] = persisted( Persist.serverGlobal(serverSDK().scope, "layout.page", ["layout.page.v1"]), createStore({ lastProjectSession: {} as { [directory: string]: { directory: string; id: string; at: number } }, @@ -556,11 +556,11 @@ export default function LegacyLayout(props: ParentProps) { const workspaceName = (directory: string, projectId?: string, branch?: string) => { const key = pathKey(directory) - const direct = store.workspaceName[key] ?? store.workspaceName[directory] + const direct = store().workspaceName[key] ?? store().workspaceName[directory] if (direct) return direct if (!projectId) return if (!branch) return - return store.workspaceBranchName[projectId]?.[branch] + return store().workspaceBranchName[projectId]?.[branch] } const setWorkspaceName = (directory: string, next: string, projectId?: string, branch?: string) => { @@ -568,7 +568,7 @@ export default function LegacyLayout(props: ParentProps) { setStore("workspaceName", key, next) if (!projectId) return if (!branch) return - if (!store.workspaceBranchName[projectId]) { + if (!store().workspaceBranchName[projectId]) { setStore("workspaceBranchName", projectId, {}) } setStore("workspaceBranchName", projectId, branch, next) @@ -591,7 +591,7 @@ export default function LegacyLayout(props: ParentProps) { const activeDir = currentDir() return workspaceIds(project).filter((directory) => { - const expanded = store.workspaceExpanded[directory] ?? directory === project.worktree + const expanded = store().workspaceExpanded[directory] ?? directory === project.worktree const active = pathKey(directory) === pathKey(activeDir) return expanded || active }) @@ -601,7 +601,7 @@ export default function LegacyLayout(props: ParentProps) { if (!pageReady()) return if (!layoutReady()) return const projects = layout.projects.list() - for (const [directory, expanded] of Object.entries(store.workspaceExpanded)) { + for (const [directory, expanded] of Object.entries(store().workspaceExpanded)) { if (!expanded) continue const key = pathKey(directory) const project = projects.find( @@ -1127,7 +1127,7 @@ export default function LegacyLayout(props: ParentProps) { .find((item) => pathKey(item.worktree) === key || item.sandboxes?.some((sandbox) => pathKey(sandbox) === key)) if (project) return project.worktree - const known = Object.entries(store.workspaceOrder).find( + const known = Object.entries(store().workspaceOrder).find( ([root, dirs]) => pathKey(root) === key || dirs.some((item) => pathKey(item) === key), ) if (known) return known[0] @@ -1150,7 +1150,7 @@ export default function LegacyLayout(props: ParentProps) { } function clearLastProjectSession(root: string) { - if (!store.lastProjectSession[root]) return + if (!store().lastProjectSession[root]) return setStore( "lastProjectSession", produce((draft) => { @@ -1162,7 +1162,7 @@ export default function LegacyLayout(props: ParentProps) { function syncSessionRoute(directory: string, id: string, root = activeProjectRoot(directory)) { rememberSessionRoute(directory, id, root) notification.session.markViewed(id) - const expanded = untrack(() => store.workspaceExpanded[directory]) + const expanded = untrack(() => store().workspaceExpanded[directory]) if (expanded === false) { setStore("workspaceExpanded", directory, true) } @@ -1176,7 +1176,7 @@ export default function LegacyLayout(props: ParentProps) { server.projects.touch(root) const project = layout.projects.list().find((item) => item.worktree === root) let dirs = project - ? effectiveWorkspaceOrder(root, [root, ...(project.sandboxes ?? [])], store.workspaceOrder[root]) + ? effectiveWorkspaceOrder(root, [root, ...(project.sandboxes ?? [])], store().workspaceOrder[root]) : [root] const canOpen = (value: string | undefined) => { if (!value) return false @@ -1188,7 +1188,7 @@ export default function LegacyLayout(props: ParentProps) { .client.worktree.list({ directory: root }) .then((x) => x.data ?? []) .catch(() => [] as string[]) - dirs = effectiveWorkspaceOrder(root, [root, ...listed], store.workspaceOrder[root]) + dirs = effectiveWorkspaceOrder(root, [root, ...listed], store().workspaceOrder[root]) return canOpen(target) } const openSession = async (target: { directory: string; id: string }) => { @@ -1210,7 +1210,7 @@ export default function LegacyLayout(props: ParentProps) { return true } - const projectSession = store.lastProjectSession[root] + const projectSession = store().lastProjectSession[root] if (projectSession?.id) { await refreshDirs(projectSession.directory) const opened = await openSession(projectSession) @@ -1401,7 +1401,7 @@ export default function LegacyLayout(props: ParentProps) { if (!result) return - if (pathKey(store.lastProjectSession[root]?.directory ?? "") === pathKey(directory)) { + if (pathKey(store().lastProjectSession[root]?.directory ?? "") === pathKey(directory)) { clearLastProjectSession(root) } @@ -1424,7 +1424,7 @@ export default function LegacyLayout(props: ParentProps) { const nextKey = pathKey(nextCurrent) const project = layout.projects.list().find((item) => item.worktree === root) const dirs = project - ? effectiveWorkspaceOrder(root, [root, ...(project.sandboxes ?? [])], store.workspaceOrder[root]) + ? effectiveWorkspaceOrder(root, [root, ...(project.sandboxes ?? [])], store().workspaceOrder[root]) : [root] const valid = dirs.some((item) => pathKey(item) === nextKey) @@ -1771,7 +1771,7 @@ export default function LegacyLayout(props: ParentProps) { : undefined const pending = extra ? WorktreeState.get(serverSDK().scope, extra)?.status === "pending" : false - const ordered = effectiveWorkspaceOrder(local, dirs, store.workspaceOrder[project.worktree]) + const ordered = effectiveWorkspaceOrder(local, dirs, store().workspaceOrder[project.worktree]) if (pending && extra) return [local, extra, ...ordered.filter((item) => item !== local)] if (!extra) return ordered if (pending) return ordered @@ -1875,7 +1875,7 @@ export default function LegacyLayout(props: ParentProps) { setEditor, InlineEditor, isBusy, - workspaceExpanded: (directory, local) => store.workspaceExpanded[directory] ?? local, + workspaceExpanded: (directory, local) => store().workspaceExpanded[directory] ?? local, setWorkspaceExpanded: (directory, value) => setStore("workspaceExpanded", directory, value), showResetWorkspaceDialog: (root, directory) => dialog.show(() => ), @@ -2171,7 +2171,7 @@ export default function LegacyLayout(props: ParentProps) { store.activeWorkspace} + activeWorkspace={() => store().activeWorkspace} workspaceLabel={workspaceLabel} /> @@ -2187,7 +2187,7 @@ export default function LegacyLayout(props: ParentProps) {
0 && providers.paid().length === 0), + hidden: store().gettingStartedDismissed || !(providers.all().size > 0 && providers.paid().length === 0), }} >
@@ -2217,7 +2217,7 @@ export default function LegacyLayout(props: ParentProps) { } const projects = () => layout.projects.list() - const projectOverlay = () => store.activeProject} /> + const projectOverlay = () => store().activeProject} /> const sidebarContent = (mobile?: boolean) => ( failed: Record @@ -1614,19 +1614,19 @@ export default function Page() { const queuedFollowups = createMemo(() => { const id = params.id if (!id) return emptyFollowups - return followup.items[id] ?? emptyFollowups + return followup().items[id] ?? emptyFollowups }) const editingFollowup = createMemo(() => { const id = params.id if (!id) return - return followup.edit[id] + return followup().edit[id] }) const followupMutation = useMutation(() => ({ mutationFn: async (input: { sessionID: string; id: string; manual?: boolean }) => { const owner = sessionOwnership.capture() - const item = (followup.items[input.sessionID] ?? []).find((entry) => entry.id === input.id) + const item = (followup().items[input.sessionID] ?? []).find((entry) => entry.id === input.id) if (!item) return if (input.manual) setFollowup("paused", input.sessionID, undefined) @@ -1696,7 +1696,7 @@ export default function Page() { const sendFollowup = (sessionID: string, id: string, opts?: { manual?: boolean }) => { if (sync().session.get(sessionID)?.parentID) return Promise.resolve() - const item = (followup.items[sessionID] ?? []).find((entry) => entry.id === id) + const item = (followup().items[sessionID] ?? []).find((entry) => entry.id === id) if (!item) return Promise.resolve() if (followupBusy(sessionID)) return Promise.resolve() @@ -1818,8 +1818,8 @@ export default function Page() { const item = queuedFollowups()[0] if (!item) return if (followupBusy(sessionID)) return - if (followup.failed[sessionID] === item.id) return - if (followup.paused[sessionID]) return + if (followup().failed[sessionID] === item.id) return + if (followup().paused[sessionID]) return if (isChildSession()) return if (composer.blocked()) return if (busy(sessionID)) return diff --git a/packages/app/src/pages/session/usage-exceeded-dialogs.tsx b/packages/app/src/pages/session/usage-exceeded-dialogs.tsx index d56fa3d1f4..cafad10538 100644 --- a/packages/app/src/pages/session/usage-exceeded-dialogs.tsx +++ b/packages/app/src/pages/session/usage-exceeded-dialogs.tsx @@ -61,9 +61,9 @@ export function useUsageExceededDialogs() { const keys = goUpsellKeys(evt.properties.status) if (!keys) return - const seen = goUpsellState[keys.lastSeenAt] + const seen = goUpsellState()[keys.lastSeenAt] if (seen && Date.now() - seen < GO_UPSELL_WINDOW) return - if (goUpsellState[keys.dontShow]) return + if (goUpsellState()[keys.dontShow]) return if (action.reason === "free_tier_limit") { dialog.show(() => ( diff --git a/packages/app/src/pages/session/v2/review-panel-v2-state.ts b/packages/app/src/pages/session/v2/review-panel-v2-state.ts index d5894bfb69..ebd559d5d0 100644 --- a/packages/app/src/pages/session/v2/review-panel-v2-state.ts +++ b/packages/app/src/pages/session/v2/review-panel-v2-state.ts @@ -22,11 +22,11 @@ export function createReviewPanelV2State() { const [filter, setFilter] = createSignal("") return { - sidebarOpened: () => store.sidebarOpened, - sidebarWidth: () => store.sidebarWidth, + sidebarOpened: () => store().sidebarOpened, + sidebarWidth: () => store().sidebarWidth, filter, setFilter, - expandMode: () => store.expandMode, + expandMode: () => store().expandMode, setExpandMode: (mode: SessionReviewExpandMode) => setStore("expandMode", mode), resizeSidebar: (width: number) => setStore( diff --git a/packages/app/src/utils/persist.ts b/packages/app/src/utils/persist.ts index 671b798f61..66535d3674 100644 --- a/packages/app/src/utils/persist.ts +++ b/packages/app/src/utils/persist.ts @@ -6,11 +6,9 @@ import type { SetStoreFunction, Store } from "solid-js/store" import { pathKey } from "@/utils/path-key" import { ScopedKey, ServerScope, type ServerScope as ServerScopeValue } from "@/utils/server-scope" -type InitType = Promise | string | null type PersistedWithReady = [ - Store, + Accessor, SetStoreFunction, - InitType, Accessor & { promise: undefined | Promise }, ] @@ -641,20 +639,20 @@ export function persisted( const [state, setState, init] = makePersisted(store, { name: config.key, storage }) const isAsync = init instanceof Promise - const [ready] = createResource( + + const [storeResource] = createResource( () => init, - async (initValue) => { - if (initValue instanceof Promise) await initValue - return true + async () => { + if (init instanceof Promise) await init + return state }, - { initialValue: !isAsync }, + { initialValue: state }, ) return [ - state, + () => storeResource() as T, setState, - init, - Object.assign(() => (ready.loading ? false : ready.latest === true), { + Object.assign(() => !isAsync || !storeResource.loading, { promise: init instanceof Promise ? init : undefined, }), ]