summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-01-16 15:49:29 -0600
committerAdam <[email protected]>2026-01-16 15:49:35 -0600
commit6e00348bd7771847ea60cc182c14c6a4ccad5fe1 (patch)
tree3eb82d5c456ba296861884a676c8dfe7e40096db
parent95f7403daff172beb1dc6c16766348a222e9f670 (diff)
downloadopencode-6e00348bd7771847ea60cc182c14c6a4ccad5fe1.tar.gz
opencode-6e00348bd7771847ea60cc182c14c6a4ccad5fe1.zip
fix(app): remember last opened project
-rw-r--r--packages/app/src/context/server.tsx11
-rw-r--r--packages/app/src/pages/home.tsx3
-rw-r--r--packages/app/src/pages/layout.tsx40
3 files changed, 53 insertions, 1 deletions
diff --git a/packages/app/src/context/server.tsx b/packages/app/src/context/server.tsx
index 8945cd37e..107657092 100644
--- a/packages/app/src/context/server.tsx
+++ b/packages/app/src/context/server.tsx
@@ -36,6 +36,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
createStore({
list: [] as string[],
projects: {} as Record<string, StoredProject[]>,
+ lastProject: {} as Record<string, string>,
}),
)
@@ -197,6 +198,16 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
result.splice(toIndex, 0, item)
setStore("projects", key, result)
},
+ last() {
+ const key = origin()
+ if (!key) return
+ return store.lastProject[key]
+ },
+ touch(directory: string) {
+ const key = origin()
+ if (!key) return
+ setStore("lastProject", key, directory)
+ },
},
}
},
diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx
index 275113566..a9e89a7f5 100644
--- a/packages/app/src/pages/home.tsx
+++ b/packages/app/src/pages/home.tsx
@@ -1,4 +1,3 @@
-import { useGlobalSync } from "@/context/global-sync"
import { createMemo, For, Match, Show, Switch } from "solid-js"
import { Button } from "@opencode-ai/ui/button"
import { Logo } from "@opencode-ai/ui/logo"
@@ -12,6 +11,7 @@ import { useDialog } from "@opencode-ai/ui/context/dialog"
import { DialogSelectDirectory } from "@/components/dialog-select-directory"
import { DialogSelectServer } from "@/components/dialog-select-server"
import { useServer } from "@/context/server"
+import { useGlobalSync } from "@/context/global-sync"
export default function Home() {
const sync = useGlobalSync()
@@ -24,6 +24,7 @@ export default function Home() {
function openProject(directory: string) {
layout.projects.open(directory)
+ server.projects.touch(directory)
navigate(`/${base64Encode(directory)}`)
}
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx
index c25512a15..5e291449f 100644
--- a/packages/app/src/pages/layout.tsx
+++ b/packages/app/src/pages/layout.tsx
@@ -88,6 +88,7 @@ export default function Layout(props: ParentProps) {
onCleanup(() => xlQuery.removeEventListener("change", handleViewportChange))
const params = useParams()
+ const [autoselect, setAutoselect] = createSignal(!params.dir)
const globalSDK = useGlobalSDK()
const globalSync = useGlobalSync()
const layout = useLayout()
@@ -101,6 +102,7 @@ export default function Layout(props: ParentProps) {
const dialog = useDialog()
const command = useCommand()
const theme = useTheme()
+ const initialDir = params.dir
const availableThemeEntries = createMemo(() => Object.entries(theme.themes()))
const colorSchemeOrder: ColorScheme[] = ["system", "light", "dark"]
const colorSchemeLabel: Record<ColorScheme, string> = {
@@ -400,6 +402,43 @@ export default function Layout(props: ParentProps) {
return layout.projects.list().find((p) => p.worktree === directory || p.sandboxes?.includes(directory))
})
+ createEffect(
+ on(
+ () => ({ ready: pageReady(), project: currentProject() }),
+ (value) => {
+ if (!value.ready) return
+ const project = value.project
+ if (!project) return
+ const last = server.projects.last()
+ if (last === project.worktree) return
+ server.projects.touch(project.worktree)
+ },
+ { defer: true },
+ ),
+ )
+
+ createEffect(
+ on(
+ () => ({ ready: pageReady(), layoutReady: layoutReady(), dir: params.dir, list: layout.projects.list() }),
+ (value) => {
+ if (!value.ready) return
+ if (!value.layoutReady) return
+ if (!autoselect()) return
+ if (initialDir) return
+ if (value.dir) return
+ if (value.list.length === 0) return
+
+ const last = server.projects.last()
+ const next = value.list.find((project) => project.worktree === last) ?? value.list[0]
+ if (!next) return
+ setAutoselect(false)
+ openProject(next.worktree, false)
+ navigateToProject(next.worktree)
+ },
+ { defer: true },
+ ),
+ )
+
const workspaceName = (directory: string) => store.workspaceName[directory]
const workspaceLabel = (directory: string, branch?: string) =>
workspaceName(directory) ?? branch ?? getFilename(directory)
@@ -791,6 +830,7 @@ export default function Layout(props: ParentProps) {
function navigateToProject(directory: string | undefined) {
if (!directory) return
+ server.projects.touch(directory)
const lastSession = store.lastSession[directory]
navigate(`/${base64Encode(directory)}${lastSession ? `/session/${lastSession}` : ""}`)
layout.mobileSidebar.hide()