feat(SessionItem): add confirmation for session deletion with keyboard shortcut

Add a confirmation step before deleting a session, including a tooltip showing the keyboard shortcut. Uses a timer to automatically cancel the confirmation after 3 seconds.
This commit is contained in:
icarus 2025-09-27 14:17:43 +08:00
parent f429e3fc01
commit 8b0e8506c2

View File

@ -1,14 +1,17 @@
import { Button, cn, Input } from '@heroui/react'
import { Button, cn, Input, PressEvent, Tooltip } from '@heroui/react'
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
import { isMac } from '@renderer/config/constant'
import { useUpdateSession } from '@renderer/hooks/agents/useUpdateSession'
import { useInPlaceEdit } from '@renderer/hooks/useInPlaceEdit'
import { useRuntime } from '@renderer/hooks/useRuntime'
import { useSettings } from '@renderer/hooks/useSettings'
import { useTimer } from '@renderer/hooks/useTimer'
import { SessionSettingsPopup } from '@renderer/pages/settings/AgentSettings'
import { SessionLabel } from '@renderer/pages/settings/AgentSettings/shared'
import { AgentSessionEntity } from '@renderer/types'
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from '@renderer/ui/context-menu'
import { FC, memo } from 'react'
import { XIcon } from 'lucide-react'
import { FC, memo, startTransition, useState } from 'react'
import { useTranslation } from 'react-i18next'
// const logger = loggerService.withContext('AgentItem')
@ -28,6 +31,8 @@ const SessionItem: FC<SessionItemProps> = ({ session, agentId, isDisabled, isLoa
const { chat } = useRuntime()
const updateSession = useUpdateSession(agentId)
const activeSessionId = chat.activeSessionId[agentId]
const [isConfirmingDeletion, setIsConfirmingDeletion] = useState(false)
const { setTimeoutTimer } = useTimer()
const { isEditing, isSaving, editValue, inputRef, startEdit, handleKeyDown, handleValueChange } = useInPlaceEdit({
onSave: async (value) => {
@ -48,7 +53,8 @@ const SessionItem: FC<SessionItemProps> = ({ session, agentId, isDisabled, isLoa
isLoading={isLoading}
onPress={onPress}
isActive={isActive}
onDoubleClick={() => startEdit(session.name ?? '')}>
onDoubleClick={() => startEdit(session.name ?? '')}
className="group">
<SessionLabelContainer className="name h-full w-full" title={session.name ?? session.id}>
{isEditing && (
<Input
@ -66,7 +72,53 @@ const SessionItem: FC<SessionItemProps> = ({ session, agentId, isDisabled, isLoa
}}
/>
)}
{!isEditing && <SessionLabel session={session} />}
{!isEditing && (
<div className="flex w-full items-center justify-between">
<SessionLabel session={session} />
<Tooltip
content={t('chat.topics.delete.shortcut', { key: isMac ? '⌘' : 'Ctrl' })}
classNames={{ content: 'text-xs' }}>
<Button
className="mr-2 aspect-square h-6 w-6 min-w-6"
variant="light"
startContent={
isConfirmingDeletion ? (
<DeleteIcon
size={14}
className="opacity-0 transition-colors-opacity group-hover:text-danger group-hover:opacity-100"
/>
) : (
<XIcon
size={14}
className={cn(
isActive ? 'opacity-100' : 'opacity-0',
'group-hover:opacity-100',
'transition-opacity'
)}
/>
)
}
onPress={(e: PressEvent) => {
if (isConfirmingDeletion || e.ctrlKey || e.metaKey) {
onDelete()
} else {
startTransition(() => {
setIsConfirmingDeletion(true)
setTimeoutTimer(
'confirmDeletion',
() => {
setIsConfirmingDeletion(false)
},
3000
)
})
}
}}
isIconOnly
/>
</Tooltip>
</div>
)}
</SessionLabelContainer>
</ButtonContainer>
</ContextMenuTrigger>