"use client"; import type { RefObject } from "react"; import { ContextMenuContent, ContextMenuItem, ContextMenuSeparator } from "@kandev/ui/context-menu"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@kandev/ui/alert-dialog"; import { ActionConfirmPopover } from "@/components/confirmation/action-confirm-popover"; import { isSessionStoppable as isStoppable, isSessionDeletable as isDeletable, isSessionResumable as isResumable, } from "@/hooks/domains/session/use-session-actions"; import { ShareDialog } from "@/components/task/share/share-dialog"; import { HandoffContextMenuSub } from "@/components/task/handoff-profile-menu-items"; import { NewSessionDialog, type HandoffPreset } from "@/components/task/new-session-dialog"; import type { TaskSessionState } from "@/lib/types/http"; import { useTranslation } from "react-i18next"; import { SessionDeleteDescription } from "./session-delete-description"; /** Lifecycle callbacks the context menu needs from the owning tab. * `handleCloseOthers` is dockview-specific (closing sibling panels) and has * no equivalent where tabs are a plain session switcher, so it's optional — * omitting it hides the Close Others item entirely. */ export type SessionTabMenuActions = { handleSetPrimary: () => void; handleStop: () => void; handleResume: () => void; handleCloseOthers?: () => void; }; export function DeleteSessionDialog({ open, onOpenChange, isPrimary, sessionCount, onConfirm, }: { open: boolean; onOpenChange: (open: boolean) => void; isPrimary: boolean; sessionCount: number; onConfirm: () => void; }) { const { t } = useTranslation(); return ( {t("task:deleteSession")}
{t("common:cancel")} { onOpenChange(false); onConfirm(); }} className="cursor-pointer bg-destructive text-destructive-foreground hover:bg-destructive/90" > {t("task:delete")}
); } export function DeleteSessionPopover({ open, anchorRef, focusBoundaryRef, onOpenChange, isPrimary, sessionCount, targetName, onConfirm, }: { open: boolean; anchorRef: RefObject; focusBoundaryRef?: RefObject; onOpenChange: (open: boolean) => void; isPrimary: boolean; sessionCount: number; targetName?: string | null; onConfirm: () => void | Promise; }) { const { t } = useTranslation(); const name = targetName || t("task:session"); return ( } cancelLabel={t("common:cancel")} confirmLabel={t("task:delete")} confirmAriaLabel={t("task:delete2", { name })} confirmTestId="session-delete-confirm" testId="session-delete-confirm-popover" onOpenChange={onOpenChange} onConfirm={onConfirm} /> ); } export function SessionContextMenuItems({ sessionState, isPrimary, canShare, taskId, sessionId, actions, onDelete, onShare, onHandoffProfile, onStartRename, }: { sessionState: TaskSessionState | null; isPrimary: boolean; canShare: boolean; taskId: string | null; sessionId: string | undefined; actions: SessionTabMenuActions; /** Passes the Radix selection event so the owner can capture its currentTarget as an anchor. */ onDelete: (event: Event) => void; onShare: () => void; onHandoffProfile: (profileId: string) => void; onStartRename: () => void; }) { const { t } = useTranslation(); return ( {t("task:rename2")} {t("task:setAsPrimary")} {sessionState && isStoppable(sessionState) && ( {t("task:stop")} )} {sessionState && isResumable(sessionState) && ( {t("task:resume")} )} {sessionState && isDeletable(sessionState) && ( { // Keep the context menu mounted so the confirmation popover can stay anchored here. event.preventDefault(); onDelete(event); }} > {t("task:delete")} )} {canShare && ( <> {t("task:share")} )} {taskId && sessionId && ( <> )} {actions.handleCloseOthers && ( <> {t("task:closeOthers")} )} ); } /** Delete / share / handoff dialogs rendered alongside the tab. */ export function SessionTabDialogs({ confirmDelete, menuDeleteOpen, menuDeleteAnchorRef, menuDeleteFocusBoundaryRef, setConfirmDelete, isPrimary, sessionCount, onConfirmDelete, targetName, taskId, sessionId, shareOpen, setShareOpen, handoffOpen, setHandoffOpen, handoffPreset, setHandoffPreset, groupId, }: { confirmDelete: boolean; menuDeleteOpen: boolean; menuDeleteAnchorRef: RefObject; menuDeleteFocusBoundaryRef?: RefObject; setConfirmDelete: (open: boolean) => void; isPrimary: boolean; sessionCount: number; onConfirmDelete: () => void; targetName?: string | null; taskId: string | null; sessionId: string | undefined; shareOpen: boolean; setShareOpen: (open: boolean) => void; handoffOpen: boolean; setHandoffOpen: (open: boolean) => void; handoffPreset: HandoffPreset | null; setHandoffPreset: (preset: HandoffPreset | null) => void; groupId: string | undefined; }) { return ( <> {taskId && sessionId && ( )} {taskId && handoffPreset && ( { setHandoffOpen(open); if (!open) setHandoffPreset(null); }} taskId={taskId} groupId={groupId} handoff={handoffPreset} /> )} ); }