diff --git a/web/app/components/workflow/comment/thread.tsx b/web/app/components/workflow/comment/thread.tsx index a717482b67..f900d05e15 100644 --- a/web/app/components/workflow/comment/thread.tsx +++ b/web/app/components/workflow/comment/thread.tsx @@ -8,6 +8,7 @@ import { RiArrowDownSLine, RiArrowUpSLine, RiCheckboxCircleFill, RiCheckboxCircl import Avatar from '@/app/components/base/avatar' import Divider from '@/app/components/base/divider' import Tooltip from '@/app/components/base/tooltip' +import InlineDeleteConfirm from '@/app/components/base/inline-delete-confirm' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem' import cn from '@/utils/classnames' import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now' @@ -31,6 +32,7 @@ type CommentThreadProps = { onReply?: (content: string, mentionedUserIds?: string[]) => Promise | void onReplyEdit?: (replyId: string, content: string, mentionedUserIds?: string[]) => Promise | void onReplyDelete?: (replyId: string) => void + onReplyDeleteDirect?: (replyId: string) => Promise | void } const ThreadMessage: FC<{ @@ -150,6 +152,7 @@ export const CommentThread: FC = memo(({ onReply, onReplyEdit, onReplyDelete, + onReplyDeleteDirect, }) => { const { flowToScreenPosition } = useReactFlow() const viewport = useViewport() @@ -158,6 +161,7 @@ export const CommentThread: FC = memo(({ const [replyContent, setReplyContent] = useState('') const [activeReplyMenuId, setActiveReplyMenuId] = useState(null) const [editingReply, setEditingReply] = useState<{ id: string; content: string }>({ id: '', content: '' }) + const [deletingReplyId, setDeletingReplyId] = useState(null) useEffect(() => { setReplyContent('') @@ -372,6 +376,9 @@ export const CommentThread: FC = memo(({ placement='bottom-end' open={activeReplyMenuId === reply.id} onOpenChange={(open) => { + // Don't allow closing if we're showing delete confirm + if (!open && deletingReplyId === reply.id) + return if (!open) setActiveReplyMenuId(null) }} @@ -389,6 +396,7 @@ export const CommentThread: FC = memo(({ className='flex h-6 w-6 items-center justify-center rounded-md text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary' onClick={(e) => { e.stopPropagation() + setDeletingReplyId(null) setActiveReplyMenuId(prev => prev === reply.id ? null : reply.id) }} aria-label={t('workflow.comments.aria.replyActions')} @@ -401,21 +409,48 @@ export const CommentThread: FC = memo(({ className='z-[100] w-36 rounded-xl border border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[10px]' data-reply-menu > - - + {deletingReplyId === reply.id ? ( + { + setDeletingReplyId(null) + setActiveReplyMenuId(null) + onReplyDeleteDirect?.(reply.id) + }} + onCancel={() => { + setDeletingReplyId(null) + setActiveReplyMenuId(null) + }} + className='m-0 w-full border-0 shadow-none' + /> + ) : ( + <> + + + + )} )} diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index e078b41b48..188c11cd20 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -480,6 +480,7 @@ export const Workflow: FC = memo(({ onReply={(content, ids) => handleCommentReply(comment.id, content, ids ?? [])} onReplyEdit={(replyId, content, ids) => handleCommentReplyUpdate(comment.id, replyId, content, ids ?? [])} onReplyDelete={replyId => handleCommentReplyDeleteClick(comment.id, replyId)} + onReplyDeleteDirect={replyId => handleCommentReplyDelete(comment.id, replyId)} canGoPrev={canGoPrev} canGoNext={canGoNext} />