From c78ef5f05a3da40174ce3106ee64f7bfc613b564 Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Thu, 16 Apr 2026 11:27:47 +0800 Subject: [PATCH] fix(desktop): wrap shell in WorkspaceSlugProvider from module var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AppSidebar calls useWorkspacePaths() → useRequiredWorkspaceSlug() which throws outside WorkspaceSlugProvider. In the desktop shell, the sidebar renders at the shell level (outside any tab's WorkspaceRouteLayout). Fix: DesktopShell reads the current slug via useSyncExternalStore on the workspace-storage singleton. When slug is available, wraps the entire shell in WorkspaceSlugProvider. When null (first mount before any tab's WorkspaceRouteLayout sets it), shows a loading spinner. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/components/desktop-layout.tsx | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/apps/desktop/src/renderer/src/components/desktop-layout.tsx b/apps/desktop/src/renderer/src/components/desktop-layout.tsx index 08a11c4c99..02459a09da 100644 --- a/apps/desktop/src/renderer/src/components/desktop-layout.tsx +++ b/apps/desktop/src/renderer/src/components/desktop-layout.tsx @@ -1,4 +1,4 @@ -import { useEffect } from "react"; +import { useEffect, useSyncExternalStore } from "react"; import { ChevronLeft, ChevronRight } from "lucide-react"; import { cn } from "@multica/ui/lib/utils"; import { useTabHistory } from "@/hooks/use-tab-history"; @@ -13,6 +13,9 @@ import { AppSidebar } from "@multica/views/layout"; import { SearchCommand, SearchTrigger } from "@multica/views/search"; import { ChatFab, ChatWindow } from "@multica/views/chat"; import { StepWorkspace } from "@multica/views/onboarding"; +import { WorkspaceSlugProvider } from "@multica/core/paths"; +import { getCurrentSlug, subscribeToCurrentSlug } from "@multica/core/platform"; +import { MulticaIcon } from "@multica/ui/components/common/multica-icon"; import { DesktopNavigationProvider } from "@/platform/navigation"; import { OnboardingGate } from "./onboarding-gate"; import { TabBar } from "./tab-bar"; @@ -87,6 +90,12 @@ export function DesktopShell() { useInternalLinkHandler(); useActiveTitleSync(); + // Reactive read of current workspace slug from the platform singleton. + // On first mount, slug is null until WorkspaceRouteLayout (inside the tab + // router) sets it. Once set, the sidebar and other shell-level components + // can resolve workspace-scoped paths via useWorkspacePaths(). + const slug = useSyncExternalStore(subscribeToCurrentSlug, getCurrentSlug, () => null); + return ( )} > -
- - } searchSlot={} /> - {/* Right side: header + content container */} -
- - {/* Content area with inset styling — relative so ChatWindow/ChatFab are constrained here */} -
- - - -
+ {slug ? ( + +
+ + } searchSlot={} /> + {/* Right side: header + content container */} +
+ + {/* Content area with inset styling — relative so ChatWindow/ChatFab are constrained here */} +
+ + + +
+
+
- -
- - + + + + ) : ( +
+ +
+ )} );