summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/pages/layout
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-02-19 10:23:15 -0600
committerAdam <[email protected]>2026-02-19 11:12:56 -0600
commit6b8902e8b91a7561d57f80249feada949c4d0665 (patch)
treec4e0989b32df5bf7dc849946e6e0c62a758364fc /packages/app/src/pages/layout
parent08a2d002b8f972c98911fd3b25c847c0da8b1d9b (diff)
downloadopencode-6b8902e8b91a7561d57f80249feada949c4d0665.tar.gz
opencode-6b8902e8b91a7561d57f80249feada949c4d0665.zip
fix(app): navigate to last session on project nav
Diffstat (limited to 'packages/app/src/pages/layout')
-rw-r--r--packages/app/src/pages/layout/helpers.test.ts39
-rw-r--r--packages/app/src/pages/layout/helpers.ts18
2 files changed, 56 insertions, 1 deletions
diff --git a/packages/app/src/pages/layout/helpers.test.ts b/packages/app/src/pages/layout/helpers.test.ts
index 83d8f4748..6f868ab69 100644
--- a/packages/app/src/pages/layout/helpers.test.ts
+++ b/packages/app/src/pages/layout/helpers.test.ts
@@ -1,6 +1,13 @@
import { describe, expect, test } from "bun:test"
import { collectOpenProjectDeepLinks, drainPendingDeepLinks, parseDeepLink } from "./deep-links"
-import { displayName, errorMessage, getDraggableId, syncWorkspaceOrder, workspaceKey } from "./helpers"
+import {
+ displayName,
+ errorMessage,
+ getDraggableId,
+ projectSessionTarget,
+ syncWorkspaceOrder,
+ workspaceKey,
+} from "./helpers"
describe("layout deep links", () => {
test("parses open-project deep links", () => {
@@ -89,4 +96,34 @@ describe("layout workspace helpers", () => {
expect(errorMessage(new Error("broken"), "fallback")).toBe("broken")
expect(errorMessage("unknown", "fallback")).toBe("fallback")
})
+
+ test("picks newest session across project workspaces", () => {
+ const result = projectSessionTarget({
+ directory: "/root",
+ project: { worktree: "/root", sandboxes: ["/root/a", "/root/b"] },
+ lastSession: {
+ "/root": "root-session",
+ "/root/a": "sandbox-a",
+ "/root/b": "sandbox-b",
+ },
+ lastSessionAt: {
+ "/root": 1,
+ "/root/a": 3,
+ "/root/b": 2,
+ },
+ })
+
+ expect(result).toEqual({ directory: "/root/a", id: "sandbox-a", at: 3 })
+ })
+
+ test("falls back to project route when no session exists", () => {
+ const result = projectSessionTarget({
+ directory: "/root",
+ project: { worktree: "/root", sandboxes: ["/root/a"] },
+ lastSession: {},
+ lastSessionAt: {},
+ })
+
+ expect(result).toEqual({ directory: "/root" })
+ })
})
diff --git a/packages/app/src/pages/layout/helpers.ts b/packages/app/src/pages/layout/helpers.ts
index 6a1e7c012..88066cfb8 100644
--- a/packages/app/src/pages/layout/helpers.ts
+++ b/packages/app/src/pages/layout/helpers.ts
@@ -62,6 +62,24 @@ export const errorMessage = (err: unknown, fallback: string) => {
return fallback
}
+export function projectSessionTarget(input: {
+ directory: string
+ project?: { worktree: string; sandboxes?: string[] }
+ lastSession: Record<string, string>
+ lastSessionAt: Record<string, number>
+}): { directory: string; id?: string; at?: number } {
+ const dirs = input.project ? [input.project.worktree, ...(input.project.sandboxes ?? [])] : [input.directory]
+ const best = dirs.reduce<{ directory: string; id: string; at: number } | undefined>((result, directory) => {
+ const id = input.lastSession[directory]
+ if (!id) return result
+ const at = input.lastSessionAt[directory] ?? 0
+ if (result && result.at >= at) return result
+ return { directory, id, at }
+ }, undefined)
+ if (best) return best
+ return { directory: input.directory }
+}
+
export const syncWorkspaceOrder = (local: string, dirs: string[], existing?: string[]) => {
if (!existing) return dirs
const keep = existing.filter((d) => d !== local && dirs.includes(d))