AeThex-Connect/packages/core/state/slices/callsSlice.ts

113 lines
2.6 KiB
TypeScript

/**
* Calls State Slice
* Manages voice and video calls
*/
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
export interface Call {
id: string;
type: 'voice' | 'video';
participants: string[];
initiatorId: string;
status: 'ringing' | 'active' | 'ended' | 'declined' | 'missed';
startedAt?: string;
endedAt?: string;
}
export interface VoiceState {
muted: boolean;
deafened: boolean;
speaking: boolean;
volume: number;
}
interface CallsState {
activeCall: Call | null;
incomingCall: Call | null;
callHistory: Call[];
voiceState: VoiceState;
error: string | null;
}
const initialState: CallsState = {
activeCall: null,
incomingCall: null,
callHistory: [],
voiceState: {
muted: false,
deafened: false,
speaking: false,
volume: 100,
},
error: null,
};
const callsSlice = createSlice({
name: 'calls',
initialState,
reducers: {
setActiveCall: (state, action: PayloadAction<Call>) => {
state.activeCall = action.payload;
state.incomingCall = null;
},
setIncomingCall: (state, action: PayloadAction<Call>) => {
state.incomingCall = action.payload;
},
endCall: (state) => {
if (state.activeCall) {
const endedCall = {
...state.activeCall,
status: 'ended' as const,
endedAt: new Date().toISOString(),
};
state.callHistory.unshift(endedCall);
state.activeCall = null;
}
},
declineCall: (state) => {
if (state.incomingCall) {
const declinedCall = {
...state.incomingCall,
status: 'declined' as const,
endedAt: new Date().toISOString(),
};
state.callHistory.unshift(declinedCall);
state.incomingCall = null;
}
},
setMuted: (state, action: PayloadAction<boolean>) => {
state.voiceState.muted = action.payload;
},
setDeafened: (state, action: PayloadAction<boolean>) => {
state.voiceState.deafened = action.payload;
// Deafening also mutes
if (action.payload) {
state.voiceState.muted = true;
}
},
setSpeaking: (state, action: PayloadAction<boolean>) => {
state.voiceState.speaking = action.payload;
},
setVolume: (state, action: PayloadAction<number>) => {
state.voiceState.volume = Math.max(0, Math.min(100, action.payload));
},
clearError: (state) => {
state.error = null;
},
},
});
export const {
setActiveCall,
setIncomingCall,
endCall,
declineCall,
setMuted,
setDeafened,
setSpeaking,
setVolume,
clearError,
} = callsSlice.actions;
export default callsSlice.reducer;