@@ -3,7 +3,7 @@ import { Link, useNavigate } from "react-router";
33import { useMutation , useQueryClient } from "@tanstack/react-query" ;
44import type { Agent , Conversation , ConversationWithMessages } from "@godmode/shared" ;
55import { EFFORT_LABELS } from "@godmode/shared" ;
6- import { Archive , ArchiveRestore , AudioLines , ChevronRight , Cpu , Ellipsis , HeartPulse , Laptop , Moon , Pencil , Pin , PinOff , Share2 , SquareKanban , Trash2 , Plug , Workflow } from "lucide-react" ;
6+ import { Archive , ArchiveRestore , AudioLines , ChevronRight , Cpu , Ellipsis , HeartPulse , Laptop , Moon , Pencil , Pin , PinOff , Share2 , SquareKanban , Trash2 , Plug , Workflow , X } from "lucide-react" ;
77import { toast } from "sonner" ;
88import { Button } from "@/components/ui/button" ;
99import {
@@ -20,6 +20,7 @@ import type { AgentMood } from "@/components/chat/conversation-mood";
2020import { PLATFORMS } from "@/components/messaging/platform" ;
2121import { THIS_COMPUTER_INLINE } from "@/components/runners/runner-parts" ;
2222import { DeleteChatDialog , useArchiveChat } from "@/components/chat/chat-actions" ;
23+ import { PrivateChatBadge } from "@/components/chat/private-chat" ;
2324import { useEffectiveModel } from "@/components/chat/model-picker" ;
2425import { useModelLabel } from "@/components/runs/run-status" ;
2526import { api , errorMessage } from "@/lib/api" ;
@@ -183,6 +184,7 @@ export function ConversationHeader({
183184 < TooltipContent > Model, effort and Ultracode set for this chat — in the model picker or with /model and /effort</ TooltipContent >
184185 </ Tooltip >
185186 ) }
187+ { conversation . private && < PrivateChatBadge /> }
186188 { conversation . archived && (
187189 < Link
188190 to = "/archived"
@@ -195,21 +197,23 @@ export function ConversationHeader({
195197
196198 < div className = "flex shrink-0 items-center gap-0.5" >
197199 { browserToggle }
198- < Tooltip >
199- < TooltipTrigger asChild >
200- < Button
201- variant = "ghost"
202- size = "icon-sm"
203- aria-label = { conversation . pinned ? "Unpin chat" : "Pin chat" }
204- aria-pressed = { conversation . pinned }
205- onClick = { ( ) => update . mutate ( { pinned : ! conversation . pinned } ) }
206- className = { cn ( "text-muted-foreground" , conversation . pinned && "text-foreground" ) }
207- >
208- < Pin className = { cn ( conversation . pinned && "fill-current" ) } />
209- </ Button >
210- </ TooltipTrigger >
211- < TooltipContent > { conversation . pinned ? "Unpin" : "Pin to sidebar" } </ TooltipContent >
212- </ Tooltip >
200+ { ! conversation . private && (
201+ < Tooltip >
202+ < TooltipTrigger asChild >
203+ < Button
204+ variant = "ghost"
205+ size = "icon-sm"
206+ aria-label = { conversation . pinned ? "Unpin chat" : "Pin chat" }
207+ aria-pressed = { conversation . pinned }
208+ onClick = { ( ) => update . mutate ( { pinned : ! conversation . pinned } ) }
209+ className = { cn ( "text-muted-foreground" , conversation . pinned && "text-foreground" ) }
210+ >
211+ < Pin className = { cn ( conversation . pinned && "fill-current" ) } />
212+ </ Button >
213+ </ TooltipTrigger >
214+ < TooltipContent > { conversation . pinned ? "Unpin" : "Pin to sidebar" } </ TooltipContent >
215+ </ Tooltip >
216+ ) }
213217 { onVoiceMode && (
214218 < Tooltip >
215219 < TooltipTrigger asChild >
@@ -220,33 +224,44 @@ export function ConversationHeader({
220224 < TooltipContent > Voice mode</ TooltipContent >
221225 </ Tooltip >
222226 ) }
223- < DropdownMenu >
224- < DropdownMenuTrigger asChild >
225- < Button variant = "ghost" size = "icon-sm" aria-label = "More actions" className = "text-muted-foreground" >
226- < Ellipsis />
227- </ Button >
228- </ DropdownMenuTrigger >
229- < DropdownMenuContent align = "end" className = "w-48" >
230- < DropdownMenuItem onClick = { ( ) => setEditing ( true ) } >
231- < Pencil /> Rename
232- </ DropdownMenuItem >
233- < DropdownMenuItem onClick = { ( ) => update . mutate ( { pinned : ! conversation . pinned } ) } >
234- { conversation . pinned ? < PinOff /> : < Pin /> } { conversation . pinned ? "Unpin" : "Pin" }
235- </ DropdownMenuItem >
236- < DropdownMenuItem onClick = { ( ) => setArchived ( conversation , ! conversation . archived ) } >
237- { conversation . archived ? < ArchiveRestore /> : < Archive /> } { conversation . archived ? "Unarchive" : "Archive" }
238- </ DropdownMenuItem >
239- { move && (
240- < DropdownMenuItem disabled = { ! ! move . blocked } title = { move . blocked ?? undefined } onClick = { move . onSelect } >
241- < Laptop /> { move . label ?? `Move to ${ THIS_COMPUTER_INLINE } ` }
227+ { conversation . private ? (
228+ < Tooltip >
229+ < TooltipTrigger asChild >
230+ < Button variant = "ghost" size = "sm" aria-label = "End private chat" className = "gap-1 text-muted-foreground" onClick = { ( ) => navigate ( "/" ) } >
231+ < X /> End
232+ </ Button >
233+ </ TooltipTrigger >
234+ < TooltipContent > End and wipe this chat</ TooltipContent >
235+ </ Tooltip >
236+ ) : (
237+ < DropdownMenu >
238+ < DropdownMenuTrigger asChild >
239+ < Button variant = "ghost" size = "icon-sm" aria-label = "More actions" className = "text-muted-foreground" >
240+ < Ellipsis />
241+ </ Button >
242+ </ DropdownMenuTrigger >
243+ < DropdownMenuContent align = "end" className = "w-48" >
244+ < DropdownMenuItem onClick = { ( ) => setEditing ( true ) } >
245+ < Pencil /> Rename
246+ </ DropdownMenuItem >
247+ < DropdownMenuItem onClick = { ( ) => update . mutate ( { pinned : ! conversation . pinned } ) } >
248+ { conversation . pinned ? < PinOff /> : < Pin /> } { conversation . pinned ? "Unpin" : "Pin" }
242249 </ DropdownMenuItem >
243- ) }
244- < DropdownMenuSeparator />
245- < DropdownMenuItem variant = "destructive" onClick = { ( ) => setConfirmDelete ( true ) } >
246- < Trash2 /> Delete
247- </ DropdownMenuItem >
248- </ DropdownMenuContent >
249- </ DropdownMenu >
250+ < DropdownMenuItem onClick = { ( ) => setArchived ( conversation , ! conversation . archived ) } >
251+ { conversation . archived ? < ArchiveRestore /> : < Archive /> } { conversation . archived ? "Unarchive" : "Archive" }
252+ </ DropdownMenuItem >
253+ { move && (
254+ < DropdownMenuItem disabled = { ! ! move . blocked } title = { move . blocked ?? undefined } onClick = { move . onSelect } >
255+ < Laptop /> { move . label ?? `Move to ${ THIS_COMPUTER_INLINE } ` }
256+ </ DropdownMenuItem >
257+ ) }
258+ < DropdownMenuSeparator />
259+ < DropdownMenuItem variant = "destructive" onClick = { ( ) => setConfirmDelete ( true ) } >
260+ < Trash2 /> Delete
261+ </ DropdownMenuItem >
262+ </ DropdownMenuContent >
263+ </ DropdownMenu >
264+ ) }
250265 </ div >
251266
252267 < DeleteChatDialog
0 commit comments