Implement chat switching animation

This commit is contained in:
2025-09-05 20:07:16 +03:00
Unverified
parent 19f92115bb
commit 98b5e34438
5 changed files with 41 additions and 29 deletions
@@ -1,13 +0,0 @@
import { ChatMainHeader } from "./ChatMainHeader";
import { ChatMessages } from "./ChatMessages";
import { ChatInputWrapper } from "./ChatInputWrapper";
export function ChatMain() {
return (
<div className="chat-main" id="chat-inner">
<ChatMainHeader />
<ChatMessages />
<ChatInputWrapper />
</div>
);
}
@@ -1,15 +1,8 @@
import { useChat } from "../../hooks/useChat"; import { useChat } from "../../hooks/useChat";
import { useState } from "react";
import defaultAvatar from "../../../resources/images/default-avatar.png"; import defaultAvatar from "../../../resources/images/default-avatar.png";
export function ChatMainHeader() { export function ChatMainHeader() {
const { currentChat } = useChat(); const { currentChat } = useChat();
const [isCollapsed, setIsCollapsed] = useState(false);
const handleCollapse = () => {
setIsCollapsed(!isCollapsed);
// TODO: Implement chat collapse animation
};
return ( return (
<div className="chat-header"> <div className="chat-header">
@@ -22,7 +15,6 @@ export function ChatMainHeader() {
Онлайн Онлайн
</p> </p>
</div> </div>
<a href="#" id="hide-chat" onClick={handleCollapse}>Свернуть чат</a>
</div> </div>
</div> </div>
); );
+12 -3
View File
@@ -1,9 +1,18 @@
import { ChatMain } from "./ChatMain"; import { useChat } from "../../hooks/useChat";
import { ChatInputWrapper } from "./ChatInputWrapper";
import { ChatMainHeader } from "./ChatMainHeader";
import { ChatMessages } from "./ChatMessages";
export function RightPanel() { export function RightPanel() {
const { isChatSwitching } = useChat();
return ( return (
<div className="chat-container"> <div className={`chat-container ${!isChatSwitching && "chat-switch-in"} chat-switch-out`}>
<ChatMain /> <div className="chat-main" id="chat-inner">
<ChatMainHeader />
<ChatMessages />
<ChatInputWrapper />
</div>
</div> </div>
); );
} }
+12 -3
View File
@@ -4,6 +4,7 @@ import { request, websocket } from "../../websocket";
import { API_BASE_URL } from "../../core/config"; import { API_BASE_URL } from "../../core/config";
import type { Message, WebSocketMessage } from "../../core/types"; import type { Message, WebSocketMessage } from "../../core/types";
import { getAuthHeaders } from "../../auth/api"; import { getAuthHeaders } from "../../auth/api";
import { delay } from "../../utils/utils";
export function useChat() { export function useChat() {
const { const {
@@ -16,6 +17,7 @@ export function useChat() {
setActiveTab, setActiveTab,
setDmUsers, setDmUsers,
setActiveDm, setActiveDm,
setIsChatSwitching,
user user
} = useAppState(); } = useAppState();
@@ -112,9 +114,14 @@ export function useChat() {
// Reset messages loaded flag and clear messages when chat changes // Reset messages loaded flag and clear messages when chat changes
useEffect(() => { useEffect(() => {
messagesLoadedRef.current = false; (async () => {
clearMessages(); // Clear messages when switching chats setIsChatSwitching(true);
loadMessages(); await delay(250);
messagesLoadedRef.current = false;
clearMessages(); // Clear messages when switching chats
loadMessages();
setIsChatSwitching(false);
})();
}, [chat.currentChat, clearMessages]); }, [chat.currentChat, clearMessages]);
return { return {
@@ -123,6 +130,8 @@ export function useChat() {
activeTab: chat.activeTab, activeTab: chat.activeTab,
dmUsers: chat.dmUsers, dmUsers: chat.dmUsers,
activeDm: chat.activeDm, activeDm: chat.activeDm,
isChatSwitching: chat.isChatSwitching,
setIsChatSwitching,
sendMessage, sendMessage,
updateMessage, updateMessage,
removeMessage, removeMessage,
+17 -2
View File
@@ -4,12 +4,19 @@ import { request } from "../websocket";
type Page = "login" | "register" | "chat" type Page = "login" | "register" | "chat"
interface ActiveDM {
userId: number;
username: string;
publicKey: string | null
}
interface ChatState { interface ChatState {
messages: Message[]; messages: Message[];
currentChat: string; currentChat: string;
activeTab: "chats" | "channels" | "contacts" | "dms"; activeTab: "chats" | "channels" | "contacts" | "dms";
dmUsers: User[]; dmUsers: User[];
activeDm: { userId: number; username: string; publicKey: string | null } | null; activeDm: ActiveDM | null;
isChatSwitching: boolean;
} }
interface UserState { interface UserState {
@@ -31,6 +38,7 @@ interface AppState {
setDmUsers: (users: User[]) => void; setDmUsers: (users: User[]) => void;
setActiveDm: (dm: ChatState["activeDm"]) => void; setActiveDm: (dm: ChatState["activeDm"]) => void;
clearMessages: () => void; clearMessages: () => void;
setIsChatSwitching: (value: boolean) => void;
// User state // User state
user: UserState; user: UserState;
@@ -48,8 +56,15 @@ export const useAppState = create<AppState>((set, get) => ({
currentChat: "Общий чат", currentChat: "Общий чат",
activeTab: "chats", activeTab: "chats",
dmUsers: [], dmUsers: [],
activeDm: null activeDm: null,
isChatSwitching: false
}, },
setIsChatSwitching: (value: boolean) => set((state) => ({
chat: {
...state.chat,
isChatSwitching: value
}
})),
addMessage: (message: Message) => set((state) => { addMessage: (message: Message) => set((state) => {
// Check if message already exists to prevent duplicates // Check if message already exists to prevent duplicates
const messageExists = state.chat.messages.some(msg => msg.id === message.id); const messageExists = state.chat.messages.some(msg => msg.id === message.id);