From a7265307355e7efed9e276da6625c96458009db6 Mon Sep 17 00:00:00 2001
From: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Date: Fri, 17 Apr 2026 15:26:14 +0800
Subject: fix(app): workspace loading and persist ready state (#23046)
---
packages/app/src/pages/layout.tsx | 364 ++++++++++-----------
.../app/src/pages/layout/sidebar-workspace.tsx | 12 +-
2 files changed, 186 insertions(+), 190 deletions(-)
(limited to 'packages/app/src/pages')
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx
index 12a2bf763..6f6b3c555 100644
--- a/packages/app/src/pages/layout.tsx
+++ b/packages/app/src/pages/layout.tsx
@@ -13,7 +13,7 @@ import {
type Accessor,
} from "solid-js"
import { makeEventListener } from "@solid-primitives/event-listener"
-import { useNavigate, useParams } from "@solidjs/router"
+import { useLocation, useNavigate, useParams } from "@solidjs/router"
import { useLayout, LocalProject } from "@/context/layout"
import { useGlobalSync } from "@/context/global-sync"
import { Persist, persisted } from "@/utils/persist"
@@ -127,6 +127,7 @@ export default function Layout(props: ParentProps) {
const theme = useTheme()
const language = useLanguage()
const initialDirectory = decode64(params.dir)
+ const location = useLocation()
const route = createMemo(() => {
const slug = params.dir
if (!slug) return { slug, dir: "" }
@@ -576,7 +577,7 @@ export default function Layout(props: ParentProps) {
return projects.find((p) => p.worktree === root)
})
-
+
const [autoselecting] = createResource(async () => {
await ready.promise
await layout.ready.promise
@@ -2102,196 +2103,198 @@ export default function Layout(props: ParentProps) {
}
>
- <>
-
-
-
- {
- const item = project()
- if (!item) return
- void renameProject(item, next)
- }}
- class="text-14-medium text-text-strong truncate"
- displayClass="text-14-medium text-text-strong truncate"
- stopPropagation
- />
-
-
-
- {worktree().replace(homedir(), "~")}
-
-
-
+ {(project) => (
+ <>
+
+
+
+ {
+ const item = project()
+ if (!item) return
+ void renameProject(item, next)
+ }}
+ class="text-14-medium text-text-strong truncate"
+ displayClass="text-14-medium text-text-strong truncate"
+ stopPropagation
+ />
+
+
+
+ {worktree().replace(homedir(), "~")}
+
+
+
-
-
-
-
- {
- const item = project()
- if (!item) return
- showEditProjectDialog(item)
- }}
- >
- {language.t("common.edit")}
-
- {
- const item = project()
- if (!item) return
- toggleProjectWorkspaces(item)
- }}
- >
-
- {workspacesEnabled()
- ? language.t("sidebar.workspaces.disable")
- : language.t("sidebar.workspaces.enable")}
-
-
-
-
- {language.t("sidebar.project.clearNotifications")}
-
-
-
- {
- const dir = worktree()
- if (!dir) return
- closeProject(dir)
- }}
- >
- {language.t("common.close")}
-
-
-
-
+
+
+
+
+ {
+ const item = project()
+ if (!item) return
+ showEditProjectDialog(item)
+ }}
+ >
+ {language.t("common.edit")}
+
+ {
+ const item = project()
+ if (!item) return
+ toggleProjectWorkspaces(item)
+ }}
+ >
+
+ {workspacesEnabled()
+ ? language.t("sidebar.workspaces.disable")
+ : language.t("sidebar.workspaces.enable")}
+
+
+
+
+ {language.t("sidebar.project.clearNotifications")}
+
+
+
+ {
+ const dir = worktree()
+ if (!dir) return
+ closeProject(dir)
+ }}
+ >
+ {language.t("common.close")}
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+ >
+ }
+ >
<>
-
-
+
+
+
+
+ {
+ if (!panelProps.mobile) scrollContainerRef = el
+ }}
+ class="size-full flex flex-col py-2 gap-4 overflow-y-auto no-scrollbar [overflow-anchor:none]"
+ >
+
+
+ {(directory) => (
+
+ )}
+
+
+
+
+ store.activeWorkspace}
+ workspaceLabel={workspaceLabel}
+ />
+
+
>
- }
- >
- <>
-
-
-
-
-
-
-
- {
- if (!panelProps.mobile) scrollContainerRef = el
- }}
- class="size-full flex flex-col py-2 gap-4 overflow-y-auto no-scrollbar [overflow-anchor:none]"
- >
-
-
- {(directory) => (
-
- )}
-
-
-
-
- store.activeWorkspace}
- workspaceLabel={workspaceLabel}
- />
-
-
-
- >
-
-
- >
+
+
+ >
+ )}
)
- const [loading] = createResource(
- () => route()?.store?.[0]?.bootstrapPromise,
- (p) => p,
- )
-
return (
- {(autoselecting(), loading()) ?? ""}
+ {autoselecting() ?? ""}
diff --git a/packages/app/src/pages/layout/sidebar-workspace.tsx b/packages/app/src/pages/layout/sidebar-workspace.tsx
index c1836fa8a..0202cfc3b 100644
--- a/packages/app/src/pages/layout/sidebar-workspace.tsx
+++ b/packages/app/src/pages/layout/sidebar-workspace.tsx
@@ -317,12 +317,11 @@ export const SortableWorkspace = (props: {
})
const open = createMemo(() => props.ctx.workspaceExpanded(props.directory, local()))
const boot = createMemo(() => open() || active())
- const booted = createMemo((prev) => prev || workspaceStore.status === "complete", false)
const count = createMemo(() => sessions()?.length ?? 0)
const hasMore = createMemo(() => workspaceStore.sessionTotal > count())
+ const query = useQuery(() => ({ ...loadSessionsQuery(props.project.worktree) }))
const busy = createMemo(() => props.ctx.isBusy(props.directory))
- const wasBusy = createMemo((prev) => prev || busy(), false)
- const loading = createMemo(() => open() && !booted() && count() === 0 && !wasBusy())
+ const loading = () => query.isLoading
const touch = createMediaQuery("(hover: none)")
const showNew = createMemo(() => !loading() && (touch() || count() === 0 || (active() && !params.id)))
const loadMore = async () => {
@@ -427,7 +426,7 @@ export const SortableWorkspace = (props: {
mobile={props.mobile}
ctx={props.ctx}
showNew={showNew}
- loading={loading}
+ loading={() => query.isLoading && count() === 0}
sessions={sessions}
hasMore={hasMore}
loadMore={loadMore}
@@ -453,11 +452,10 @@ export const LocalWorkspace = (props: {
})
const slug = createMemo(() => base64Encode(props.project.worktree))
const sessions = createMemo(() => sortedRootSessions(workspace().store, props.sortNow()))
- const booted = createMemo((prev) => prev || workspace().store.status === "complete", false)
const count = createMemo(() => sessions()?.length ?? 0)
const query = useQuery(() => ({ ...loadSessionsQuery(props.project.worktree) }))
- const loading = createMemo(() => query.isPending && count() === 0)
const hasMore = createMemo(() => workspace().store.sessionTotal > count())
+ const loading = () => query.isLoading && count() === 0
const loadMore = async () => {
workspace().setStore("limit", (limit) => (limit ?? 0) + 5)
await globalSync.project.loadSessions(props.project.worktree)
@@ -473,7 +471,7 @@ export const LocalWorkspace = (props: {
mobile={props.mobile}
ctx={props.ctx}
showNew={() => false}
- loading={() => query.isLoading}
+ loading={loading}
sessions={sessions}
hasMore={hasMore}
loadMore={loadMore}
--
cgit v1.2.3