Skip to content

Commit

Permalink
Move onDeviceChange event listener to local media slice
Browse files Browse the repository at this point in the history
  • Loading branch information
thyal committed Jan 9, 2024
1 parent 261509c commit fac6b2a
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 13 deletions.
28 changes: 18 additions & 10 deletions src/lib/core/redux/slices/localMedia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createAppAsyncThunk, createAppThunk } from "../../redux/thunk";
import { RootState } from "../../redux/store";
import { createReactor, startAppListening } from "../../redux/listenerMiddleware";
import { doAppJoin, selectAppWantsToJoin } from "./app";
import debounce from "~/lib/utils/debounce";
import debounce from "../../../utils/debounce";

export type LocalMediaOptions = {
audio: boolean;
Expand Down Expand Up @@ -143,7 +143,7 @@ export const localMediaSlice = createSlice({
status: "starting",
};
})
.addCase(doStartLocalMedia.fulfilled, (state, { payload: { stream } }) => {
.addCase(doStartLocalMedia.fulfilled, (state, { payload: { stream, onDeviceChange } }) => {
let cameraDeviceId = undefined;
let cameraEnabled = false;
let microphoneDeviceId = undefined;
Expand All @@ -170,6 +170,7 @@ export const localMediaSlice = createSlice({
currentMicrophoneDeviceId: microphoneDeviceId,
cameraEnabled,
microphoneEnabled,
onDeviceChange,
};
})
.addCase(doStartLocalMedia.rejected, (state, action) => {
Expand Down Expand Up @@ -448,22 +449,24 @@ export const doSwitchLocalStream = createAppAsyncThunk(
export const doStartLocalMedia = createAppAsyncThunk(
"localMedia/doStartLocalMedia",
async (payload: LocalMediaOptions | MediaStream, { getState, dispatch, rejectWithValue }) => {
// Resolve if existing stream is passed
if ("getTracks" in payload) {
return Promise.resolve({ stream: payload });
}

const onDeviceChange = debounce(
() => {
dispatch(doUpdateDeviceList());
},
{ delay: 500 }
);

global.navigator.mediaDevices && global.navigator.mediaDevices.addEventListener("devicechange", onDeviceChange);
if (global.navigator.mediaDevices) {
global.navigator.mediaDevices.addEventListener("devicechange", onDeviceChange);
}

// Resolve if existing stream is passed
if ("getTracks" in payload) {
return Promise.resolve({ stream: payload, onDeviceChange });
}

if (!(payload.audio || payload.video)) {
return { stream: new MediaStream() };
return { stream: new MediaStream(), onDeviceChange };
} else {
dispatch(doSetLocalMediaOptions({ options: payload }));
}
Expand All @@ -482,7 +485,7 @@ export const doStartLocalMedia = createAppAsyncThunk(
videoId: payload.video,
});

return { stream };
return { stream, onDeviceChange };
} catch (error) {
return rejectWithValue(error);
}
Expand All @@ -492,6 +495,7 @@ export const doStartLocalMedia = createAppAsyncThunk(
export const doStopLocalMedia = createAppThunk(() => (dispatch, getState) => {
const screenshareStream = selectScreenshareStream(getState());
const stream = selectLocalMediaStream(getState());
const onDeviceChange = selectLocalMediaRaw(getState()).onDeviceChange;

screenshareStream?.getTracks().forEach((track) => {
track.stop();
Expand All @@ -501,6 +505,10 @@ export const doStopLocalMedia = createAppThunk(() => (dispatch, getState) => {
track.stop();
});

if (onDeviceChange && global.navigator.mediaDevices) {
global.navigator.mediaDevices.removeEventListener("devicechange", onDeviceChange);
}

dispatch(localMediaStopped());
});

Expand Down
7 changes: 6 additions & 1 deletion src/lib/core/redux/tests/store/localMedia.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ describe("actions", () => {

const after = store.getState().localMedia;

expect(diff(before, after)).toEqual({ status: "started", stream: existingStream });
expect(diff(before, after)).toEqual({
status: "started",
stream: existingStream,
onDeviceChange: expect.any(Function),
});
});
});

Expand Down Expand Up @@ -91,6 +95,7 @@ describe("actions", () => {
stream: newStream,
devices: expect.any(Object),
options: { audio: true, video: true },
onDeviceChange: expect.any(Function),
});
});
});
Expand Down
2 changes: 0 additions & 2 deletions src/lib/react/useLocalMedia/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import {
doStopLocalMedia,
doToggleCameraEnabled,
doToggleMicrophoneEnabled,
doUpdateDeviceList,
} from "../../core/redux/slices/localMedia";
import { LocalMediaState, UseLocalMediaOptions, UseLocalMediaResult } from "./types";
import { selectLocalMediaState } from "./selector";
import { createStore, observeStore, Store } from "../../core/redux/store";
import { createServices } from "../../services";
import debounce from "../../utils/debounce";

const initialState: LocalMediaState = {
cameraDeviceError: null,
Expand Down

0 comments on commit fac6b2a

Please sign in to comment.