mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
227 lines
6.9 KiB
TypeScript
227 lines
6.9 KiB
TypeScript
import type { StateCreator } from "zustand";
|
|
import type { Message, User } from "@/core/types";
|
|
import { MessagePanel } from "../ui/right/panels/MessagePanel";
|
|
import { PublicChatPanel } from "../ui/right/panels/PublicChatPanel";
|
|
import { DMPanel, type DMPanelData } from "../ui/right/panels/DMPanel";
|
|
import type { ChatState, ChatTabs, ActiveDM } from "./types";
|
|
import { useUserStore } from "@/state/user";
|
|
|
|
export interface ChatStateSlice {
|
|
chat: ChatState;
|
|
addMessage: (message: Message) => void;
|
|
updateMessage: (messageId: number, updatedMessage: Partial<Message>) => void;
|
|
removeMessage: (messageId: number) => void;
|
|
setCurrentChat: (chat: string) => void;
|
|
setActiveTab: (tab: ChatTabs) => void;
|
|
setDmUsers: (users: User[]) => void;
|
|
setActiveDm: (dm: ActiveDM | null) => void;
|
|
clearMessages: () => void;
|
|
setActivePanel: (panel: MessagePanel | null) => void;
|
|
setPendingPanel: (panel: MessagePanel | null) => void;
|
|
applyPendingPanel: () => void;
|
|
switchToPublicChat: (chatName: string) => Promise<void>;
|
|
switchToDM: (dmData: DMPanelData) => Promise<void>;
|
|
}
|
|
|
|
export const createChatState: StateCreator<
|
|
ChatStateSlice & { user: { authToken: string | null } },
|
|
[],
|
|
[],
|
|
ChatStateSlice
|
|
> = (set, get) => ({
|
|
chat: {
|
|
messages: [],
|
|
currentChat: "Общий чат",
|
|
activeTab: "chats",
|
|
dmUsers: [],
|
|
activeDm: null,
|
|
isSwitching: false,
|
|
setIsSwitching: (value: boolean) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
isSwitching: value
|
|
}
|
|
})),
|
|
activePanel: null,
|
|
publicChatPanel: null,
|
|
dmPanel: null,
|
|
pendingPanel: null,
|
|
profileDialog: null,
|
|
call: {
|
|
isActive: false,
|
|
status: "ended",
|
|
startTime: null,
|
|
isMuted: false,
|
|
remoteUserId: null,
|
|
remoteUsername: null,
|
|
isInitiator: false,
|
|
isMinimized: false,
|
|
sessionKeyHash: null,
|
|
encryptionEmojis: [],
|
|
isVideoEnabled: false,
|
|
isRemoteVideoEnabled: false,
|
|
isSharingScreen: false,
|
|
isRemoteScreenSharing: false
|
|
},
|
|
onlineStatuses: new Map(),
|
|
typingUsers: new Map(),
|
|
dmTypingUsers: new Map()
|
|
},
|
|
addMessage: (message: Message) => set((state) => {
|
|
const messageExists = state.chat.messages.some(msg => msg.id === message.id);
|
|
if (messageExists) {
|
|
return state;
|
|
}
|
|
|
|
return {
|
|
chat: {
|
|
...state.chat,
|
|
messages: [...state.chat.messages, message]
|
|
}
|
|
};
|
|
}),
|
|
updateMessage: (messageId: number, updatedMessage: Partial<Message>) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
messages: state.chat.messages.map(msg =>
|
|
msg.id === messageId ? { ...msg, ...updatedMessage } : msg
|
|
)
|
|
}
|
|
})),
|
|
removeMessage: (messageId: number) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
messages: state.chat.messages.filter(msg => msg.id !== messageId)
|
|
}
|
|
})),
|
|
clearMessages: () => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
messages: []
|
|
}
|
|
})),
|
|
setCurrentChat: (chat: string) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
currentChat: chat
|
|
}
|
|
})),
|
|
setActiveTab: (tab: ChatTabs) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
activeTab: tab
|
|
}
|
|
})),
|
|
setDmUsers: (users: User[]) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
dmUsers: users
|
|
}
|
|
})),
|
|
setActiveDm: (dm: ActiveDM | null) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
activeDm: dm
|
|
}
|
|
})),
|
|
setActivePanel: (panel: MessagePanel | null) => {
|
|
const state = get();
|
|
if (state.chat.activePanel && state.chat.activePanel !== panel) {
|
|
state.chat.activePanel.deactivate();
|
|
}
|
|
return set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
activePanel: panel
|
|
}
|
|
}));
|
|
},
|
|
setPendingPanel: (panel: MessagePanel | null) => set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
pendingPanel: panel
|
|
}
|
|
})),
|
|
applyPendingPanel: () => {
|
|
const state = get();
|
|
if (state.chat.activePanel) {
|
|
state.chat.activePanel.deactivate();
|
|
}
|
|
return set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
activePanel: state.chat.pendingPanel || state.chat.activePanel,
|
|
publicChatPanel: (state.chat.pendingPanel instanceof PublicChatPanel)
|
|
? (state.chat.pendingPanel as PublicChatPanel)
|
|
: state.chat.publicChatPanel,
|
|
dmPanel: (state.chat.pendingPanel instanceof DMPanel)
|
|
? (state.chat.pendingPanel as DMPanel)
|
|
: state.chat.dmPanel,
|
|
currentChat: state.chat.pendingPanel ? state.chat.pendingPanel.getState().title || state.chat.currentChat : state.chat.currentChat,
|
|
pendingPanel: null
|
|
}
|
|
}));
|
|
},
|
|
switchToPublicChat: async (chatName: string) => {
|
|
const { chat } = get();
|
|
const { user } = useUserStore();
|
|
|
|
if (!user.authToken) return;
|
|
|
|
chat.setIsSwitching(true);
|
|
|
|
let publicChatPanel = chat.publicChatPanel;
|
|
if (!publicChatPanel) {
|
|
publicChatPanel = new PublicChatPanel(chatName, user);
|
|
} else {
|
|
publicChatPanel.setChatName(chatName);
|
|
publicChatPanel.setAuthToken(user.authToken);
|
|
publicChatPanel.clearMessages();
|
|
}
|
|
|
|
await publicChatPanel.activate();
|
|
|
|
set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
pendingPanel: publicChatPanel,
|
|
activeTab: "chats"
|
|
}
|
|
}));
|
|
},
|
|
switchToDM: async (dmData: DMPanelData) => {
|
|
const { chat } = get();
|
|
const { user } = useUserStore();
|
|
|
|
if (!user.authToken) return;
|
|
|
|
chat.setIsSwitching(true);
|
|
|
|
let dmPanel = chat.dmPanel;
|
|
if (!dmPanel) {
|
|
dmPanel = new DMPanel(user);
|
|
} else {
|
|
dmPanel.setAuthToken(user.authToken);
|
|
dmPanel.clearMessages();
|
|
}
|
|
|
|
dmPanel.setDMData(dmData);
|
|
|
|
await dmPanel.activate();
|
|
|
|
set((state) => ({
|
|
chat: {
|
|
...state.chat,
|
|
pendingPanel: dmPanel,
|
|
activeDm: {
|
|
userId: dmData.userId,
|
|
username: dmData.username,
|
|
publicKey: dmData.publicKey
|
|
},
|
|
activeTab: "chats"
|
|
}
|
|
}));
|
|
}
|
|
});
|
|
|