Fix closing animation

This commit is contained in:
2025-09-04 21:27:01 +03:00
Unverified
parent b6542328de
commit 3194379eb1
2 changed files with 21 additions and 20 deletions
@@ -23,11 +23,12 @@ export function ChatMessages() {
message: null, message: null,
position: { x: 0, y: 0 } position: { x: 0, y: 0 }
}); });
const [isContextMenuClosing, setIsContextMenuClosing] = useState(false);
// Effect to handle clicks outside the context menu // Effect to handle clicks outside the context menu
useEffect(() => { useEffect(() => {
const handleClickOutside = (event: MouseEvent) => { const handleClickOutside = (event: MouseEvent) => {
if (contextMenu.isOpen) { if (contextMenu.isOpen && !isContextMenuClosing) {
// Check if the click is on a context menu element // Check if the click is on a context menu element
const target = event.target as Element; const target = event.target as Element;
if (!target.closest('.context-menu')) { if (!target.closest('.context-menu')) {
@@ -37,14 +38,14 @@ export function ChatMessages() {
}; };
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape' && contextMenu.isOpen) { if (event.key === 'Escape' && contextMenu.isOpen && !isContextMenuClosing) {
handleContextMenuClose(); handleContextMenuClose();
} }
}; };
const handleWindowBlur = () => { const handleWindowBlur = () => {
// Close context menu when browser window loses focus // Close context menu when browser window loses focus
if (contextMenu.isOpen) { if (contextMenu.isOpen && !isContextMenuClosing) {
handleContextMenuClose(); handleContextMenuClose();
} }
}; };
@@ -60,7 +61,7 @@ export function ChatMessages() {
document.removeEventListener('keydown', handleKeyDown); document.removeEventListener('keydown', handleKeyDown);
window.removeEventListener('blur', handleWindowBlur); window.removeEventListener('blur', handleWindowBlur);
}; };
}, [contextMenu.isOpen]); }, [contextMenu.isOpen, isContextMenuClosing]);
const handleProfileClick = async (username: string) => { const handleProfileClick = async (username: string) => {
if (!user.authToken) return; if (!user.authToken) return;
@@ -82,6 +83,7 @@ export function ChatMessages() {
const handleContextMenu = (e: React.MouseEvent, message: MessageType) => { const handleContextMenu = (e: React.MouseEvent, message: MessageType) => {
e.preventDefault(); e.preventDefault();
console.log("Context menu triggered for message:", message.id, "at position:", e.clientX, e.clientY); console.log("Context menu triggered for message:", message.id, "at position:", e.clientX, e.clientY);
setIsContextMenuClosing(false);
setContextMenu({ setContextMenu({
isOpen: true, isOpen: true,
message, message,
@@ -90,11 +92,16 @@ export function ChatMessages() {
}; };
const handleContextMenuClose = () => { const handleContextMenuClose = () => {
setIsContextMenuClosing(true);
// Wait for animation to complete before removing from DOM
setTimeout(() => {
setContextMenu({ setContextMenu({
isOpen: false, isOpen: false,
message: null, message: null,
position: { x: 0, y: 0 } position: { x: 0, y: 0 }
}); });
setIsContextMenuClosing(false);
}, 200); // Match the animation duration from _animations.scss
}; };
const handleEdit = async (message: MessageType) => { const handleEdit = async (message: MessageType) => {
@@ -193,6 +200,7 @@ export function ChatMessages() {
onDelete={handleDelete} onDelete={handleDelete}
onClose={handleContextMenuClose} onClose={handleContextMenuClose}
position={contextMenu.position} position={contextMenu.position}
isClosing={isContextMenuClosing}
/> />
)} )}
</> </>
@@ -11,6 +11,7 @@ interface MessageContextMenuProps {
onDelete: (message: Message) => void; onDelete: (message: Message) => void;
onClose: () => void; onClose: () => void;
position: { x: number; y: number }; position: { x: number; y: number };
isClosing: boolean;
} }
export interface ContextMenuState { export interface ContextMenuState {
@@ -26,14 +27,14 @@ export function MessageContextMenu({
onReply, onReply,
onDelete, onDelete,
onClose, onClose,
position position,
isClosing
}: MessageContextMenuProps) { }: MessageContextMenuProps) {
console.log("MessageContextMenu rendered with position:", position, "message:", message.id); console.log("MessageContextMenu rendered with position:", position, "message:", message.id);
// Internal state for dialogs // Internal state for dialogs
const [editDialogOpen, setEditDialogOpen] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false);
const [replyDialogOpen, setReplyDialogOpen] = useState(false); const [replyDialogOpen, setReplyDialogOpen] = useState(false);
const [isClosing, setIsClosing] = useState(false);
const handleAction = (action: string) => { const handleAction = (action: string) => {
console.log("Context menu action triggered:", action); console.log("Context menu action triggered:", action);
@@ -49,20 +50,12 @@ export function MessageContextMenu({
case "delete": case "delete":
if (isAuthor) { if (isAuthor) {
onDelete(message); onDelete(message);
handleClose(); onClose();
} }
break; break;
} }
}; };
const handleClose = () => {
setIsClosing(true);
// Wait for animation to complete before calling onClose
setTimeout(() => {
onClose();
}, 200); // Match the animation duration from _animations.scss
};
const handleEditSave = (messageId: number, newContent: string) => { const handleEditSave = (messageId: number, newContent: string) => {
// Create a temporary message object with the updated content // Create a temporary message object with the updated content
const updatedMessage = { ...message, content: newContent }; const updatedMessage = { ...message, content: newContent };