diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts
index 72caed40ad9..8efd9d3bc9f 100644
--- a/packages/app/src/i18n/en.ts
+++ b/packages/app/src/i18n/en.ts
@@ -23,6 +23,8 @@ export const dict = {
"command.sidebar.toggle": "Toggle sidebar",
"command.project.open": "Open project",
+ "command.project.previous": "Previous project",
+ "command.project.next": "Next project",
"command.provider.connect": "Connect provider",
"command.server.switch": "Switch server",
"command.settings.open": "Open settings",
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx
index 8e2248469de..0c10cc89bce 100644
--- a/packages/app/src/pages/layout.tsx
+++ b/packages/app/src/pages/layout.tsx
@@ -936,6 +936,26 @@ export default function Layout(props: ParentProps) {
navigateToSession(session)
}
+ function navigateProjectByOffset(offset: number) {
+ const projects = layout.projects.list()
+ if (projects.length === 0) return
+
+ const current = currentProject()?.worktree
+ const fallback = currentDir() ? projectRoot(currentDir()) : undefined
+ const active = current ?? fallback
+ const index = active ? projects.findIndex((project) => project.worktree === active) : -1
+
+ const target =
+ index === -1
+ ? offset > 0
+ ? projects[0]
+ : projects[projects.length - 1]
+ : projects[(index + offset + projects.length) % projects.length]
+ if (!target) return
+
+ openProject(target.worktree)
+ }
+
function navigateSessionByUnseen(offset: number) {
const sessions = currentSessions()
if (sessions.length === 0) return
@@ -1002,6 +1022,20 @@ export default function Layout(props: ParentProps) {
keybind: "mod+o",
onSelect: () => chooseProject(),
},
+ {
+ id: "project.previous",
+ title: language.t("command.project.previous"),
+ category: language.t("command.category.project"),
+ keybind: "mod+alt+arrowup",
+ onSelect: () => navigateProjectByOffset(-1),
+ },
+ {
+ id: "project.next",
+ title: language.t("command.project.next"),
+ category: language.t("command.category.project"),
+ keybind: "mod+alt+arrowdown",
+ onSelect: () => navigateProjectByOffset(1),
+ },
{
id: "provider.connect",
title: language.t("command.provider.connect"),
@@ -2334,14 +2368,12 @@ export default function Layout(props: ParentProps) {
size={layout.sidebar.width()}
min={244}
max={typeof window === "undefined" ? 1000 : window.innerWidth * 0.3 + 64}
- collapseThreshold={244}
onResize={(w) => {
setState("sizing", true)
if (sizet !== undefined) clearTimeout(sizet)
sizet = window.setTimeout(() => setState("sizing", false), 120)
layout.sidebar.resize(w)
}}
- onCollapse={layout.sidebar.close}
/>
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx
index 6d29170081a..428826f6ad9 100644
--- a/packages/app/src/pages/session.tsx
+++ b/packages/app/src/pages/session.tsx
@@ -1,5 +1,6 @@
import type { Project, UserMessage } from "@opencode-ai/sdk/v2"
import { useDialog } from "@opencode-ai/ui/context/dialog"
+import { useMutation } from "@tanstack/solid-query"
import {
batch,
onCleanup,
@@ -327,10 +328,7 @@ export default function Page() {
})
const [ui, setUi] = createStore({
- git: false,
pendingMessage: undefined as string | undefined,
- restoring: undefined as string | undefined,
- reverting: false,
reviewSnap: false,
scrollGesture: 0,
scroll: {
@@ -506,7 +504,6 @@ export default function Page() {
const [followup, setFollowup] = createStore({
items: {} as Record