feat: add URL-driven workspace state and streamed Codex research

This commit is contained in:
2026-09-28 20:08:28 +09:00
parent 85d23a328b
commit 8085ad2f90
207 changed files with 15287 additions and 16026 deletions
+38 -48
View File
@@ -1,15 +1,7 @@
import { Link, useLocation, useRouteContext } from '@tanstack/react-router'
import {
Activity,
House,
Inbox,
Layers3,
MessagesSquare,
NotebookPen,
Search,
} from 'lucide-react'
import { type ReactNode, useState } from 'react'
import { Avatar, AvatarFallback } from '#/components/ui/avatar'
import { Link, useLocation, useRouteContext } from "@tanstack/react-router";
import { Activity, House, Inbox, Layers3, MessagesSquare, NotebookPen, Search } from "lucide-react";
import type { ReactNode } from "react";
import { Avatar, AvatarFallback } from "#/components/ui/avatar";
import {
Sidebar,
SidebarContent,
@@ -21,62 +13,62 @@ import {
SidebarMenuButton,
SidebarMenuItem,
SidebarSeparator,
} from '#/components/ui/sidebar'
import { ConnectionManagerDialog } from '#/features/connections/connection-manager-dialog'
} from "#/components/ui/sidebar";
import { ConnectionManagerDialog } from "#/features/connections/connection-manager-dialog";
import { useUrlState } from "#/features/navigation/use-url-state";
type WorkspaceNavigationProps = {
children?: ReactNode
footer?: ReactNode
hasTemporaryDecks?: boolean
}
children?: ReactNode;
footer?: ReactNode;
hasTemporaryDecks?: boolean;
};
export function WorkspaceNavigation({
children,
footer,
hasTemporaryDecks,
}: WorkspaceNavigationProps) {
const { auth } = useRouteContext({ from: '__root__' })
const [managingAccounts, setManagingAccounts] = useState(false)
const pathname = useLocation({ select: (location) => location.pathname })
const { auth } = useRouteContext({ from: "__root__" });
const [search, updateSearch] = useUrlState();
const managingAccounts = search.accounts;
const setManagingAccounts = (open: boolean) => updateSearch({ accounts: open || undefined });
const pathname = useLocation({ select: (location) => location.pathname });
const navigation = [
{ title: 'Home', to: '/', icon: House, active: pathname === '/' },
{ title: "Home", to: "/", icon: House, active: pathname === "/" },
{
title: 'Vitals',
to: '/vitals',
title: "Vitals",
to: "/vitals",
icon: Activity,
active: pathname === '/vitals',
active: pathname === "/vitals",
},
{
title: 'Messages',
to: '/support',
title: "Messages",
to: "/support",
icon: MessagesSquare,
active: pathname === '/support',
active: pathname === "/support",
},
{
title: 'Journal',
to: '/journal',
title: "Journal",
to: "/journal",
icon: NotebookPen,
active: pathname === '/journal',
active: pathname === "/journal",
},
{
title: 'Reader',
to: '/inbox',
title: "Reader",
to: "/inbox",
icon: Inbox,
active: pathname === '/inbox',
active: pathname === "/inbox",
},
{
title: 'Research',
to: '/deck',
title: "Research",
to: "/deck",
icon: Search,
active: pathname === '/deck',
active: pathname === "/deck",
},
] as const
] as const;
return (
<Sidebar
collapsible="none"
className="workspace-navigation w-16! shrink-0 border-r"
>
<Sidebar collapsible="none" className="w-16! shrink-0 border-r">
<SidebarHeader className="items-center py-4">
<div
className="flex size-9 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground"
@@ -94,7 +86,7 @@ export function WorkspaceNavigation({
<SidebarMenuItem key={item.to}>
<SidebarMenuButton
aria-label={item.title}
aria-current={item.active ? 'page' : undefined}
aria-current={item.active ? "page" : undefined}
tooltip={{ children: item.title, hidden: false }}
isActive={item.active}
render={<Link to={item.to} />}
@@ -125,14 +117,12 @@ export function WorkspaceNavigation({
<SidebarMenuItem>
<SidebarMenuButton
aria-label="Manage connected accounts"
tooltip={{ children: 'Manage connected accounts', hidden: false }}
tooltip={{ children: "Manage connected accounts", hidden: false }}
className="size-10 justify-center p-0"
onClick={() => setManagingAccounts(true)}
>
<Avatar className="size-8">
<AvatarFallback>
{auth.owner?.name.slice(0, 1).toUpperCase()}
</AvatarFallback>
<AvatarFallback>{auth.owner?.name.slice(0, 1).toUpperCase()}</AvatarFallback>
</Avatar>
</SidebarMenuButton>
</SidebarMenuItem>
@@ -145,5 +135,5 @@ export function WorkspaceNavigation({
/>
)}
</Sidebar>
)
);
}