diff --git a/packages/web/src/components/chat/Message.tsx b/packages/web/src/components/chat/Message.tsx index 76e30502..0d369611 100644 --- a/packages/web/src/components/chat/Message.tsx +++ b/packages/web/src/components/chat/Message.tsx @@ -51,7 +51,9 @@ export function Message({ message, isCompact, isFirstInGroup }: MessageProps) { const [isEditing, setIsEditing] = useState(false); const [editContent, setEditContent] = useState(message.content ?? ''); const [isHovered, setIsHovered] = useState(false); + const [confirmingDelete, setConfirmingDelete] = useState(false); const [showReactionPicker, setShowReactionPicker] = useState(false); + const confirmDeleteTimeout = useRef>(); const reactionPickerBtnRef = useRef(null); const reactionPickerRef = useRef(null); const currentUser = useAuthStore((s) => s.user); @@ -96,9 +98,23 @@ export function Message({ message, isCompact, isFirstInGroup }: MessageProps) { return acc; }, {} as Record); + // Auto-cancel delete confirmation after timeout + const startDeleteConfirm = useCallback(() => { + setConfirmingDelete(true); + clearTimeout(confirmDeleteTimeout.current); + confirmDeleteTimeout.current = setTimeout(() => setConfirmingDelete(false), 3000); + }, []); + + const cancelDeleteConfirm = useCallback(() => { + setConfirmingDelete(false); + clearTimeout(confirmDeleteTimeout.current); + }, []); + + useEffect(() => { + return () => clearTimeout(confirmDeleteTimeout.current); + }, []); + const isGifOnly = isGifOnlyMessage(message.content); - const isSticker = !!(message.stickerId || (message as any).sticker); - const stickerData = (message as any).sticker ?? null; const urlRegex = /(https?:\/\/[^\s]+)/g; const firstUrl = isGifOnly ? null : message.content?.match(urlRegex)?.[0]; @@ -206,7 +222,13 @@ export function Message({ message, isCompact, isFirstInGroup }: MessageProps) { : 'hover:bg-[rgba(255,255,255,0.025)]' }`} onMouseEnter={() => setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} + onMouseLeave={() => { + setIsHovered(false); + if (confirmingDelete) { + clearTimeout(confirmDeleteTimeout.current); + confirmDeleteTimeout.current = setTimeout(() => setConfirmingDelete(false), 2000); + } + }} > {/* Reply Line */} {message.replyTo && ( @@ -289,19 +311,7 @@ export function Message({ message, isCompact, isFirstInGroup }: MessageProps) { ) : (
- {/* Sticker rendering */} - {isSticker && stickerData ? ( -
- {stickerData.name} -
- ) : isSticker ? ( -
Sticker unavailable
- ) : isGifOnly ? ( + {isGifOnly ? (
{canAddReactions && (
@@ -469,13 +479,39 @@ export function Message({ message, isCompact, isFirstInGroup }: MessageProps) { )} {canDelete && ( )}