diff --git a/src/room/PTTCallView.jsx b/src/room/PTTCallView.jsx index 6993ec9..2406d0b 100644 --- a/src/room/PTTCallView.jsx +++ b/src/room/PTTCallView.jsx @@ -16,6 +16,7 @@ import { Timer } from "./Timer"; import { Toggle } from "../input/Toggle"; import { getAvatarUrl } from "../matrix-utils"; import { ReactComponent as AudioIcon } from "../icons/Audio.svg"; +import { OtherUserSpeakingError } from "matrix-js-sdk/src/webrtc/groupCall"; export function PTTCallView({ client, @@ -47,21 +48,22 @@ export function PTTCallView({ activeSpeakerUserId, startTalking, stopTalking, + unmuteError, } = usePTT(client, groupCall, userMediaFeeds); + const showTalkOverError = pttButtonHeld && unmuteError instanceof OtherUserSpeakingError; + const activeSpeakerIsLocalUser = activeSpeakerUserId && client.getUserId() === activeSpeakerUserId; - const showTalkOverError = - pttButtonHeld && !activeSpeakerIsLocalUser && !talkOverEnabled; const activeSpeakerUser = activeSpeakerUserId ? client.getUser(activeSpeakerUserId) : null; const activeSpeakerAvatarUrl = activeSpeakerUser ? getAvatarUrl( - client, - activeSpeakerUser.avatarUrl, - pttButtonSize - pttBorderWidth * 2 - ) + client, + activeSpeakerUser.avatarUrl, + pttButtonSize - pttBorderWidth * 2 + ) : null; const activeSpeakerDisplayName = activeSpeakerUser ? activeSpeakerUser.displayName @@ -77,9 +79,8 @@ export function PTTCallView({
-

{`${participants.length} ${ - participants.length > 1 ? "people" : "person" - } connected`}

+

{`${participants.length} ${participants.length > 1 ? "people" : "person" + } connected`}

{showTalkOverError ? "You can't talk at the same time" - : pttButtonHeld - ? "Release spacebar key to stop" - : talkOverEnabled && - activeSpeakerUserId && - !activeSpeakerIsLocalUser - ? `Press and hold spacebar to talk over ${activeSpeakerDisplayName}` - : "Press and hold spacebar to talk"} + : pttButtonHeld && activeSpeakerIsLocalUser + ? "Release spacebar key to stop" + : talkOverEnabled && + activeSpeakerUserId && + !activeSpeakerIsLocalUser + ? `Press and hold spacebar to talk over ${activeSpeakerDisplayName}` + : "Press and hold spacebar to talk"}

{userMediaFeeds.map((callFeed) => ( { function onMuteStateChanged(...args) { const activeSpeakerFeed = userMediaFeeds.find((f) => !f.isAudioMuted()); @@ -47,22 +49,26 @@ export function usePTT(client, groupCall, userMediaFeeds) { }; }, [userMediaFeeds]); - const startTalking = useCallback(() => { + const startTalking = useCallback(async () => { + setState((prevState) => ({ ...prevState, pttButtonHeld: true })); + setUnmuteError(null); if (!activeSpeakerUserId || isAdmin || talkOverEnabled) { if (groupCall.isMicrophoneMuted()) { - groupCall.setMicrophoneMuted(false); + try { + await groupCall.setMicrophoneMuted(false); + } catch (e) { + setUnmuteError(e); + } } - - setState((prevState) => ({ ...prevState, pttButtonHeld: true })); } - }, []); + }, [setUnmuteError]); const stopTalking = useCallback(() => { + setState((prevState) => ({ ...prevState, pttButtonHeld: false })); + if (!groupCall.isMicrophoneMuted()) { groupCall.setMicrophoneMuted(true); } - - setState((prevState) => ({ ...prevState, pttButtonHeld: false })); }, []); useEffect(() => { @@ -70,6 +76,8 @@ export function usePTT(client, groupCall, userMediaFeeds) { if (event.code === "Space") { event.preventDefault(); + if (pttButtonHeld) return; + startTalking(); } } @@ -100,7 +108,7 @@ export function usePTT(client, groupCall, userMediaFeeds) { window.removeEventListener("keyup", onKeyUp); window.removeEventListener("blur", onBlur); }; - }, [activeSpeakerUserId, isAdmin, talkOverEnabled]); + }, [activeSpeakerUserId, isAdmin, talkOverEnabled, pttButtonHeld]); const setTalkOverEnabled = useCallback((talkOverEnabled) => { setState((prevState) => ({ @@ -117,5 +125,6 @@ export function usePTT(client, groupCall, userMediaFeeds) { activeSpeakerUserId, startTalking, stopTalking, + unmuteError, }; }