diff --git a/apps/desktop/src/renderer/src/App.tsx b/apps/desktop/src/renderer/src/App.tsx
index bf706081..b0b1f698 100644
--- a/apps/desktop/src/renderer/src/App.tsx
+++ b/apps/desktop/src/renderer/src/App.tsx
@@ -1,6 +1,7 @@
import { useEffect } from 'react'
import { createHashRouter, Navigate, RouterProvider } from 'react-router-dom'
import { ThemeProvider } from './components/theme-provider'
+import { TooltipProvider } from '@multica/ui/components/ui/tooltip'
import Layout from './pages/layout'
import HomePage from './pages/home'
import ChatPage from './pages/chat'
@@ -15,8 +16,7 @@ import { useChannelsStore } from './stores/channels'
function OnboardingGuard({ children }: { children: React.ReactNode }) {
const completed = useOnboardingStore((s) => s.completed)
- const forceOnboarding = useOnboardingStore((s) => s.forceOnboarding)
- if (!completed || forceOnboarding) return
+ if (!completed) return
return <>{children}>
}
@@ -48,7 +48,6 @@ const router = createHashRouter([
export default function App() {
useEffect(() => {
- useOnboardingStore.getState().initForceFlag()
// Prefetch global data at app startup
useProviderStore.getState().fetch()
useChannelsStore.getState().fetch()
@@ -56,7 +55,9 @@ export default function App() {
return (
-
+
+
+
)
}
diff --git a/apps/desktop/src/renderer/src/pages/layout.tsx b/apps/desktop/src/renderer/src/pages/layout.tsx
index e1d9cb1d..9d0f0c31 100644
--- a/apps/desktop/src/renderer/src/pages/layout.tsx
+++ b/apps/desktop/src/renderer/src/pages/layout.tsx
@@ -1,90 +1,114 @@
import { Outlet, NavLink, useLocation } from 'react-router-dom'
import { Toaster } from '@multica/ui/components/ui/sonner'
-import { Button } from '@multica/ui/components/ui/button'
import { HugeiconsIcon } from '@hugeicons/react'
import {
- Settings02Icon,
Home01Icon,
+ Comment01Icon,
CodeIcon,
PlugIcon,
- Comment01Icon,
Share08Icon,
Time04Icon,
} from '@hugeicons/core-free-icons'
+import {
+ Sidebar,
+ SidebarContent,
+ SidebarGroup,
+ SidebarHeader,
+ SidebarInset,
+ SidebarMenu,
+ SidebarMenuButton,
+ SidebarMenuItem,
+ SidebarProvider,
+ SidebarTrigger,
+ useSidebar,
+} from '@multica/ui/components/ui/sidebar'
import { cn } from '@multica/ui/lib/utils'
+import { ModeToggle } from '../components/mode-toggle'
import { DeviceConfirmDialog } from '../components/device-confirm-dialog'
-import ChatPage from './chat'
-const tabs = [
- { path: '/', label: 'Home', icon: Home01Icon, exact: true },
+const navItems = [
+ { path: '/', label: 'Home', icon: Home01Icon },
{ path: '/chat', label: 'Chat', icon: Comment01Icon },
{ path: '/tools', label: 'Tools', icon: CodeIcon },
{ path: '/skills', label: 'Skills', icon: PlugIcon },
{ path: '/channels', label: 'Channels', icon: Share08Icon },
- { path: '/crons', label: 'Cron', icon: Time04Icon },
+ { path: '/crons', label: 'Crons', icon: Time04Icon },
]
+function MainHeader() {
+ const { state, isMobile } = useSidebar()
+ const needsTrafficLightSpace = state === 'collapsed' || isMobile
+
+ return (
+
+ {/* Drag placeholder for traffic lights when sidebar is collapsed */}
+
+
+
+
+ {/* Spacer */}
+
+
+ {/* Right: Theme toggle */}
+
+
+ )
+}
+
export default function Layout() {
const location = useLocation()
return (
-
- {/* Header with drag region for macOS */}
-
-
- Multica
-
-
-
-
-
+
+
+
+ {/* Traffic light area */}
+
- {/* Tabs */}
-
- return (
-
-
-
- )
- })}
-
+
+
- {/* Content */}
-
- {/* ChatPage is always mounted (cached), hidden via CSS */}
-
-
-
+ {/* Main Content */}
+
+
+
+
- {/* Other routes render normally via Outlet */}
- {location.pathname !== '/chat' && (
-
-
-
- )}
-
-
-
+
+
+
)
}
diff --git a/apps/desktop/src/renderer/src/stores/onboarding.ts b/apps/desktop/src/renderer/src/stores/onboarding.ts
index d627e7fc..3b9cbb17 100644
--- a/apps/desktop/src/renderer/src/stores/onboarding.ts
+++ b/apps/desktop/src/renderer/src/stores/onboarding.ts
@@ -10,7 +10,6 @@ interface AcknowledgementsState {
interface OnboardingStore {
completed: boolean
- forceOnboarding: boolean
currentStep: number
acknowledgements: AcknowledgementsState
allAcknowledged: boolean
@@ -23,14 +22,12 @@ interface OnboardingStore {
setProviderConfigured: (configured: boolean) => void
setClientConnected: (connected: boolean) => void
completeOnboarding: () => void
- initForceFlag: () => Promise
}
export const useOnboardingStore = create()(
persist(
(set, get) => ({
completed: false,
- forceOnboarding: false,
currentStep: 0,
acknowledgements: {
@@ -57,14 +54,7 @@ export const useOnboardingStore = create()(
setClientConnected: (connected) => set({ clientConnected: connected }),
- completeOnboarding: () => set({ completed: true, forceOnboarding: false, currentStep: 0 }),
-
- initForceFlag: async () => {
- const flags = await window.electronAPI.app.getFlags()
- if (flags.forceOnboarding) {
- set({ forceOnboarding: true })
- }
- },
+ completeOnboarding: () => set({ completed: true, currentStep: 0 }),
}),
{
name: 'multica-onboarding',