Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Persist audio and video mute state in video rooms
Browse files Browse the repository at this point in the history
…so that video lobbies remember whether you've disabled your camera.
  • Loading branch information
robintown committed Apr 20, 2022
1 parent 6e86a14 commit b5be70f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
16 changes: 12 additions & 4 deletions src/components/views/voip/VideoLobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { Room } from "matrix-js-sdk/src/models/room";

import { _t } from "../../../languageHandler";
import { useAsyncMemo } from "../../../hooks/useAsyncMemo";
import { useStateToggle } from "../../../hooks/useStateToggle";
import { useConnectedMembers } from "../../../utils/VideoChannelUtils";
import VideoChannelStore from "../../../stores/VideoChannelStore";
import IconizedContextMenu, {
Expand Down Expand Up @@ -108,6 +107,7 @@ const DeviceButton: FC<IDeviceButtonProps> = ({
const MAX_FACES = 8;

const VideoLobby: FC<{ room: Room }> = ({ room }) => {
const store = VideoChannelStore.instance;
const [connecting, setConnecting] = useState(false);
const me = useMemo(() => room.getMember(room.myUserId), [room]);
const connectedMembers = useConnectedMembers(room.currentState);
Expand All @@ -130,8 +130,16 @@ const VideoLobby: FC<{ room: Room }> = ({ room }) => {
const audioDevice = selectedAudioDevice ?? audioDevices[0];
const videoDevice = selectedVideoDevice ?? videoDevices[0];

const [audioActive, toggleAudio] = useStateToggle(true);
const [videoActive, toggleVideo] = useStateToggle(true);
const [audioActive, setAudioActive] = useState(!store.audioMuted);
const [videoActive, setVideoActive] = useState(!store.videoMuted);
const toggleAudio = () => {
store.audioMuted = audioActive;
setAudioActive(!audioActive);
};
const toggleVideo = () => {
store.videoMuted = videoActive;
setVideoActive(!videoActive);
};

const videoStream = useAsyncMemo(async () => {
if (videoDevice && videoActive) {
Expand Down Expand Up @@ -162,7 +170,7 @@ const VideoLobby: FC<{ room: Room }> = ({ room }) => {
const connect = async () => {
setConnecting(true);
try {
await VideoChannelStore.instance.connect(
await store.connect(
room.roomId, audioActive ? audioDevice : null, videoActive ? videoDevice : null,
);
} catch (e) {
Expand Down
44 changes: 43 additions & 1 deletion src/stores/VideoChannelStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ export default class VideoChannelStore extends AsyncStoreWithClient<null> {
public get participants(): IJitsiParticipant[] { return this._participants; }
private set participants(value: IJitsiParticipant[]) { this._participants = value; }

private _audioMuted = localStorage.getItem("mx_audioMuted") === "true";
public get audioMuted(): boolean { return this._audioMuted; }
public set audioMuted(value: boolean) {
this._audioMuted = value;
localStorage.setItem("mx_audioMuted", value.toString());
}

private _videoMuted = localStorage.getItem("mx_videoMuted") === "true";
public get videoMuted(): boolean { return this._videoMuted; }
public set videoMuted(value: boolean) {
this._videoMuted = value;
localStorage.setItem("mx_videoMuted", value.toString());
}

public connect = async (roomId: string, audioDevice: MediaDeviceInfo, videoDevice: MediaDeviceInfo) => {
if (this.activeChannel) await this.disconnect();

Expand Down Expand Up @@ -136,10 +150,14 @@ export default class VideoChannelStore extends AsyncStoreWithClient<null> {
}
}

// Participant data and mute state will come down the event pipeline quickly, so prepare in advance
this.activeChannel = messaging;
this.roomId = roomId;
// Participant data will come down the event pipeline quickly, so prepare in advance
messaging.on(`action:${ElementWidgetActions.CallParticipants}`, this.onParticipants);
messaging.on(`action:${ElementWidgetActions.MuteAudio}`, this.onMuteAudio);
messaging.on(`action:${ElementWidgetActions.UnmuteAudio}`, this.onUnmuteAudio);
messaging.on(`action:${ElementWidgetActions.MuteVideo}`, this.onMuteVideo);
messaging.on(`action:${ElementWidgetActions.UnmuteVideo}`, this.onUnmuteVideo);

this.emit(VideoChannelEvent.StartConnect, roomId);

Expand All @@ -163,6 +181,10 @@ export default class VideoChannelStore extends AsyncStoreWithClient<null> {
this.activeChannel = null;
this.roomId = null;
messaging.off(`action:${ElementWidgetActions.CallParticipants}`, this.onParticipants);
messaging.off(`action:${ElementWidgetActions.MuteAudio}`, this.onMuteAudio);
messaging.off(`action:${ElementWidgetActions.UnmuteAudio}`, this.onUnmuteAudio);
messaging.off(`action:${ElementWidgetActions.MuteVideo}`, this.onMuteVideo);
messaging.off(`action:${ElementWidgetActions.UnmuteVideo}`, this.onUnmuteVideo);

this.emit(VideoChannelEvent.Disconnect, roomId);

Expand Down Expand Up @@ -233,4 +255,24 @@ export default class VideoChannelStore extends AsyncStoreWithClient<null> {
this.emit(VideoChannelEvent.Participants, this.roomId, ev.detail.data.participants);
this.ack(ev);
};

private onMuteAudio = (ev: CustomEvent<IWidgetApiRequest>) => {
this.audioMuted = true;
this.ack(ev);
};

private onUnmuteAudio = (ev: CustomEvent<IWidgetApiRequest>) => {
this.audioMuted = false;
this.ack(ev);
};

private onMuteVideo = (ev: CustomEvent<IWidgetApiRequest>) => {
this.videoMuted = true;
this.ack(ev);
};

private onUnmuteVideo = (ev: CustomEvent<IWidgetApiRequest>) => {
this.videoMuted = false;
this.ack(ev);
};
}

0 comments on commit b5be70f

Please sign in to comment.