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 */} - + + - {/* 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',