@@ -2,12 +2,12 @@ import { useEffect } from "react";
22import { useNavigate , useRouterState } from "@tanstack/react-router" ;
33import type { ChatSummary } from "@/lib/schemas" ;
44import { formatDistanceToNow } from "date-fns" ;
5- import { PlusCircle } from "lucide-react" ;
5+ import { PlusCircle , MoreVertical , Trash2 } from "lucide-react" ;
66import { useAtom } from "jotai" ;
77import { selectedChatIdAtom } from "@/atoms/chatAtoms" ;
88import { selectedAppIdAtom } from "@/atoms/appAtoms" ;
99import { IpcClient } from "@/ipc/ipc_client" ;
10- import { showError } from "@/lib/toast" ;
10+ import { showError , showSuccess } from "@/lib/toast" ;
1111import {
1212 SidebarGroup ,
1313 SidebarGroupContent ,
@@ -16,6 +16,12 @@ import {
1616 SidebarMenuItem ,
1717} from "@/components/ui/sidebar" ;
1818import { Button } from "@/components/ui/button" ;
19+ import {
20+ DropdownMenu ,
21+ DropdownMenuContent ,
22+ DropdownMenuItem ,
23+ DropdownMenuTrigger ,
24+ } from "@/components/ui/dropdown-menu" ;
1925import { useChats } from "@/hooks/useChats" ;
2026
2127export function ChatList ( { show } : { show ?: boolean } ) {
@@ -82,6 +88,28 @@ export function ChatList({ show }: { show?: boolean }) {
8288 }
8389 } ;
8490
91+ const handleDeleteChat = async ( chatId : number ) => {
92+ try {
93+ const result = await IpcClient . getInstance ( ) . deleteChat ( chatId ) ;
94+ if ( ! result . success ) {
95+ showError ( "Failed to delete chat" ) ;
96+ return ;
97+ }
98+ showSuccess ( "Chat deleted successfully" ) ;
99+
100+ // If the deleted chat was selected, navigate to home
101+ if ( selectedChatId === chatId ) {
102+ setSelectedChatId ( null ) ;
103+ navigate ( { to : "/chat" } ) ;
104+ }
105+
106+ // Refresh the chat list
107+ await refreshChats ( ) ;
108+ } catch ( error ) {
109+ showError ( `Failed to delete chat: ${ ( error as any ) . toString ( ) } ` ) ;
110+ }
111+ } ;
112+
85113 return (
86114 < SidebarGroup className = "overflow-y-auto h-[calc(100vh-112px)]" >
87115 < SidebarGroupLabel > Recent Chats</ SidebarGroupLabel >
@@ -108,28 +136,54 @@ export function ChatList({ show }: { show?: boolean }) {
108136 < SidebarMenu className = "space-y-1" >
109137 { chats . map ( ( chat ) => (
110138 < SidebarMenuItem key = { chat . id } className = "mb-1" >
111- < Button
112- variant = "ghost"
113- onClick = { ( ) =>
114- handleChatClick ( { chatId : chat . id , appId : chat . appId } )
115- }
116- className = { `justify-start w-full text-left py-3 hover:bg-sidebar-accent/80 ${
117- selectedChatId === chat . id
118- ? "bg-sidebar-accent text-sidebar-accent-foreground"
119- : ""
120- } `}
121- >
122- < div className = "flex flex-col w-full" >
123- < span className = "truncate" >
124- { chat . title || "New Chat" }
125- </ span >
126- < span className = "text-xs text-gray-500" >
127- { formatDistanceToNow ( new Date ( chat . createdAt ) , {
128- addSuffix : true ,
129- } ) }
130- </ span >
131- </ div >
132- </ Button >
139+ < div className = "flex w-[185px] items-center" >
140+ < Button
141+ variant = "ghost"
142+ onClick = { ( ) =>
143+ handleChatClick ( { chatId : chat . id , appId : chat . appId } )
144+ }
145+ className = { `justify-start w-full text-left py-3 pr-1 hover:bg-sidebar-accent/80 ${
146+ selectedChatId === chat . id
147+ ? "bg-sidebar-accent text-sidebar-accent-foreground"
148+ : ""
149+ } `}
150+ >
151+ < div className = "flex flex-col w-full" >
152+ < span className = "truncate" >
153+ { chat . title || "New Chat" }
154+ </ span >
155+ < span className = "text-xs text-gray-500" >
156+ { formatDistanceToNow ( new Date ( chat . createdAt ) , {
157+ addSuffix : true ,
158+ } ) }
159+ </ span >
160+ </ div >
161+ </ Button >
162+
163+ { selectedChatId === chat . id && (
164+ < DropdownMenu >
165+ < DropdownMenuTrigger asChild >
166+ < Button
167+ variant = "ghost"
168+ size = "icon"
169+ className = "ml-1 w-4"
170+ onClick = { ( e ) => e . stopPropagation ( ) }
171+ >
172+ < MoreVertical className = "h-4 w-4" />
173+ </ Button >
174+ </ DropdownMenuTrigger >
175+ < DropdownMenuContent align = "end" >
176+ < DropdownMenuItem
177+ variant = "destructive"
178+ onClick = { ( ) => handleDeleteChat ( chat . id ) }
179+ >
180+ < Trash2 className = "mr-2 h-4 w-4" />
181+ < span > Delete Chat</ span >
182+ </ DropdownMenuItem >
183+ </ DropdownMenuContent >
184+ </ DropdownMenu >
185+ ) }
186+ </ div >
133187 </ SidebarMenuItem >
134188 ) ) }
135189 </ SidebarMenu >
0 commit comments