Disable mute button if media is not yet available. (#1218)
--------- Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
@@ -61,6 +61,10 @@ limitations under the License.
|
|||||||
outline: auto;
|
outline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toolbarButton:disabled {
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
.toolbarButton,
|
.toolbarButton,
|
||||||
.toolbarButtonSecondary {
|
.toolbarButtonSecondary {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ interface Props {
|
|||||||
children: Element[];
|
children: Element[];
|
||||||
onPress: (e: PressEvent) => void;
|
onPress: (e: PressEvent) => void;
|
||||||
onPressStart: (e: PressEvent) => void;
|
onPressStart: (e: PressEvent) => void;
|
||||||
|
disabled: boolean;
|
||||||
// TODO: add all props for <Button>
|
// TODO: add all props for <Button>
|
||||||
[index: string]: unknown;
|
[index: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,10 +66,14 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
const [videoEnabled, setVideoEnabled] = useState<boolean>(true);
|
const [videoEnabled, setVideoEnabled] = useState<boolean>(true);
|
||||||
const [audioEnabled, setAudioEnabled] = useState<boolean>(true);
|
const [audioEnabled, setAudioEnabled] = useState<boolean>(true);
|
||||||
|
|
||||||
|
// we store if the tracks are currently initializing to not show them as muted.
|
||||||
|
// showing them as muted while they are not yet available makes the buttons flicker undesirable during startup.
|
||||||
|
const [initializingVideo, setInitializingVideo] = useState<boolean>(true);
|
||||||
|
const [initializingAudio, setInitializingAudio] = useState<boolean>(true);
|
||||||
|
|
||||||
// The settings are updated as soon as the device changes. We wrap the settings value in a ref to store their initial value.
|
// The settings are updated as soon as the device changes. We wrap the settings value in a ref to store their initial value.
|
||||||
// Not changing the device options prohibits the usePreviewTracks hook to recreate the tracks.
|
// Not changing the device options prohibits the usePreviewTracks hook to recreate the tracks.
|
||||||
const initialDefaultDevices = useRef(useDefaultDevices()[0]);
|
const initialDefaultDevices = useRef(useDefaultDevices()[0]);
|
||||||
|
|
||||||
const tracks = usePreviewTracks(
|
const tracks = usePreviewTracks(
|
||||||
{
|
{
|
||||||
audio: { deviceId: initialDefaultDevices.current.audioinput },
|
audio: { deviceId: initialDefaultDevices.current.audioinput },
|
||||||
@@ -89,6 +93,7 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
tracks?.filter((t) => t.kind === Track.Kind.Audio)[0] as LocalAudioTrack,
|
tracks?.filter((t) => t.kind === Track.Kind.Audio)[0] as LocalAudioTrack,
|
||||||
[tracks]
|
[tracks]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Only let the MediaDeviceSwitcher request permissions if a video track is already available.
|
// Only let the MediaDeviceSwitcher request permissions if a video track is already available.
|
||||||
// Otherwise we would end up asking for permissions in usePreviewTracks and in useMediaDevicesSwitcher.
|
// Otherwise we would end up asking for permissions in usePreviewTracks and in useMediaDevicesSwitcher.
|
||||||
const requestPermissions = !!videoTrack;
|
const requestPermissions = !!videoTrack;
|
||||||
@@ -104,6 +109,12 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
|
|
||||||
const videoEl = React.useRef(null);
|
const videoEl = React.useRef(null);
|
||||||
|
|
||||||
|
// pretend the video is available until the initialization is over
|
||||||
|
const videoAvailableAndEndabled =
|
||||||
|
videoEnabled && (!!videoTrack || initializingVideo);
|
||||||
|
const audioAvailableAndEndabled =
|
||||||
|
audioEnabled && (!!videoTrack || initializingAudio);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Effect to update the settings
|
// Effect to update the settings
|
||||||
const createChoices = (
|
const createChoices = (
|
||||||
@@ -118,8 +129,8 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
: undefined;
|
: undefined;
|
||||||
};
|
};
|
||||||
onUserChoicesChanged({
|
onUserChoicesChanged({
|
||||||
video: createChoices(videoEnabled, videoIn.selectedId),
|
video: createChoices(videoAvailableAndEndabled, videoIn.selectedId),
|
||||||
audio: createChoices(audioEnabled, audioIn.selectedId),
|
audio: createChoices(audioAvailableAndEndabled, audioIn.selectedId),
|
||||||
});
|
});
|
||||||
}, [
|
}, [
|
||||||
onUserChoicesChanged,
|
onUserChoicesChanged,
|
||||||
@@ -127,11 +138,16 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
videoEnabled,
|
videoEnabled,
|
||||||
audioIn.selectedId,
|
audioIn.selectedId,
|
||||||
audioEnabled,
|
audioEnabled,
|
||||||
|
videoAvailableAndEndabled,
|
||||||
|
audioAvailableAndEndabled,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Effect to update the initial device selection for the ui elements based on the current preview track.
|
// Effect to update the initial device selection for the ui elements based on the current preview track.
|
||||||
if (!videoIn.selectedId || videoIn.selectedId == "") {
|
if (!videoIn.selectedId || videoIn.selectedId == "") {
|
||||||
|
if (videoTrack) {
|
||||||
|
setInitializingVideo(false);
|
||||||
|
}
|
||||||
videoTrack?.getDeviceId().then((videoId) => {
|
videoTrack?.getDeviceId().then((videoId) => {
|
||||||
if (videoId) {
|
if (videoId) {
|
||||||
videoIn.setSelected(videoId);
|
videoIn.setSelected(videoId);
|
||||||
@@ -139,6 +155,9 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!audioIn.selectedId || audioIn.selectedId == "") {
|
if (!audioIn.selectedId || audioIn.selectedId == "") {
|
||||||
|
if (audioTrack) {
|
||||||
|
setInitializingAudio(false);
|
||||||
|
}
|
||||||
audioTrack?.getDeviceId().then((audioId) => {
|
audioTrack?.getDeviceId().then((audioId) => {
|
||||||
if (audioId) {
|
if (audioId) {
|
||||||
audioIn.setSelected(audioId);
|
audioIn.setSelected(audioId);
|
||||||
@@ -158,6 +177,15 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
};
|
};
|
||||||
}, [videoTrack]);
|
}, [videoTrack]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Effect to mute/unmute video track. (This has to be done, so that the hardware camera indicator does not confuse the user)
|
||||||
|
if (videoTrack && videoEnabled) {
|
||||||
|
videoTrack?.unmute();
|
||||||
|
} else if (videoTrack) {
|
||||||
|
videoTrack?.mute();
|
||||||
|
}
|
||||||
|
}, [videoEnabled, videoTrack]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.preview} ref={previewRef}>
|
<div className={styles.preview} ref={previewRef}>
|
||||||
<video ref={videoEl} muted playsInline disablePictureInPicture />
|
<video ref={videoEl} muted playsInline disablePictureInPicture />
|
||||||
@@ -173,12 +201,14 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) {
|
|||||||
)}
|
)}
|
||||||
<div className={styles.previewButtons}>
|
<div className={styles.previewButtons}>
|
||||||
<MicButton
|
<MicButton
|
||||||
muted={!audioEnabled}
|
muted={!audioAvailableAndEndabled}
|
||||||
onPress={() => setAudioEnabled(!audioEnabled)}
|
onPress={() => setAudioEnabled(!audioAvailableAndEndabled)}
|
||||||
|
disabled={!audioTrack}
|
||||||
/>
|
/>
|
||||||
<VideoButton
|
<VideoButton
|
||||||
muted={!videoEnabled}
|
muted={!videoAvailableAndEndabled}
|
||||||
onPress={() => setVideoEnabled(!videoEnabled)}
|
onPress={() => setVideoEnabled(!videoAvailableAndEndabled)}
|
||||||
|
disabled={!videoTrack}
|
||||||
/>
|
/>
|
||||||
<SettingsButton onPress={openSettings} />
|
<SettingsButton onPress={openSettings} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user