element-call/src/room/usePTT.js

129 lines
3.4 KiB
JavaScript
Raw Normal View History

2022-04-29 00:44:50 +00:00
import { useCallback, useEffect, useState } from "react";
export function usePTT(client, groupCall, userMediaFeeds) {
const [
2022-05-06 20:23:29 +00:00
{ pttButtonHeld, isAdmin, talkOverEnabled, activeSpeakerUserId, unmuteError },
2022-04-29 00:44:50 +00:00
setState,
] = useState(() => {
const roomMember = groupCall.room.getMember(client.getUserId());
const activeSpeakerFeed = userMediaFeeds.find((f) => !f.isAudioMuted());
return {
isAdmin: roomMember.powerLevel >= 100,
talkOverEnabled: false,
pttButtonHeld: false,
activeSpeakerUserId: activeSpeakerFeed ? activeSpeakerFeed.userId : null,
2022-05-06 20:23:29 +00:00
unmuteError: null,
2022-04-29 00:44:50 +00:00
};
});
useEffect(() => {
function onMuteStateChanged(...args) {
const activeSpeakerFeed = userMediaFeeds.find((f) => !f.isAudioMuted());
setState((prevState) => ({
...prevState,
activeSpeakerUserId: activeSpeakerFeed
? activeSpeakerFeed.userId
: null,
}));
}
for (const callFeed of userMediaFeeds) {
callFeed.addListener("mute_state_changed", onMuteStateChanged);
}
const activeSpeakerFeed = userMediaFeeds.find((f) => !f.isAudioMuted());
setState((prevState) => ({
...prevState,
activeSpeakerUserId: activeSpeakerFeed ? activeSpeakerFeed.userId : null,
}));
return () => {
for (const callFeed of userMediaFeeds) {
callFeed.removeListener("mute_state_changed", onMuteStateChanged);
}
};
}, [userMediaFeeds]);
const startTalking = useCallback(async () => {
2022-05-06 20:23:29 +00:00
setState((prevState) => ({ ...prevState, pttButtonHeld: true, unmuteError: null, }));
if (!activeSpeakerUserId || isAdmin || talkOverEnabled) {
if (groupCall.isMicrophoneMuted()) {
try {
await groupCall.setMicrophoneMuted(false);
} catch (e) {
2022-05-06 20:23:29 +00:00
setState((prevState) => ({ ...prevState, unmuteError: null, }));
}
}
}
2022-05-06 20:23:29 +00:00
}, [setState]);
const stopTalking = useCallback(() => {
setState((prevState) => ({ ...prevState, pttButtonHeld: false }));
if (!groupCall.isMicrophoneMuted()) {
groupCall.setMicrophoneMuted(true);
}
}, []);
2022-04-29 00:44:50 +00:00
useEffect(() => {
function onKeyDown(event) {
if (event.code === "Space") {
event.preventDefault();
if (pttButtonHeld) return;
startTalking();
2022-04-29 00:44:50 +00:00
}
}
function onKeyUp(event) {
if (event.code === "Space") {
event.preventDefault();
stopTalking();
2022-04-29 00:44:50 +00:00
}
}
function onBlur() {
// TODO: We will need to disable this for a global PTT hotkey to work
if (!groupCall.isMicrophoneMuted()) {
groupCall.setMicrophoneMuted(true);
}
setState((prevState) => ({ ...prevState, pttButtonHeld: false }));
}
window.addEventListener("keydown", onKeyDown);
window.addEventListener("keyup", onKeyUp);
window.addEventListener("blur", onBlur);
return () => {
window.removeEventListener("keydown", onKeyDown);
window.removeEventListener("keyup", onKeyUp);
window.removeEventListener("blur", onBlur);
};
}, [activeSpeakerUserId, isAdmin, talkOverEnabled, pttButtonHeld]);
2022-04-29 00:44:50 +00:00
const setTalkOverEnabled = useCallback((talkOverEnabled) => {
setState((prevState) => ({
...prevState,
talkOverEnabled,
}));
}, []);
return {
pttButtonHeld,
isAdmin,
talkOverEnabled,
setTalkOverEnabled,
activeSpeakerUserId,
startTalking,
stopTalking,
unmuteError,
2022-04-29 00:44:50 +00:00
};
}