open-swe/apps/web/src/components/v2/thread-switcher.tsx
Dylan Boudro d51af805e2
Feat: Thread Status SWR Polling (#370)
* init swr polling branch

* useThreads types improvement

* minor build fix

* major refactor and simplification of polling system

* remove temp guide file

* refactor, remove errorBoundary, simplify schema

* refactor: unify client<>server status logic

* fix threads/page conflicts + functionality

* Update apps/web/src/components/v2/thread-card.tsx

Co-authored-by: Brace Sproul <braceasproul@gmail.com>

* CR in progress

* CR fix: add cn to thread-card.tsx

Co-authored-by: Brace Sproul <braceasproul@gmail.com>

* CR

* CR

* CR: no threads state, Batch ThreadsStatus for /chat/threads actual logic

* drop req type validation in lg proxy

* optimize thread polling, reduce unnecessary api calls, match implementation spec

* reduce unnecessary api calls, update all threads page

* add thread loading state to threadCard

* utilize threads/search for manager thread info

* improve polling api req efficiency

* rm comments

* post merge format

* fix import

* improve programmer cache logic

* reduce run requests

* remove timeout run requests

* remove run check for completed tasks

* fix: update status dot to support dark mode styles too

* fix session cache and proper typing

* fix: more typing

* code review fixes

* CR

* code review

* fix build

---------

Co-authored-by: Brace Sproul <braceasproul@gmail.com>
2025-07-15 17:51:12 -07:00

110 lines
3.2 KiB
TypeScript

"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
import {
CheckCircle,
XCircle,
Loader2,
GitBranch,
Layers3,
Plus,
Bug,
} from "lucide-react";
import { useRouter } from "next/navigation";
import { ThreadMetadata } from "./types";
import { ThreadCard } from "./thread-card";
interface ThreadSwitcherProps {
currentThread: ThreadMetadata;
allThreads: ThreadMetadata[];
}
export function ThreadSwitcher({
currentThread,
allThreads,
}: ThreadSwitcherProps) {
const [open, setOpen] = useState(false);
const router = useRouter();
const otherThreads = allThreads.filter((t) => t.id !== currentThread.id);
return (
<Sheet
open={open}
onOpenChange={setOpen}
>
<SheetTrigger asChild>
<Button
variant="outline"
size="sm"
className="border-border bg-card text-muted-foreground hover:bg-muted hover:text-foreground h-7 gap-1 text-xs dark:border-gray-700 dark:bg-gray-900 dark:hover:bg-gray-800 dark:hover:text-gray-300"
>
<Layers3 className="h-3 w-3" />
<span className="hidden sm:inline">Switch Thread</span>
</Button>
</SheetTrigger>
<SheetContent
side="right"
className="border-border bg-background w-80 sm:w-96 dark:border-gray-800 dark:bg-gray-950"
>
<SheetHeader className="pb-4">
<SheetTitle className="text-foreground text-base">
All Threads
</SheetTitle>
</SheetHeader>
<div className="mx-2 h-full space-y-3">
{/* New Chat Button */}
<Button
onClick={() => {
router.push("/chat");
setOpen(false);
}}
className="border-border bg-card text-foreground hover:bg-muted h-8 w-full justify-start gap-2 text-xs dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 dark:hover:bg-gray-800"
variant="outline"
>
<Plus className="h-3 w-3" />
Start New Chat
</Button>
{/* Current Thread */}
<div className="space-y-2">
<h3 className="text-muted-foreground text-xs font-medium tracking-wide uppercase dark:text-gray-500">
Current Thread
</h3>
<ThreadCard thread={currentThread} />
</div>
{/* Other Threads */}
{otherThreads.length > 0 && (
<div className="h-full space-y-2">
<h3 className="text-muted-foreground text-xs font-medium tracking-wide uppercase dark:text-gray-500">
Other Threads
</h3>
<ScrollArea className="h-full">
<div className="space-y-1">
{otherThreads.map((thread) => (
<ThreadCard
thread={thread}
key={thread.id}
/>
))}
</div>
</ScrollArea>
</div>
)}
</div>
</SheetContent>
</Sheet>
);
}