Implement audio calls

This commit is contained in:
2025-09-21 19:09:39 +03:00
Unverified
parent 27902cf092
commit a853164b50
20 changed files with 1265 additions and 12 deletions
+99 -3
View File
@@ -10,7 +10,9 @@ import { API_BASE_URL } from "@/core/config";
import { initialize, subscribe, startElectronReceiver, isSupported } from "@/core/push-notifications/push-notifications";
import { isElectron } from "@/core/electron/electron";
export type ChatTabs = "chats" | "channels" | "contacts" | "dms"
export type ChatTabs = "chats" | "channels" | "contacts" | "dms";
export type CallStatus = "calling" | "connecting" | "active" | "ended";
interface ActiveDM {
userId: number;
@@ -18,6 +20,16 @@ interface ActiveDM {
publicKey: string | null
}
interface CallState {
isActive: boolean;
status: CallStatus;
startTime: number | null;
isMuted: boolean;
remoteUserId: number | null;
remoteUsername: string | null;
isInitiator: boolean;
}
interface ChatState {
messages: Message[];
currentChat: string;
@@ -30,6 +42,7 @@ interface ChatState {
publicChatPanel: PublicChatPanel | null;
dmPanel: DMPanel | null;
pendingPanel?: MessagePanel | null;
call: CallState;
}
export interface UserState {
@@ -54,6 +67,13 @@ interface AppState {
switchToPublicChat: (chatName: string) => Promise<void>;
switchToDM: (dmData: DMPanelData) => Promise<void>;
// Call state
startCall: (userId: number, username: string) => void;
endCall: () => void;
setCallStatus: (status: CallStatus) => void;
toggleMute: () => void;
receiveCall: (userId: number, username: string) => void;
// User state
user: UserState;
setUser: (token: string, user: User) => void;
@@ -79,7 +99,16 @@ export const useAppState = create<AppState>((set, get) => ({
activePanel: null,
publicChatPanel: null,
dmPanel: null,
pendingPanel: null
pendingPanel: null,
call: {
isActive: false,
status: "ended",
startTime: null,
isMuted: false,
remoteUserId: null,
remoteUsername: null,
isInitiator: false
}
},
addMessage: (message: Message) => set((state) => {
// Check if message already exists to prevent duplicates
@@ -358,5 +387,72 @@ export const useAppState = create<AppState>((set, get) => ({
// Let MessagePanelRenderer handle the animation timing completely
// It will set isChatSwitching to false when the fadeInDown animation completes
}
},
// Call state management
startCall: (userId: number, username: string) => set((state) => ({
chat: {
...state.chat,
call: {
isActive: true,
status: "calling",
startTime: null,
isMuted: false,
remoteUserId: userId,
remoteUsername: username,
isInitiator: true
}
}
})),
endCall: () => set((state) => ({
chat: {
...state.chat,
call: {
isActive: false,
status: "ended",
startTime: null,
isMuted: false,
remoteUserId: null,
remoteUsername: null,
isInitiator: false
}
}
})),
setCallStatus: (status: CallStatus) => set((state) => ({
chat: {
...state.chat,
call: {
...state.chat.call,
status,
startTime: status === "active" && !state.chat.call.startTime ? Date.now() : state.chat.call.startTime
}
}
})),
toggleMute: () => set((state) => ({
chat: {
...state.chat,
call: {
...state.chat.call,
isMuted: !state.chat.call.isMuted
}
}
})),
receiveCall: (userId: number, username: string) => set((state) => ({
chat: {
...state.chat,
call: {
isActive: true,
status: "calling",
startTime: null,
isMuted: false,
remoteUserId: userId,
remoteUsername: username,
isInitiator: false
}
}
}))
}));