client/packages/call/src/speakingState.ts
Alois b5ce3c554d
All checks were successful
/ build-web (push) Successful in 7m40s
/ build-desktop (linux) (push) Successful in 12m10s
/ build-mobile (push) Successful in 19m34s
/ release (push) Successful in 3m31s
(feat): improve mobile cal ui a bit
(feat): add popout for call ui on mobile
(fix): fix cache and profile avatar upload stuff
2026-07-31 22:17:08 +02:00

74 lines
2 KiB
TypeScript

import { create } from "zustand";
type SpeakingState = {
speakingParticipantIds: Set<number>;
lastSpeakingParticipantId: number | null;
micGated: boolean;
};
const useSpeakingState = create<SpeakingState>(() => ({
speakingParticipantIds: new Set(),
lastSpeakingParticipantId: null,
micGated: false,
}));
export function setMicGated(micGated: boolean) {
useSpeakingState.setState({ micGated });
}
export function clearSpeakingParticipants() {
useSpeakingState.setState({ speakingParticipantIds: new Set() });
}
export function removeSpeakingParticipant(participantId: number) {
useSpeakingState.setState((state) => {
const wasSpeaking = state.speakingParticipantIds.has(participantId);
const wasLastSpeaking = state.lastSpeakingParticipantId === participantId;
if (!wasSpeaking && !wasLastSpeaking) return state;
const next = new Set(state.speakingParticipantIds);
next.delete(participantId);
return {
speakingParticipantIds: next,
lastSpeakingParticipantId: wasLastSpeaking
? null
: state.lastSpeakingParticipantId,
};
});
}
export function updateSpeakingParticipants(changed: Map<number, boolean>) {
useSpeakingState.setState((state) => {
let hasDiff = false;
const next = new Set(state.speakingParticipantIds);
let lastSpeakingParticipantId = state.lastSpeakingParticipantId;
for (const [id, speaking] of changed) {
if (speaking) {
if (!next.has(id)) {
next.add(id);
lastSpeakingParticipantId = id;
hasDiff = true;
}
} else if (next.has(id)) {
next.delete(id);
hasDiff = true;
}
}
return hasDiff
? { speakingParticipantIds: next, lastSpeakingParticipantId }
: state;
});
}
export function useLastSpeakingParticipantId(): number | null {
return useSpeakingState((state) => state.lastSpeakingParticipantId);
}
export function useIsSpeaking(participantId: number): boolean {
return useSpeakingState((state) =>
state.speakingParticipantIds.has(participantId),
);
}