diff options
| author | Adam <[email protected]> | 2026-03-02 10:50:50 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-03-02 10:50:50 -0600 |
| commit | 8176bafc555e562ade48a675dffa3f38751ed8c9 (patch) | |
| tree | 7d4b0f6e98f431999b89c1f24687f6f53bd0bc6b /packages/app/src/context/layout.tsx | |
| parent | 0a3a3216db5974efd3edc9a213054fd97d8dbd34 (diff) | |
| download | opencode-8176bafc555e562ade48a675dffa3f38751ed8c9.tar.gz opencode-8176bafc555e562ade48a675dffa3f38751ed8c9.zip | |
chore(app): solidjs refactoring (#13399)
Diffstat (limited to 'packages/app/src/context/layout.tsx')
| -rw-r--r-- | packages/app/src/context/layout.tsx | 82 |
1 files changed, 77 insertions, 5 deletions
diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx index 71f0294e7..5199e5a26 100644 --- a/packages/app/src/context/layout.tsx +++ b/packages/app/src/context/layout.tsx @@ -7,8 +7,10 @@ import { useServer } from "./server" import { usePlatform } from "./platform" import { Project } from "@opencode-ai/sdk/v2" import { Persist, persisted, removePersisted } from "@/utils/persist" +import { decode64 } from "@/utils/base64" import { same } from "@/utils/same" import { createScrollPersistence, type SessionScroll } from "./layout-scroll" +import { createPathHelpers } from "./file/path" const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const const DEFAULT_PANEL_WIDTH = 344 @@ -96,6 +98,38 @@ function nextSessionTabsForOpen(current: SessionTabs | undefined, tab: string): return { all, active: tab } } +const sessionPath = (key: string) => { + const dir = key.split("/")[0] + if (!dir) return + const root = decode64(dir) + if (!root) return + return createPathHelpers(() => root) +} + +const normalizeSessionTab = (path: ReturnType<typeof createPathHelpers> | undefined, tab: string) => { + if (!tab.startsWith("file://")) return tab + if (!path) return tab + return path.tab(tab) +} + +const normalizeSessionTabList = (path: ReturnType<typeof createPathHelpers> | undefined, all: string[]) => { + const seen = new Set<string>() + return all.flatMap((tab) => { + const value = normalizeSessionTab(path, tab) + if (seen.has(value)) return [] + seen.add(value) + return [value] + }) +} + +const normalizeStoredSessionTabs = (key: string, tabs: SessionTabs) => { + const path = sessionPath(key) + return { + all: normalizeSessionTabList(path, tabs.all), + active: tabs.active ? normalizeSessionTab(path, tabs.active) : tabs.active, + } +} + export const { use: useLayout, provider: LayoutProvider } = createSimpleContext({ name: "Layout", init: () => { @@ -147,12 +181,46 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( } })() - if (migratedSidebar === sidebar && migratedReview === review && migratedFileTree === fileTree) return value + const sessionTabs = value.sessionTabs + const migratedSessionTabs = (() => { + if (!isRecord(sessionTabs)) return sessionTabs + + let changed = false + const next = Object.fromEntries( + Object.entries(sessionTabs).map(([key, tabs]) => { + if (!isRecord(tabs) || !Array.isArray(tabs.all)) return [key, tabs] + + const current = { + all: tabs.all.filter((tab): tab is string => typeof tab === "string"), + active: typeof tabs.active === "string" ? tabs.active : undefined, + } + const normalized = normalizeStoredSessionTabs(key, current) + if (current.all.length !== tabs.all.length) changed = true + if (!same(current.all, normalized.all) || current.active !== normalized.active) changed = true + if (tabs.active !== undefined && typeof tabs.active !== "string") changed = true + return [key, normalized] + }), + ) + + if (!changed) return sessionTabs + return next + })() + + if ( + migratedSidebar === sidebar && + migratedReview === review && + migratedFileTree === fileTree && + migratedSessionTabs === sessionTabs + ) { + return value + } + return { ...value, sidebar: migratedSidebar, review: migratedReview, fileTree: migratedFileTree, + sessionTabs: migratedSessionTabs, } } @@ -745,22 +813,26 @@ 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 normalize = (tab: string) => normalizeSessionTab(path(), tab) + const normalizeAll = (all: string[]) => normalizeSessionTabList(path(), all) return { tabs, active: createMemo(() => tabs().active), all: createMemo(() => tabs().all.filter((tab) => tab !== "review")), setActive(tab: string | undefined) { const session = key() + const next = tab ? normalize(tab) : tab if (!store.sessionTabs[session]) { - setStore("sessionTabs", session, { all: [], active: tab }) + setStore("sessionTabs", session, { all: [], active: next }) } else { - setStore("sessionTabs", session, "active", tab) + setStore("sessionTabs", session, "active", next) } }, setAll(all: string[]) { const session = key() - const next = all.filter((tab) => tab !== "review") + const next = normalizeAll(all).filter((tab) => tab !== "review") if (!store.sessionTabs[session]) { setStore("sessionTabs", session, { all: next, active: undefined }) } else { @@ -769,7 +841,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, async open(tab: string) { const session = key() - const next = nextSessionTabsForOpen(store.sessionTabs[session], tab) + const next = nextSessionTabsForOpen(store.sessionTabs[session], normalize(tab)) setStore("sessionTabs", session, next) }, close(tab: string) { |
