diff --git a/packages/app/src/components/dialog-select-file.tsx b/packages/app/src/components/dialog-select-file.tsx index 7c3113a54..1bb95c68a 100644 --- a/packages/app/src/components/dialog-select-file.tsx +++ b/packages/app/src/components/dialog-select-file.tsx @@ -32,8 +32,8 @@ export function DialogSelectFile() { const dialog = useDialog() const params = useParams() const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) - const tabs = createMemo(() => layout.tabs(sessionKey())) - const view = createMemo(() => layout.view(sessionKey())) + const tabs = createMemo(() => layout.tabs(sessionKey)) + const view = createMemo(() => layout.view(sessionKey)) const state = { cleanup: undefined as (() => void) | void, committed: false } const [grouped, setGrouped] = createSignal(false) const common = [ diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index a5d0569ed..e4a5a5150 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -167,8 +167,8 @@ export const PromptInput: Component = (props) => { } const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) - const tabs = createMemo(() => layout.tabs(sessionKey())) - const view = createMemo(() => layout.view(sessionKey())) + const tabs = createMemo(() => layout.tabs(sessionKey)) + const view = createMemo(() => layout.view(sessionKey)) const recent = createMemo(() => { const all = tabs().all() diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index ee93b3f03..64133af72 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -21,8 +21,8 @@ export function SessionContextUsage(props: SessionContextUsageProps) { const variant = createMemo(() => props.variant ?? "button") const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) - const tabs = createMemo(() => layout.tabs(sessionKey())) - const view = createMemo(() => layout.view(sessionKey())) + const tabs = createMemo(() => layout.tabs(sessionKey)) + const view = createMemo(() => layout.view(sessionKey)) const messages = createMemo(() => (params.id ? (sync.data.message[params.id] ?? []) : [])) const cost = createMemo(() => { diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index a76734a69..1e06e8ed6 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -50,7 +50,7 @@ export function SessionHeader() { const showShare = createMemo(() => shareEnabled() && !!currentSession()) const showReview = createMemo(() => !!currentSession()) const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) - const view = createMemo(() => layout.view(sessionKey())) + const view = createMemo(() => layout.view(sessionKey)) const [state, setState] = createStore({ share: false, diff --git a/packages/app/src/context/file.tsx b/packages/app/src/context/file.tsx index 5ea499387..20fc980f6 100644 --- a/packages/app/src/context/file.tsx +++ b/packages/app/src/context/file.tsx @@ -189,6 +189,8 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ const params = useParams() const language = useLanguage() + const scope = createMemo(() => sdk.directory) + const directory = createMemo(() => sync.data.path.directory) function normalize(input: string) { @@ -234,6 +236,12 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ file: {}, }) + createEffect(() => { + scope() + inflight.clear() + setStore("file", {}) + }) + const viewCache = new Map() const disposeViews = () => { @@ -284,12 +292,16 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ const path = normalize(input) if (!path) return Promise.resolve() + const directory = scope() + const key = `${directory}\n${path}` + const client = sdk.client + ensure(path) const current = store.file[path] if (!options?.force && current?.loaded) return Promise.resolve() - const pending = inflight.get(path) + const pending = inflight.get(key) if (pending) return pending setStore( @@ -301,9 +313,10 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ }), ) - const promise = sdk.client.file + const promise = client.file .read({ path }) .then((x) => { + if (scope() !== directory) return setStore( "file", path, @@ -315,6 +328,7 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ ) }) .catch((e) => { + if (scope() !== directory) return setStore( "file", path, @@ -330,10 +344,10 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ }) }) .finally(() => { - inflight.delete(path) + inflight.delete(key) }) - inflight.set(path, promise) + inflight.set(key, promise) return promise } diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx index 444a36d65..ddd66aa2f 100644 --- a/packages/app/src/context/layout.tsx +++ b/packages/app/src/context/layout.tsx @@ -1,5 +1,5 @@ import { createStore, produce } from "solid-js/store" -import { batch, createEffect, createMemo, onCleanup, onMount } from "solid-js" +import { batch, createEffect, createMemo, on, onCleanup, onMount, type Accessor } from "solid-js" import { createSimpleContext } from "@opencode-ai/ui/context" import { useGlobalSync } from "./global-sync" import { useGlobalSDK } from "./global-sdk" @@ -432,10 +432,24 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setStore("mobileSidebar", "opened", (x) => !x) }, }, - view(sessionKey: string) { - touch(sessionKey) - scroll.seed(sessionKey) - const s = createMemo(() => store.sessionView[sessionKey] ?? { scroll: {} }) + view(sessionKey: string | Accessor) { + const key = typeof sessionKey === "function" ? sessionKey : () => sessionKey + + touch(key()) + scroll.seed(key()) + + createEffect( + on( + key, + (value) => { + touch(value) + scroll.seed(value) + }, + { defer: true }, + ), + ) + + const s = createMemo(() => store.sessionView[key()] ?? { scroll: {} }) const terminalOpened = createMemo(() => store.terminal?.opened ?? false) const reviewPanelOpened = createMemo(() => store.review?.panelOpened ?? true) @@ -465,10 +479,10 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( return { scroll(tab: string) { - return scroll.scroll(sessionKey, tab) + return scroll.scroll(key(), tab) }, setScroll(tab: string, pos: SessionScroll) { - scroll.setScroll(sessionKey, tab, pos) + scroll.setScroll(key(), tab, pos) }, terminal: { opened: terminalOpened, @@ -497,9 +511,10 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( review: { open: createMemo(() => s().reviewOpen), setOpen(open: string[]) { - const current = store.sessionView[sessionKey] + const session = key() + const current = store.sessionView[session] if (!current) { - setStore("sessionView", sessionKey, { + setStore("sessionView", session, { scroll: {}, reviewOpen: open, }) @@ -507,93 +522,111 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( } if (same(current.reviewOpen, open)) return - setStore("sessionView", sessionKey, "reviewOpen", open) + setStore("sessionView", session, "reviewOpen", open) }, }, } }, - tabs(sessionKey: string) { - touch(sessionKey) - const tabs = createMemo(() => store.sessionTabs[sessionKey] ?? { all: [] }) + tabs(sessionKey: string | Accessor) { + const key = typeof sessionKey === "function" ? sessionKey : () => sessionKey + + touch(key()) + + createEffect( + on( + key, + (value) => { + touch(value) + }, + { defer: true }, + ), + ) + + const tabs = createMemo(() => store.sessionTabs[key()] ?? { all: [] }) return { tabs, active: createMemo(() => tabs().active), all: createMemo(() => tabs().all), setActive(tab: string | undefined) { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: [], active: tab }) + const session = key() + if (!store.sessionTabs[session]) { + setStore("sessionTabs", session, { all: [], active: tab }) } else { - setStore("sessionTabs", sessionKey, "active", tab) + setStore("sessionTabs", session, "active", tab) } }, setAll(all: string[]) { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all, active: undefined }) + const session = key() + if (!store.sessionTabs[session]) { + setStore("sessionTabs", session, { all, active: undefined }) } else { - setStore("sessionTabs", sessionKey, "all", all) + setStore("sessionTabs", session, "all", all) } }, async open(tab: string) { - const current = store.sessionTabs[sessionKey] ?? { all: [] } + const session = key() + const current = store.sessionTabs[session] ?? { all: [] } if (tab === "review") { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: [], active: tab }) + if (!store.sessionTabs[session]) { + setStore("sessionTabs", session, { all: [], active: tab }) return } - setStore("sessionTabs", sessionKey, "active", tab) + setStore("sessionTabs", session, "active", tab) return } if (tab === "context") { const all = [tab, ...current.all.filter((x) => x !== tab)] - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all, active: tab }) + if (!store.sessionTabs[session]) { + setStore("sessionTabs", session, { all, active: tab }) return } - setStore("sessionTabs", sessionKey, "all", all) - setStore("sessionTabs", sessionKey, "active", tab) + setStore("sessionTabs", session, "all", all) + setStore("sessionTabs", session, "active", tab) return } if (!current.all.includes(tab)) { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: [tab], active: tab }) + if (!store.sessionTabs[session]) { + setStore("sessionTabs", session, { all: [tab], active: tab }) return } - setStore("sessionTabs", sessionKey, "all", [...current.all, tab]) - setStore("sessionTabs", sessionKey, "active", tab) + setStore("sessionTabs", session, "all", [...current.all, tab]) + setStore("sessionTabs", session, "active", tab) return } - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: current.all, active: tab }) + if (!store.sessionTabs[session]) { + setStore("sessionTabs", session, { all: current.all, active: tab }) return } - setStore("sessionTabs", sessionKey, "active", tab) + setStore("sessionTabs", session, "active", tab) }, close(tab: string) { - const current = store.sessionTabs[sessionKey] + const session = key() + const current = store.sessionTabs[session] if (!current) return const all = current.all.filter((x) => x !== tab) batch(() => { - setStore("sessionTabs", sessionKey, "all", all) + setStore("sessionTabs", session, "all", all) if (current.active !== tab) return const index = current.all.findIndex((f) => f === tab) const next = all[index - 1] ?? all[0] - setStore("sessionTabs", sessionKey, "active", next) + setStore("sessionTabs", session, "active", next) }) }, move(tab: string, to: number) { - const current = store.sessionTabs[sessionKey] + const session = key() + const current = store.sessionTabs[session] if (!current) return const index = current.all.findIndex((f) => f === tab) if (index === -1) return setStore( "sessionTabs", - sessionKey, + session, "all", produce((opened) => { opened.splice(to, 0, opened.splice(index, 1)[0]) diff --git a/packages/app/src/context/local.tsx b/packages/app/src/context/local.tsx index 64bfa838d..4a585e06b 100644 --- a/packages/app/src/context/local.tsx +++ b/packages/app/src/context/local.tsx @@ -1,5 +1,5 @@ import { createStore, produce, reconcile } from "solid-js/store" -import { batch, createMemo, onCleanup } from "solid-js" +import { batch, createEffect, createMemo, onCleanup } from "solid-js" import { filter, firstBy, flat, groupBy, mapValues, pipe, uniqueBy, values } from "remeda" import type { FileContent, FileNode, Model, Provider, File as FileStatus } from "@opencode-ai/sdk/v2" import { createSimpleContext } from "@opencode-ai/ui/context" @@ -338,6 +338,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ node: {}, // Object.fromEntries(sync.data.node.map((x) => [x.path, x])), }) + const scope = createMemo(() => sdk.directory) + createEffect(() => { + scope() + setStore("node", {}) + }) + // const changeset = createMemo(() => new Set(sync.data.changes.map((f) => f.path))) // const changes = createMemo(() => Array.from(changeset()).sort((a, b) => a.localeCompare(b))) @@ -394,10 +400,13 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const relative = (path: string) => path.replace(sync.data.path.directory + "/", "") const load = async (path: string) => { + const directory = scope() + const client = sdk.client const relativePath = relative(path) - await sdk.client.file + await client.file .read({ path: relativePath }) .then((x) => { + if (scope() !== directory) return if (!store.node[relativePath]) return setStore( "node", @@ -409,6 +418,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ ) }) .catch((e) => { + if (scope() !== directory) return showToast({ variant: "error", title: language.t("toast.file.loadFailed.title"), @@ -453,9 +463,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ } const list = async (path: string) => { - return sdk.client.file + const directory = scope() + const client = sdk.client + return client.file .list({ path: path + "/" }) .then((x) => { + if (scope() !== directory) return setStore( "node", produce((draft) => { diff --git a/packages/app/src/context/sdk.tsx b/packages/app/src/context/sdk.tsx index aa4820c49..123aa4e73 100644 --- a/packages/app/src/context/sdk.tsx +++ b/packages/app/src/context/sdk.tsx @@ -1,7 +1,7 @@ import { createOpencodeClient, type Event } from "@opencode-ai/sdk/v2/client" import { createSimpleContext } from "@opencode-ai/ui/context" import { createGlobalEmitter } from "@solid-primitives/event-bus" -import { onCleanup } from "solid-js" +import { createEffect, createMemo, onCleanup } from "solid-js" import { useGlobalSDK } from "./global-sdk" import { usePlatform } from "./platform" @@ -10,22 +10,39 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ init: (props: { directory: string }) => { const platform = usePlatform() const globalSDK = useGlobalSDK() - const sdk = createOpencodeClient({ - baseUrl: globalSDK.url, - fetch: platform.fetch, - directory: props.directory, - throwOnError: true, - }) + + const directory = createMemo(() => props.directory) + const client = createMemo(() => + createOpencodeClient({ + baseUrl: globalSDK.url, + fetch: platform.fetch, + directory: directory(), + throwOnError: true, + }), + ) const emitter = createGlobalEmitter<{ [key in Event["type"]]: Extract }>() - const unsub = globalSDK.event.on(props.directory, (event) => { - emitter.emit(event.type, event) + createEffect(() => { + const unsub = globalSDK.event.on(directory(), (event) => { + emitter.emit(event.type, event) + }) + onCleanup(unsub) }) - onCleanup(unsub) - return { directory: props.directory, client: sdk, event: emitter, url: globalSDK.url } + return { + get directory() { + return directory() + }, + get client() { + return client() + }, + event: emitter, + get url() { + return globalSDK.url + }, + } }, }) diff --git a/packages/app/src/context/sync.tsx b/packages/app/src/context/sync.tsx index 33129e1b4..96872584e 100644 --- a/packages/app/src/context/sync.tsx +++ b/packages/app/src/context/sync.tsx @@ -7,13 +7,20 @@ import { useGlobalSync } from "./global-sync" import { useSDK } from "./sdk" import type { Message, Part } from "@opencode-ai/sdk/v2/client" +const keyFor = (directory: string, id: string) => `${directory}\n${id}` + export const { use: useSync, provider: SyncProvider } = createSimpleContext({ name: "Sync", init: () => { const globalSync = useGlobalSync() const sdk = useSDK() - const [store, setStore] = globalSync.child(sdk.directory) - const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/") + + type Child = ReturnType<(typeof globalSync)["child"]> + type Store = Child[0] + type Setter = Child[1] + + const current = createMemo(() => globalSync.child(sdk.directory)) + const absolute = (path: string) => (current()[0].path.directory + "/" + path).replace("//", "/") const chunk = 400 const inflight = new Map>() const inflightDiff = new Map>() @@ -25,6 +32,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }) const getSession = (sessionID: string) => { + const store = current()[0] const match = Binary.search(store.session, sessionID, (s) => s.id) if (match.found) return store.session[match.index] return undefined @@ -35,22 +43,30 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ return Math.ceil(count / chunk) * chunk } - const hydrateMessages = (sessionID: string) => { - if (meta.limit[sessionID] !== undefined) return + const hydrateMessages = (directory: string, store: Store, sessionID: string) => { + const key = keyFor(directory, sessionID) + if (meta.limit[key] !== undefined) return const messages = store.message[sessionID] if (!messages) return const limit = limitFor(messages.length) - setMeta("limit", sessionID, limit) - setMeta("complete", sessionID, messages.length < limit) + setMeta("limit", key, limit) + setMeta("complete", key, messages.length < limit) } - const loadMessages = async (sessionID: string, limit: number) => { - if (meta.loading[sessionID]) return + const loadMessages = async (input: { + directory: string + client: typeof sdk.client + setStore: Setter + sessionID: string + limit: number + }) => { + const key = keyFor(input.directory, input.sessionID) + if (meta.loading[key]) return - setMeta("loading", sessionID, true) - await retry(() => sdk.client.session.messages({ sessionID, limit })) + setMeta("loading", key, true) + await retry(() => input.client.session.messages({ sessionID: input.sessionID, limit: input.limit })) .then((messages) => { const items = (messages.data ?? []).filter((x) => !!x?.info?.id) const next = items @@ -60,10 +76,10 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ .sort((a, b) => a.id.localeCompare(b.id)) batch(() => { - setStore("message", sessionID, reconcile(next, { key: "id" })) + input.setStore("message", input.sessionID, reconcile(next, { key: "id" })) for (const message of items) { - setStore( + input.setStore( "part", message.info.id, reconcile( @@ -76,25 +92,32 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ ) } - setMeta("limit", sessionID, limit) - setMeta("complete", sessionID, next.length < limit) + setMeta("limit", key, input.limit) + setMeta("complete", key, next.length < input.limit) }) }) .finally(() => { - setMeta("loading", sessionID, false) + setMeta("loading", key, false) }) } + const set: (...args: Parameters) => ReturnType = (...args) => { + return current()[1](...args) + } + return { - data: store, - set: setStore, + get data() { + return current()[0] + }, + set, get status() { - return store.status + return current()[0].status }, get ready() { - return store.status !== "loading" + return current()[0].status !== "loading" }, get project() { + const store = current()[0] const match = Binary.search(globalSync.data.project, store.project, (p) => p.id) if (match.found) return globalSync.data.project[match.index] return undefined @@ -116,7 +139,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ agent: input.agent, model: input.model, } - setStore( + current()[1]( produce((draft) => { const messages = draft.message[input.sessionID] if (!messages) { @@ -133,20 +156,28 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ ) }, async sync(sessionID: string) { - const hasSession = getSession(sessionID) !== undefined - hydrateMessages(sessionID) + const directory = sdk.directory + const client = sdk.client + const [store, setStore] = globalSync.child(directory) + const hasSession = (() => { + const match = Binary.search(store.session, sessionID, (s) => s.id) + return match.found + })() + + hydrateMessages(directory, store, sessionID) const hasMessages = store.message[sessionID] !== undefined if (hasSession && hasMessages) return - const pending = inflight.get(sessionID) + const key = keyFor(directory, sessionID) + const pending = inflight.get(key) if (pending) return pending - const limit = meta.limit[sessionID] ?? chunk + const limit = meta.limit[key] ?? chunk const sessionReq = hasSession ? Promise.resolve() - : retry(() => sdk.client.session.get({ sessionID })).then((session) => { + : retry(() => client.session.get({ sessionID })).then((session) => { const data = session.data if (!data) return setStore( @@ -162,72 +193,104 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ ) }) - const messagesReq = hasMessages ? Promise.resolve() : loadMessages(sessionID, limit) + const messagesReq = hasMessages + ? Promise.resolve() + : loadMessages({ + directory, + client, + setStore, + sessionID, + limit, + }) const promise = Promise.all([sessionReq, messagesReq]) .then(() => {}) .finally(() => { - inflight.delete(sessionID) + inflight.delete(key) }) - inflight.set(sessionID, promise) + inflight.set(key, promise) return promise }, async diff(sessionID: string) { + const directory = sdk.directory + const client = sdk.client + const [store, setStore] = globalSync.child(directory) if (store.session_diff[sessionID] !== undefined) return - const pending = inflightDiff.get(sessionID) + const key = keyFor(directory, sessionID) + const pending = inflightDiff.get(key) if (pending) return pending - const promise = retry(() => sdk.client.session.diff({ sessionID })) + const promise = retry(() => client.session.diff({ sessionID })) .then((diff) => { setStore("session_diff", sessionID, reconcile(diff.data ?? [], { key: "file" })) }) .finally(() => { - inflightDiff.delete(sessionID) + inflightDiff.delete(key) }) - inflightDiff.set(sessionID, promise) + inflightDiff.set(key, promise) return promise }, async todo(sessionID: string) { + const directory = sdk.directory + const client = sdk.client + const [store, setStore] = globalSync.child(directory) if (store.todo[sessionID] !== undefined) return - const pending = inflightTodo.get(sessionID) + const key = keyFor(directory, sessionID) + const pending = inflightTodo.get(key) if (pending) return pending - const promise = retry(() => sdk.client.session.todo({ sessionID })) + const promise = retry(() => client.session.todo({ sessionID })) .then((todo) => { setStore("todo", sessionID, reconcile(todo.data ?? [], { key: "id" })) }) .finally(() => { - inflightTodo.delete(sessionID) + inflightTodo.delete(key) }) - inflightTodo.set(sessionID, promise) + inflightTodo.set(key, promise) return promise }, history: { more(sessionID: string) { + const store = current()[0] + const key = keyFor(sdk.directory, sessionID) if (store.message[sessionID] === undefined) return false - if (meta.limit[sessionID] === undefined) return false - if (meta.complete[sessionID]) return false + if (meta.limit[key] === undefined) return false + if (meta.complete[key]) return false return true }, loading(sessionID: string) { - return meta.loading[sessionID] ?? false + const key = keyFor(sdk.directory, sessionID) + return meta.loading[key] ?? false }, async loadMore(sessionID: string, count = chunk) { - if (meta.loading[sessionID]) return - if (meta.complete[sessionID]) return + const directory = sdk.directory + const client = sdk.client + const [, setStore] = globalSync.child(directory) + const key = keyFor(directory, sessionID) + if (meta.loading[key]) return + if (meta.complete[key]) return - const current = meta.limit[sessionID] ?? chunk - await loadMessages(sessionID, current + count) + const currentLimit = meta.limit[key] ?? chunk + await loadMessages({ + directory, + client, + setStore, + sessionID, + limit: currentLimit + count, + }) }, }, fetch: async (count = 10) => { + const directory = sdk.directory + const client = sdk.client + const [store, setStore] = globalSync.child(directory) setStore("limit", (x) => x + count) - await sdk.client.session.list().then((x) => { + await client.session.list().then((x) => { const sessions = (x.data ?? []) .filter((s) => !!s?.id) .slice() @@ -236,9 +299,12 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ setStore("session", reconcile(sessions, { key: "id" })) }) }, - more: createMemo(() => store.session.length >= store.limit), + more: createMemo(() => current()[0].session.length >= current()[0].limit), archive: async (sessionID: string) => { - await sdk.client.session.update({ sessionID, time: { archived: Date.now() } }) + const directory = sdk.directory + const client = sdk.client + const [, setStore] = globalSync.child(directory) + await client.session.update({ sessionID, time: { archived: Date.now() } }) setStore( produce((draft) => { const match = Binary.search(draft.session, sessionID, (s) => s.id) @@ -249,7 +315,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }, absolute, get directory() { - return store.path.directory + return current()[0].path.directory }, } }, diff --git a/packages/app/src/pages/directory-layout.tsx b/packages/app/src/pages/directory-layout.tsx index dca02489a..caad6c996 100644 --- a/packages/app/src/pages/directory-layout.tsx +++ b/packages/app/src/pages/directory-layout.tsx @@ -16,7 +16,7 @@ export default function Layout(props: ParentProps) { return base64Decode(params.dir!) }) return ( - + {iife(() => { diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 9470a032f..2df35856e 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -199,8 +199,8 @@ export default function Page() { const permission = usePermission() const [pendingMessage, setPendingMessage] = createSignal(undefined) const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) - const tabs = createMemo(() => layout.tabs(sessionKey())) - const view = createMemo(() => layout.view(sessionKey())) + const tabs = createMemo(() => layout.tabs(sessionKey)) + const view = createMemo(() => layout.view(sessionKey)) if (import.meta.env.DEV) { createEffect(