mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-28 22:21:25 -04:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ea2db98dbe | |||
| 6910eee7fb |
@@ -72,7 +72,7 @@ const SessionRoute = () => {
|
||||
return (
|
||||
<Show when={tabs.ready()}>
|
||||
{(_) => {
|
||||
const persisted = tabs.store.filter((item) => item.type === "session")
|
||||
const persisted = tabs.store().filter((item) => item.type === "session")
|
||||
return <Navigate href={sessionHref(legacySessionServer(persisted, sessionID, server.key), sessionID)} />
|
||||
}}
|
||||
</Show>
|
||||
@@ -140,7 +140,7 @@ function DraftRoute() {
|
||||
return (
|
||||
<Show when={tabs.ready()}>
|
||||
<Show
|
||||
when={tabs.store.find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === search.draftId)}
|
||||
when={tabs.store().find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === search.draftId)}
|
||||
keyed
|
||||
fallback={<Navigate href="/" />}
|
||||
>
|
||||
@@ -568,7 +568,7 @@ function LegacyTargetSessionRoute() {
|
||||
<Navigate
|
||||
href={sessionHref(
|
||||
legacySessionServer(
|
||||
tabs.store.filter((item) => item.type === "session"),
|
||||
tabs.store().filter((item) => item.type === "session"),
|
||||
params.id,
|
||||
server.key,
|
||||
),
|
||||
|
||||
@@ -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<PromptHistoryState>({ entries: [] })
|
||||
const [shell, setShell] = createStore<PromptHistoryState>({ entries: [] })
|
||||
return createPromptInputHistoryStore(normal, setNormal, shell, setShell)
|
||||
return createPromptInputHistoryStore(() => normal, setNormal, () => shell, setShell)
|
||||
}
|
||||
|
||||
type PromptHistoryState = { entries: PromptHistoryStoredEntry[] }
|
||||
|
||||
function createPromptInputHistoryStore(
|
||||
normal: Store<PromptHistoryState>,
|
||||
normal: Accessor<PromptHistoryState>,
|
||||
setNormal: SetStoreFunction<PromptHistoryState>,
|
||||
shell: Store<PromptHistoryState>,
|
||||
shell: Accessor<PromptHistoryState>,
|
||||
setShell: SetStoreFunction<PromptHistoryState>,
|
||||
): 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
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 }) {
|
||||
</TooltipV2>
|
||||
|
||||
<TitlebarTabStrip
|
||||
tabs={tabsStore}
|
||||
tabs={tabsStore()}
|
||||
currentTab={currentTab}
|
||||
forceTruncate={tabsAreOverflowing()}
|
||||
onOverflowChange={setTabsAreOverflowing}
|
||||
@@ -491,7 +491,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
|
||||
el?.scrollIntoView({ behavior: "instant" })
|
||||
}}
|
||||
onClose={(tab) => {
|
||||
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)}
|
||||
|
||||
@@ -253,8 +253,8 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex
|
||||
const warnedDuplicates = new Set<string>()
|
||||
|
||||
type CommandCatalog = Record<string, CommandCatalogItem>
|
||||
const [catalog, setCatalog, _, catalogReady] = persisted(
|
||||
Persist.global("command.catalog.v1"),
|
||||
const [catalog, setCatalog, catalogReady] = persisted(
|
||||
Persist.global("command.catalog().v1"),
|
||||
createStore<CommandCatalog>({}),
|
||||
)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -181,13 +181,13 @@ export function createCommentSessionForTest(comments: Record<string, LineComment
|
||||
function createCommentSession(scope: ServerScope, dir: string, id: string | undefined) {
|
||||
const legacy = `${dir}/comments${id ? "/" + id : ""}.v1`
|
||||
|
||||
const [store, setStore, _, ready] = persisted(
|
||||
const [store, setStore, ready] = persisted(
|
||||
Persist.serverScoped(scope, dir, id, "comments", [legacy]),
|
||||
createStore<CommentStore>({
|
||||
comments: {},
|
||||
}),
|
||||
)
|
||||
const session = createCommentSessionState(store, setStore)
|
||||
const session = createCommentSessionState(store(), setStore)
|
||||
|
||||
return {
|
||||
ready,
|
||||
|
||||
@@ -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<string, FileViewState>
|
||||
@@ -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(
|
||||
|
||||
@@ -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 }),
|
||||
]
|
||||
|
||||
|
||||
@@ -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> | string | null, run: () => void) => {
|
||||
if (!(init instanceof Promise)) return
|
||||
void init.then(() => {
|
||||
const onPersistedInit = (ready: Accessor<boolean> & { promise: undefined | Promise<any> }, 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)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -549,7 +549,7 @@ describe("applyDirectoryEvent", () => {
|
||||
directory: "/tmp",
|
||||
loadLsp() {},
|
||||
vcsCache: {
|
||||
store: cacheStore,
|
||||
store: () => cacheStore,
|
||||
setStore: setCacheStore,
|
||||
ready: () => true,
|
||||
},
|
||||
|
||||
@@ -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<boolean>
|
||||
}
|
||||
|
||||
export type MetaCache = {
|
||||
store: Store<{ value: ProjectMeta | undefined }>
|
||||
store: Accessor<{ value: ProjectMeta | undefined }>
|
||||
setStore: SetStoreFunction<{ value: ProjectMeta | undefined }>
|
||||
ready: Accessor<boolean>
|
||||
}
|
||||
|
||||
export type IconCache = {
|
||||
store: Store<{ value: string | undefined }>
|
||||
store: Accessor<{ value: string | undefined }>
|
||||
setStore: SetStoreFunction<{ value: string | undefined }>
|
||||
ready: Accessor<boolean>
|
||||
}
|
||||
|
||||
@@ -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<Store>({ version: undefined }))
|
||||
const [store, setStore, ready] = persisted("highlights.v1", createStore<Store>({ 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,
|
||||
}
|
||||
|
||||
@@ -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<Locale>(() => normalizeLocale(store.locale))
|
||||
const locale = createMemo<Locale>(() => normalizeLocale(store().locale))
|
||||
const intl = createMemo(() => INTL[locale()])
|
||||
|
||||
const [dict] = createResource(locale, loadDict, {
|
||||
|
||||
@@ -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<string>) {
|
||||
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<string>) {
|
||||
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
|
||||
|
||||
@@ -125,7 +125,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||
const scope = createMemo<State | undefined>(() => {
|
||||
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, {
|
||||
|
||||
@@ -28,7 +28,7 @@ export const { use: useModels, provider: ModelsProvider } = createSimpleContext(
|
||||
init: (props: { directory?: Accessor<string | undefined> } = {}) => {
|
||||
const providers = useProviders(props.directory)
|
||||
|
||||
const [store, setStore, _, ready] = persisted(
|
||||
const [store, setStore, ready] = persisted(
|
||||
Persist.global("model", ["model.v1"]),
|
||||
createStore<Store>({
|
||||
user: [],
|
||||
@@ -89,7 +89,7 @@ export const { use: useModels, provider: ModelsProvider } = createSimpleContext(
|
||||
|
||||
const visibility = createMemo(() => {
|
||||
const map = new Map<string, Visibility>()
|
||||
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
|
||||
},
|
||||
|
||||
@@ -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<NotificationIndex>(buildNotificationIndex(store.list))
|
||||
const [index, setIndex] = createStore<NotificationIndex>(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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>(promptStore()),
|
||||
)
|
||||
|
||||
return { ready, ...createPromptStateValue(store, setStore) }
|
||||
return { ready, ...createPromptStateValue(store(), setStore) }
|
||||
}
|
||||
|
||||
export function createPromptReady(session: Accessor<PromptSession>) {
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
|
||||
canonicalLocalServer?: ServerConnection.Key
|
||||
servers?: Array<ServerConnection.Any>
|
||||
}) => {
|
||||
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<ServerConnection.Any> => {
|
||||
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<ServerConnection.Key, ReturnType<typeof createServerProjects>>()
|
||||
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
|
||||
}
|
||||
|
||||
@@ -152,45 +152,45 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont
|
||||
name: "Settings",
|
||||
gate: false,
|
||||
init: () => {
|
||||
const [store, setStore, _, ready] = persisted("settings.v3", createStore<Settings>(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<Settings>(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)
|
||||
},
|
||||
|
||||
@@ -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<Tab[]>([]),
|
||||
)
|
||||
const [recent, setRecent, , recentReady] = persisted(Persist.window("tabs.recent"), createStore<RecentTab>({}))
|
||||
const [recent, setRecent, recentReady] = persisted(Persist.window("tabs.recent"), createStore<RecentTab>({}))
|
||||
const [info, setInfo] = persisted(Persist.window("tabs.info"), createStore<Record<string, TabInfo>>({}))
|
||||
const [closed, setClosed, , closedReady] = persisted(Persist.window("tabs.closed"), createStore<ClosedTab[]>([]))
|
||||
const [closed, setClosed, closedReady] = persisted(Persist.window("tabs.closed"), createStore<ClosedTab[]>([]))
|
||||
|
||||
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<SessionTab, "type">) => {
|
||||
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<SessionTab, "type">) {
|
||||
// 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<SessionTab, "type">) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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<LocalPTY> & { 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",
|
||||
|
||||
@@ -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<string, boolean> }),
|
||||
)
|
||||
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 (
|
||||
<div class="relative shrink-0">
|
||||
<Show when={hasOpenTab()}>
|
||||
|
||||
@@ -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(() => <DialogResetWorkspace root={root} directory={directory} />),
|
||||
@@ -2171,7 +2171,7 @@ export default function LegacyLayout(props: ParentProps) {
|
||||
<DragOverlay>
|
||||
<WorkspaceDragOverlay
|
||||
sidebarProject={sidebarProject}
|
||||
activeWorkspace={() => store.activeWorkspace}
|
||||
activeWorkspace={() => store().activeWorkspace}
|
||||
workspaceLabel={workspaceLabel}
|
||||
/>
|
||||
</DragOverlay>
|
||||
@@ -2187,7 +2187,7 @@ export default function LegacyLayout(props: ParentProps) {
|
||||
<div
|
||||
class="shrink-0 px-3 py-3"
|
||||
classList={{
|
||||
hidden: store.gettingStartedDismissed || !(providers.all().size > 0 && providers.paid().length === 0),
|
||||
hidden: store().gettingStartedDismissed || !(providers.all().size > 0 && providers.paid().length === 0),
|
||||
}}
|
||||
>
|
||||
<div class="rounded-xl bg-background-base shadow-xs-border-base" data-component="getting-started">
|
||||
@@ -2217,7 +2217,7 @@ export default function LegacyLayout(props: ParentProps) {
|
||||
}
|
||||
|
||||
const projects = () => layout.projects.list()
|
||||
const projectOverlay = () => <ProjectDragOverlay projects={projects} activeProject={() => store.activeProject} />
|
||||
const projectOverlay = () => <ProjectDragOverlay projects={projects} activeProject={() => store().activeProject} />
|
||||
const sidebarContent = (mobile?: boolean) => (
|
||||
<SidebarContent
|
||||
mobile={mobile}
|
||||
|
||||
@@ -545,7 +545,7 @@ export default function Page() {
|
||||
})
|
||||
|
||||
const [followup, setFollowup] = persisted(
|
||||
Persist.serverWorkspace(serverSDK().scope, sdk().directory, "followup", ["followup.v1"]),
|
||||
Persist.serverWorkspace(serverSDK().scope, sdk().directory, "followup", ["followup().v1"]),
|
||||
createStore<{
|
||||
items: Record<string, FollowupItem[] | undefined>
|
||||
failed: Record<string, string | undefined>
|
||||
@@ -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
|
||||
|
||||
@@ -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(() => (
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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> | string | null
|
||||
type PersistedWithReady<T> = [
|
||||
Store<T>,
|
||||
Accessor<T>,
|
||||
SetStoreFunction<T>,
|
||||
InitType,
|
||||
Accessor<boolean> & { promise: undefined | Promise<any> },
|
||||
]
|
||||
|
||||
@@ -641,20 +639,20 @@ export function persisted<T>(
|
||||
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,
|
||||
}),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user