Improve animation

This commit is contained in:
2025-09-04 21:25:38 +03:00
Unverified
parent 68ac96c1e4
commit b6542328de
3 changed files with 59 additions and 16 deletions
@@ -6,12 +6,10 @@ import type { UserProfile } from "../../../core/types";
import { UserProfileDialog } from "./UserProfileDialog";
import { MessageContextMenu, type ContextMenuState } from "./MessageContextMenu";
import { fetchUserProfile } from "../../api/profileApi";
import { useState } from "react";
import { useState, useEffect } from "react";
import { delay } from "../../../utils/utils";
import { request } from "../../../websocket";
export function ChatMessages() {
const { messages } = useChat();
const { user } = useAppState();
@@ -26,6 +24,44 @@ export function ChatMessages() {
position: { x: 0, y: 0 }
});
// Effect to handle clicks outside the context menu
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (contextMenu.isOpen) {
// Check if the click is on a context menu element
const target = event.target as Element;
if (!target.closest('.context-menu')) {
handleContextMenuClose();
}
}
};
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape' && contextMenu.isOpen) {
handleContextMenuClose();
}
};
const handleWindowBlur = () => {
// Close context menu when browser window loses focus
if (contextMenu.isOpen) {
handleContextMenuClose();
}
};
// Add event listeners
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('keydown', handleKeyDown);
window.addEventListener('blur', handleWindowBlur);
// Cleanup
return () => {
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('keydown', handleKeyDown);
window.removeEventListener('blur', handleWindowBlur);
};
}, [contextMenu.isOpen]);
const handleProfileClick = async (username: string) => {
if (!user.authToken) return;
@@ -120,19 +156,9 @@ export function ChatMessages() {
}
};
// Close context menu when clicking outside
const handleClickOutside = (e: React.MouseEvent) => {
if (contextMenu.isOpen) {
// Only close if clicking on the chat messages container, not on the context menu itself
if (e.target === e.currentTarget) {
handleContextMenuClose();
}
}
};
return (
<>
<div className="chat-messages" id="chat-messages" onClick={handleClickOutside}>
<div className="chat-messages" id="chat-messages">
{messages.map((message) => (
<Message
key={message.id}
@@ -33,6 +33,7 @@ export function MessageContextMenu({
// Internal state for dialogs
const [editDialogOpen, setEditDialogOpen] = useState(false);
const [replyDialogOpen, setReplyDialogOpen] = useState(false);
const [isClosing, setIsClosing] = useState(false);
const handleAction = (action: string) => {
console.log("Context menu action triggered:", action);
@@ -48,12 +49,20 @@ export function MessageContextMenu({
case "delete":
if (isAuthor) {
onDelete(message);
onClose();
handleClose();
}
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) => {
// Create a temporary message object with the updated content
const updatedMessage = { ...message, content: newContent };
@@ -71,7 +80,7 @@ export function MessageContextMenu({
return (
<>
<div
className="context-menu"
className={`context-menu ${isClosing ? 'closing' : 'entering'}`}
style={{
position: "fixed",
display: "block",