2023-07-25 02:56:40 +08:00
|
|
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
|
|
import { User } from '/imports/ui/Types/user';
|
|
|
|
import { useCurrentUser } from '/imports/ui/core/hooks/useCurrentUser';
|
|
|
|
import { useMeeting } from '/imports/ui/core/hooks/useMeeting';
|
|
|
|
import { Meeting } from '/imports/ui/Types/meeting';
|
2023-08-15 04:52:35 +08:00
|
|
|
import { useShortcut } from '/imports/ui/core/hooks/useShortcut';
|
2023-07-25 02:56:40 +08:00
|
|
|
import { useMutation, useReactiveVar } from '@apollo/client';
|
|
|
|
import { defineMessages, useIntl } from 'react-intl';
|
|
|
|
import Button from '/imports/ui/components/common/button/component';
|
|
|
|
import AudioModalContainer from '../../audio-modal/container';
|
|
|
|
import AudioManager from '/imports/ui/services/audio-manager';
|
|
|
|
import { joinListenOnly } from './service';
|
|
|
|
import Styled from './styles';
|
|
|
|
import InputStreamLiveSelectorContainer from './input-stream-live-selector/component';
|
|
|
|
import { UPDATE_ECHO_TEST_RUNNING } from './queries';
|
|
|
|
|
|
|
|
const intlMessages = defineMessages({
|
|
|
|
joinAudio: {
|
|
|
|
id: 'app.audio.joinAudio',
|
|
|
|
description: 'Join audio button label',
|
|
|
|
},
|
|
|
|
leaveAudio: {
|
|
|
|
id: 'app.audio.leaveAudio',
|
|
|
|
description: 'Leave audio button label',
|
|
|
|
},
|
|
|
|
muteAudio: {
|
|
|
|
id: 'app.actionsBar.muteLabel',
|
|
|
|
description: 'Mute audio button label',
|
|
|
|
},
|
|
|
|
unmuteAudio: {
|
|
|
|
id: 'app.actionsBar.unmuteLabel',
|
|
|
|
description: 'Unmute audio button label',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
interface AudioControlsProps {
|
|
|
|
inAudio: boolean;
|
|
|
|
isConnected: boolean;
|
|
|
|
disabled: boolean;
|
|
|
|
isEchoTest: boolean;
|
|
|
|
updateEchoTestRunning: Function,
|
|
|
|
};
|
|
|
|
|
|
|
|
const AudioControls: React.FC<AudioControlsProps> = ({
|
|
|
|
isConnected,
|
|
|
|
disabled,
|
|
|
|
inAudio,
|
|
|
|
isEchoTest,
|
|
|
|
updateEchoTestRunning,
|
|
|
|
}) => {
|
|
|
|
const intl = useIntl();
|
2023-08-15 04:52:35 +08:00
|
|
|
const joinAudioShourtcut = useShortcut('joinaudio');
|
2023-09-11 21:12:37 +08:00
|
|
|
const echoTestIntervalRef = React.useRef<ReturnType<typeof setTimeout>>();
|
2023-07-25 02:56:40 +08:00
|
|
|
|
|
|
|
const [isAudioModalOpen, setIsAudioModalOpen] = React.useState(false);
|
|
|
|
|
2023-09-11 21:12:37 +08:00
|
|
|
const handleJoinAudio = useCallback((connected: boolean) => {
|
|
|
|
if (connected) {
|
2023-07-25 02:56:40 +08:00
|
|
|
joinListenOnly();
|
|
|
|
} else {
|
|
|
|
setIsAudioModalOpen(true);
|
|
|
|
}
|
2023-09-11 21:12:37 +08:00
|
|
|
}, []);
|
2023-07-25 02:56:40 +08:00
|
|
|
|
|
|
|
const joinButton = useMemo(() => {
|
|
|
|
return (
|
|
|
|
<Button
|
|
|
|
onClick={() => handleJoinAudio(isConnected)}
|
|
|
|
disabled={disabled}
|
|
|
|
hideLabel
|
|
|
|
aria-label={intl.formatMessage(intlMessages.joinAudio)}
|
|
|
|
label={intl.formatMessage(intlMessages.joinAudio)}
|
|
|
|
data-test="joinAudio"
|
|
|
|
color="default"
|
|
|
|
ghost
|
|
|
|
icon="no_audio"
|
|
|
|
size="lg"
|
|
|
|
circle
|
|
|
|
accessKey={joinAudioShourtcut}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
}, [isConnected, disabled]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (isEchoTest) {
|
|
|
|
echoTestIntervalRef.current = setInterval(() => {
|
|
|
|
updateEchoTestRunning();
|
|
|
|
}, 1000);
|
|
|
|
} else {
|
|
|
|
clearInterval(echoTestIntervalRef.current);
|
|
|
|
}
|
|
|
|
}, [isEchoTest]);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Styled.Container>
|
|
|
|
{!inAudio ? joinButton : <InputStreamLiveSelectorContainer />}
|
|
|
|
{
|
|
|
|
isAudioModalOpen ? <AudioModalContainer
|
|
|
|
{...{
|
|
|
|
priority: "low",
|
|
|
|
setIsOpen: () => setIsAudioModalOpen(false),
|
|
|
|
isOpen: isAudioModalOpen
|
|
|
|
}}
|
|
|
|
/> : null
|
|
|
|
}
|
|
|
|
</Styled.Container>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const AudioControlsContainer: React.FC = () => {
|
|
|
|
const currentUser: Partial<User> = useCurrentUser((u: Partial<User>) => {
|
|
|
|
return {
|
|
|
|
presenter: u.presenter,
|
|
|
|
isModerator: u.isModerator,
|
|
|
|
locked: u?.locked ?? false,
|
|
|
|
voice: u.voice
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const currentMeeting: Partial<Meeting> = useMeeting((m: Partial<Meeting>) => {
|
|
|
|
return {
|
|
|
|
lockSettings: m.lockSettings,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const [updateEchoTestRunning] = useMutation(UPDATE_ECHO_TEST_RUNNING);
|
|
|
|
|
|
|
|
// I access the internal variable to get the makevar reference, so we doesn't broke the client that uses the value directly
|
|
|
|
// and I can use it to make my component reactive
|
2023-08-15 04:52:35 +08:00
|
|
|
|
|
|
|
// @ts-ignore - temporary while hybrid (meteor+GraphQl)
|
2023-07-25 02:56:40 +08:00
|
|
|
const isConnected = useReactiveVar(AudioManager._isConnected.value) as boolean;
|
2023-08-15 04:52:35 +08:00
|
|
|
// @ts-ignore - temporary while hybrid (meteor+GraphQl)
|
2023-07-25 02:56:40 +08:00
|
|
|
const isConnecting = useReactiveVar(AudioManager._isConnecting.value) as boolean;
|
2023-08-15 04:52:35 +08:00
|
|
|
// @ts-ignore - temporary while hybrid (meteor+GraphQl)
|
2023-07-25 02:56:40 +08:00
|
|
|
const isHangingUp = useReactiveVar(AudioManager._isHangingUp.value) as boolean;
|
2023-08-15 04:52:35 +08:00
|
|
|
// @ts-ignore - temporary while hybrid (meteor+GraphQl)
|
2023-07-25 02:56:40 +08:00
|
|
|
const isEchoTest = useReactiveVar(AudioManager._isEchoTest.value) as boolean;
|
|
|
|
|
|
|
|
if (!currentUser || !currentMeeting) return null;
|
|
|
|
return <AudioControls
|
|
|
|
inAudio={!!currentUser.voice ?? false}
|
|
|
|
isConnected={isConnected}
|
|
|
|
disabled={isConnecting || isHangingUp}
|
|
|
|
isEchoTest={isEchoTest}
|
|
|
|
updateEchoTestRunning={updateEchoTestRunning}
|
|
|
|
/>;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default AudioControlsContainer;
|