@whereby.com/core 1.9.1 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1158,7 +1158,7 @@ const createReactor = (selectors, callback) => {
1158
1158
  });
1159
1159
  };
1160
1160
 
1161
- const coreVersion = "1.9.1";
1161
+ const coreVersion = "1.9.2";
1162
1162
 
1163
1163
  const initialState$1 = {
1164
1164
  displayName: null,
@@ -1728,7 +1728,7 @@ const doToggleCamera = createAppAsyncThunk("localMedia/doToggleCamera", (_1, _a)
1728
1728
  else {
1729
1729
  const constraintsOptions = selectLocalMediaConstraintsOptions(state);
1730
1730
  const cameraDeviceId = selectCurrentCameraDeviceId(state);
1731
- yield media.getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: false, videoId: cameraDeviceId, type: "exact" }), { replaceStream: stream });
1731
+ yield media.getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: false, videoId: cameraDeviceId || true, type: "exact" }), { replaceStream: stream });
1732
1732
  track = stream.getVideoTracks()[0];
1733
1733
  }
1734
1734
  }
@@ -1793,7 +1793,6 @@ const doSetDevice = createAppAsyncThunk("localMedia/reactSetDevice", (_a, _b) =>
1793
1793
  }
1794
1794
  }));
1795
1795
  const doUpdateDeviceList = createAppAsyncThunk("localMedia/doUpdateDeviceList", (_1, _a) => __awaiter(void 0, [_1, _a], void 0, function* (_, { getState, dispatch, rejectWithValue }) {
1796
- var _b, _c, _d, _e;
1797
1796
  const state = getState();
1798
1797
  let newDevices = [];
1799
1798
  let oldDevices = [];
@@ -1809,19 +1808,29 @@ const doUpdateDeviceList = createAppAsyncThunk("localMedia/doUpdateDeviceList",
1809
1808
  if (!shouldHandleDeviceUpdate) {
1810
1809
  return { devices: newDevices };
1811
1810
  }
1812
- const { changedDevices, addedDevices } = media.getUpdatedDevices({
1811
+ const { currentCameraDeviceId, currentMicrophoneDeviceId, currentSpeakerDeviceId } = state.localMedia;
1812
+ const { changedDevices, removedDevices } = media.getUpdatedDevices({
1813
1813
  oldDevices,
1814
1814
  newDevices,
1815
+ currentVideoId: currentCameraDeviceId,
1816
+ currentAudioId: currentMicrophoneDeviceId,
1817
+ currentSpeakerId: currentSpeakerDeviceId,
1815
1818
  });
1816
- let autoSwitchAudioId = (_b = changedDevices.audioinput) === null || _b === void 0 ? void 0 : _b.deviceId;
1817
- let autoSwitchVideoId = (_c = changedDevices.videoinput) === null || _c === void 0 ? void 0 : _c.deviceId;
1818
- if (autoSwitchAudioId === undefined) {
1819
- autoSwitchAudioId = (_d = addedDevices.audioinput) === null || _d === void 0 ? void 0 : _d.deviceId;
1819
+ let autoSwitchAudioId;
1820
+ let autoSwitchVideoId;
1821
+ if (removedDevices.audioinput) {
1822
+ autoSwitchAudioId = true;
1820
1823
  }
1821
- if (autoSwitchVideoId === undefined) {
1822
- autoSwitchVideoId = (_e = addedDevices.videoinput) === null || _e === void 0 ? void 0 : _e.deviceId;
1824
+ if (removedDevices.videoinput) {
1825
+ autoSwitchVideoId = true;
1823
1826
  }
1824
- if (autoSwitchAudioId !== undefined || autoSwitchVideoId !== undefined) {
1827
+ if (!autoSwitchAudioId && changedDevices.audioinput) {
1828
+ autoSwitchAudioId = changedDevices.audioinput.deviceId;
1829
+ }
1830
+ if (!autoSwitchVideoId && changedDevices.videoinput) {
1831
+ autoSwitchVideoId = changedDevices.videoinput.deviceId;
1832
+ }
1833
+ if (autoSwitchAudioId || autoSwitchVideoId) {
1825
1834
  dispatch(doSwitchLocalStream({ audioId: autoSwitchAudioId, videoId: autoSwitchVideoId }));
1826
1835
  }
1827
1836
  return { devices: newDevices };
@@ -1839,28 +1848,29 @@ const doSwitchLocalStream = createAppAsyncThunk("localMedia/doSwitchLocalStream"
1839
1848
  return;
1840
1849
  }
1841
1850
  const beforeEffectTracks = selectLocalMediaBeforeEffectTracks(state);
1842
- if (audioId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.audio)) {
1851
+ if (audioId && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.audio)) {
1843
1852
  beforeEffectTracks.audio.stop();
1844
1853
  beforeEffectTracks.audio = undefined;
1845
1854
  }
1846
- if (videoId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.video)) {
1855
+ if (videoId && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.video)) {
1847
1856
  beforeEffectTracks.video.stop();
1848
1857
  beforeEffectTracks.video = undefined;
1849
1858
  }
1850
1859
  try {
1851
- const { replacedTracks } = yield media.getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: audioId === undefined ? false : audioId, videoId: videoId === undefined ? false : videoId, type: "exact" }), { replaceStream });
1852
- const deviceId = audioId || videoId;
1853
- if (onlySwitchingOne && deviceId) {
1854
- dispatch(deviceBusy({
1855
- deviceId,
1856
- }));
1860
+ const { replacedTracks, error } = yield media.getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: audioId || false, videoId: videoId || false, type: "exact" }), { replaceStream });
1861
+ if (error) {
1862
+ const deviceId = audioId || videoId;
1863
+ if (onlySwitchingOne && typeof deviceId === "string") {
1864
+ dispatch(deviceBusy({
1865
+ deviceId,
1866
+ }));
1867
+ }
1857
1868
  }
1858
1869
  return { replacedTracks, beforeEffectTracks };
1859
1870
  }
1860
1871
  catch (error) {
1861
- console.error(error);
1862
1872
  const deviceId = audioId || videoId;
1863
- if (onlySwitchingOne && deviceId) {
1873
+ if (onlySwitchingOne && typeof deviceId === "string") {
1864
1874
  dispatch(deviceBusy({
1865
1875
  deviceId,
1866
1876
  }));
@@ -2000,13 +2010,17 @@ createReactor([selectLocalMediaShouldStartWithOptions], ({ dispatch }, options)
2000
2010
  dispatch(doStartLocalMedia(options));
2001
2011
  }
2002
2012
  });
2003
- const selectLocalMediaShouldStop = toolkit.createSelector(selectAppIsActive, selectLocalMediaStatus, selectLocalMediaOptions, (appIsActive, localMediaStatus, localMediaOptions) => {
2004
- return !appIsActive && localMediaStatus !== "inactive" && !!localMediaOptions;
2005
- });
2006
- createReactor([selectLocalMediaShouldStop], ({ dispatch }, localMediaShouldStop) => {
2007
- if (localMediaShouldStop) {
2013
+ startAppListening({
2014
+ predicate: (_action, currentState, previousState) => {
2015
+ const oldValue = selectAppIsActive(previousState);
2016
+ const newValue = selectAppIsActive(currentState);
2017
+ const localMediaOptions = selectLocalMediaOptions(currentState);
2018
+ const localMediaStatus = selectLocalMediaStatus(currentState);
2019
+ return (oldValue === true && newValue === false) && localMediaStatus !== "inactive" && !!localMediaOptions;
2020
+ },
2021
+ effect: (_, { dispatch }) => {
2008
2022
  dispatch(doStopLocalMedia());
2009
- }
2023
+ },
2010
2024
  });
2011
2025
  startAppListening({
2012
2026
  predicate: (_action, currentState, previousState) => {
@@ -2047,10 +2061,25 @@ startAppListening({
2047
2061
  });
2048
2062
  startAppListening({
2049
2063
  predicate: (_action, currentState, previousState) => {
2050
- const oldValue = selectCurrentCameraDeviceId(previousState);
2051
- const newValue = selectCurrentCameraDeviceId(currentState);
2064
+ var _a, _b;
2065
+ const oldDeviceId = selectCurrentCameraDeviceId(previousState);
2066
+ const newDeviceId = selectCurrentCameraDeviceId(currentState);
2052
2067
  const isReady = selectLocalMediaStatus(previousState) === "started";
2053
- return isReady && oldValue !== newValue;
2068
+ const isSwitchingStream = selectLocalMediaIsSwitchingStream(currentState);
2069
+ if (isSwitchingStream) {
2070
+ return false;
2071
+ }
2072
+ if (!newDeviceId) {
2073
+ return false;
2074
+ }
2075
+ const currentTrack = (_b = (_a = selectLocalMediaStream(currentState)) === null || _a === void 0 ? void 0 : _a.getVideoTracks()) === null || _b === void 0 ? void 0 : _b[0];
2076
+ if (currentTrack && currentTrack.readyState === "live") {
2077
+ const currentDeviceId = currentTrack.getSettings().deviceId;
2078
+ if (currentDeviceId === newDeviceId) {
2079
+ return false;
2080
+ }
2081
+ }
2082
+ return isReady && oldDeviceId !== newDeviceId;
2054
2083
  },
2055
2084
  effect: (_action, { dispatch }) => {
2056
2085
  dispatch(doSetDevice({ audio: false, video: true }));
@@ -2058,10 +2087,25 @@ startAppListening({
2058
2087
  });
2059
2088
  startAppListening({
2060
2089
  predicate: (_action, currentState, previousState) => {
2061
- const oldValue = selectCurrentMicrophoneDeviceId(previousState);
2062
- const newValue = selectCurrentMicrophoneDeviceId(currentState);
2090
+ var _a, _b;
2091
+ const oldDeviceId = selectCurrentMicrophoneDeviceId(previousState);
2092
+ const newDeviceId = selectCurrentMicrophoneDeviceId(currentState);
2063
2093
  const isReady = selectLocalMediaStatus(previousState) === "started";
2064
- return isReady && oldValue !== newValue;
2094
+ const isSwitchingStream = selectLocalMediaIsSwitchingStream(currentState);
2095
+ if (isSwitchingStream) {
2096
+ return false;
2097
+ }
2098
+ if (!newDeviceId) {
2099
+ return false;
2100
+ }
2101
+ const currentTrack = (_b = (_a = selectLocalMediaStream(currentState)) === null || _a === void 0 ? void 0 : _a.getVideoTracks()) === null || _b === void 0 ? void 0 : _b[0];
2102
+ if (currentTrack && currentTrack.readyState === "live") {
2103
+ const currentDeviceId = currentTrack.getSettings().deviceId;
2104
+ if (currentDeviceId === newDeviceId) {
2105
+ return false;
2106
+ }
2107
+ }
2108
+ return isReady && oldDeviceId !== newDeviceId;
2065
2109
  },
2066
2110
  effect: (_action, { dispatch }) => {
2067
2111
  dispatch(doSetDevice({ audio: true, video: false }));
@@ -2880,15 +2924,6 @@ startAppListening({
2880
2924
  },
2881
2925
  });
2882
2926
 
2883
- function isDeferrable({ client, breakoutCurrentId }) {
2884
- if (!client)
2885
- return false;
2886
- if (!breakoutCurrentId && client.breakoutGroup)
2887
- return true;
2888
- if (!client.isAudioEnabled && !client.isVideoEnabled)
2889
- return true;
2890
- return false;
2891
- }
2892
2927
  const createWebRtcEmitter = (dispatch) => {
2893
2928
  return {
2894
2929
  emit: (eventName, data) => {
@@ -2976,22 +3011,12 @@ const doConnectRtc = createAppThunk(() => (dispatch, getState) => {
2976
3011
  const state = getState();
2977
3012
  const socket = selectSignalConnectionRaw(state).socket;
2978
3013
  const dispatcher = selectRtcConnectionRaw(state).rtcManagerDispatcher;
2979
- const isCameraEnabled = selectIsCameraEnabled(state);
2980
- const isMicrophoneEnabled = selectIsMicrophoneEnabled(state);
2981
3014
  const isNodeSdk = selectAppIsNodeSdk(state);
2982
3015
  if (dispatcher || !socket) {
2983
3016
  return;
2984
3017
  }
2985
3018
  const webrtcProvider = {
2986
- getMediaConstraints: () => ({
2987
- audio: isMicrophoneEnabled,
2988
- video: isCameraEnabled,
2989
- }),
2990
- deferrable(clientId) {
2991
- const client = selectRemoteParticipants(getState()).find((p) => p.id === clientId);
2992
- const breakoutCurrentId = selectBreakoutCurrentId(getState()) || "";
2993
- return isDeferrable({ client, breakoutCurrentId });
2994
- },
3019
+ getMediaConstraints: () => selectLocalMediaConstraintsOptions(state),
2995
3020
  };
2996
3021
  const rtcManagerDispatcher = new media.RtcManagerDispatcher({
2997
3022
  emitter: createWebRtcEmitter(dispatch),
@@ -4621,6 +4646,10 @@ class LocalMediaClient extends BaseClient {
4621
4646
  }
4622
4647
  startMedia() {
4623
4648
  return __awaiter(this, arguments, void 0, function* (options = { audio: true, video: true }) {
4649
+ const localMediaStatus = this.store.getState().localMedia.status;
4650
+ if (["started", "starting"].includes(localMediaStatus)) {
4651
+ return;
4652
+ }
4624
4653
  return yield this.store.dispatch(doStartLocalMedia(options));
4625
4654
  });
4626
4655
  }
package/dist/index.d.cts CHANGED
@@ -1017,7 +1017,7 @@ declare class LocalMediaClient extends BaseClient<LocalMediaState, LocalMediaEve
1017
1017
  rejectedWithValue: true;
1018
1018
  } | ({
1019
1019
  rejectedWithValue: false;
1020
- } & {})), _reduxjs_toolkit.SerializedError>>;
1020
+ } & {})), _reduxjs_toolkit.SerializedError> | undefined>;
1021
1021
  toggleCamera(enabled?: boolean): void;
1022
1022
  toggleMicrophone(enabled?: boolean): void;
1023
1023
  toggleLowDataMode(enabled?: boolean): void;
package/dist/index.d.mts CHANGED
@@ -1017,7 +1017,7 @@ declare class LocalMediaClient extends BaseClient<LocalMediaState, LocalMediaEve
1017
1017
  rejectedWithValue: true;
1018
1018
  } | ({
1019
1019
  rejectedWithValue: false;
1020
- } & {})), _reduxjs_toolkit.SerializedError>>;
1020
+ } & {})), _reduxjs_toolkit.SerializedError> | undefined>;
1021
1021
  toggleCamera(enabled?: boolean): void;
1022
1022
  toggleMicrophone(enabled?: boolean): void;
1023
1023
  toggleLowDataMode(enabled?: boolean): void;
package/dist/index.d.ts CHANGED
@@ -1017,7 +1017,7 @@ declare class LocalMediaClient extends BaseClient<LocalMediaState, LocalMediaEve
1017
1017
  rejectedWithValue: true;
1018
1018
  } | ({
1019
1019
  rejectedWithValue: false;
1020
- } & {})), _reduxjs_toolkit.SerializedError>>;
1020
+ } & {})), _reduxjs_toolkit.SerializedError> | undefined>;
1021
1021
  toggleCamera(enabled?: boolean): void;
1022
1022
  toggleMicrophone(enabled?: boolean): void;
1023
1023
  toggleLowDataMode(enabled?: boolean): void;
package/dist/index.mjs CHANGED
@@ -1156,7 +1156,7 @@ const createReactor = (selectors, callback) => {
1156
1156
  });
1157
1157
  };
1158
1158
 
1159
- const coreVersion = "1.9.1";
1159
+ const coreVersion = "1.9.2";
1160
1160
 
1161
1161
  const initialState$1 = {
1162
1162
  displayName: null,
@@ -1726,7 +1726,7 @@ const doToggleCamera = createAppAsyncThunk("localMedia/doToggleCamera", (_1, _a)
1726
1726
  else {
1727
1727
  const constraintsOptions = selectLocalMediaConstraintsOptions(state);
1728
1728
  const cameraDeviceId = selectCurrentCameraDeviceId(state);
1729
- yield getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: false, videoId: cameraDeviceId, type: "exact" }), { replaceStream: stream });
1729
+ yield getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: false, videoId: cameraDeviceId || true, type: "exact" }), { replaceStream: stream });
1730
1730
  track = stream.getVideoTracks()[0];
1731
1731
  }
1732
1732
  }
@@ -1791,7 +1791,6 @@ const doSetDevice = createAppAsyncThunk("localMedia/reactSetDevice", (_a, _b) =>
1791
1791
  }
1792
1792
  }));
1793
1793
  const doUpdateDeviceList = createAppAsyncThunk("localMedia/doUpdateDeviceList", (_1, _a) => __awaiter(void 0, [_1, _a], void 0, function* (_, { getState, dispatch, rejectWithValue }) {
1794
- var _b, _c, _d, _e;
1795
1794
  const state = getState();
1796
1795
  let newDevices = [];
1797
1796
  let oldDevices = [];
@@ -1807,19 +1806,29 @@ const doUpdateDeviceList = createAppAsyncThunk("localMedia/doUpdateDeviceList",
1807
1806
  if (!shouldHandleDeviceUpdate) {
1808
1807
  return { devices: newDevices };
1809
1808
  }
1810
- const { changedDevices, addedDevices } = getUpdatedDevices({
1809
+ const { currentCameraDeviceId, currentMicrophoneDeviceId, currentSpeakerDeviceId } = state.localMedia;
1810
+ const { changedDevices, removedDevices } = getUpdatedDevices({
1811
1811
  oldDevices,
1812
1812
  newDevices,
1813
+ currentVideoId: currentCameraDeviceId,
1814
+ currentAudioId: currentMicrophoneDeviceId,
1815
+ currentSpeakerId: currentSpeakerDeviceId,
1813
1816
  });
1814
- let autoSwitchAudioId = (_b = changedDevices.audioinput) === null || _b === void 0 ? void 0 : _b.deviceId;
1815
- let autoSwitchVideoId = (_c = changedDevices.videoinput) === null || _c === void 0 ? void 0 : _c.deviceId;
1816
- if (autoSwitchAudioId === undefined) {
1817
- autoSwitchAudioId = (_d = addedDevices.audioinput) === null || _d === void 0 ? void 0 : _d.deviceId;
1817
+ let autoSwitchAudioId;
1818
+ let autoSwitchVideoId;
1819
+ if (removedDevices.audioinput) {
1820
+ autoSwitchAudioId = true;
1818
1821
  }
1819
- if (autoSwitchVideoId === undefined) {
1820
- autoSwitchVideoId = (_e = addedDevices.videoinput) === null || _e === void 0 ? void 0 : _e.deviceId;
1822
+ if (removedDevices.videoinput) {
1823
+ autoSwitchVideoId = true;
1821
1824
  }
1822
- if (autoSwitchAudioId !== undefined || autoSwitchVideoId !== undefined) {
1825
+ if (!autoSwitchAudioId && changedDevices.audioinput) {
1826
+ autoSwitchAudioId = changedDevices.audioinput.deviceId;
1827
+ }
1828
+ if (!autoSwitchVideoId && changedDevices.videoinput) {
1829
+ autoSwitchVideoId = changedDevices.videoinput.deviceId;
1830
+ }
1831
+ if (autoSwitchAudioId || autoSwitchVideoId) {
1823
1832
  dispatch(doSwitchLocalStream({ audioId: autoSwitchAudioId, videoId: autoSwitchVideoId }));
1824
1833
  }
1825
1834
  return { devices: newDevices };
@@ -1837,28 +1846,29 @@ const doSwitchLocalStream = createAppAsyncThunk("localMedia/doSwitchLocalStream"
1837
1846
  return;
1838
1847
  }
1839
1848
  const beforeEffectTracks = selectLocalMediaBeforeEffectTracks(state);
1840
- if (audioId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.audio)) {
1849
+ if (audioId && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.audio)) {
1841
1850
  beforeEffectTracks.audio.stop();
1842
1851
  beforeEffectTracks.audio = undefined;
1843
1852
  }
1844
- if (videoId !== undefined && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.video)) {
1853
+ if (videoId && (beforeEffectTracks === null || beforeEffectTracks === void 0 ? void 0 : beforeEffectTracks.video)) {
1845
1854
  beforeEffectTracks.video.stop();
1846
1855
  beforeEffectTracks.video = undefined;
1847
1856
  }
1848
1857
  try {
1849
- const { replacedTracks } = yield getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: audioId === undefined ? false : audioId, videoId: videoId === undefined ? false : videoId, type: "exact" }), { replaceStream });
1850
- const deviceId = audioId || videoId;
1851
- if (onlySwitchingOne && deviceId) {
1852
- dispatch(deviceBusy({
1853
- deviceId,
1854
- }));
1858
+ const { replacedTracks, error } = yield getStream(Object.assign(Object.assign({}, constraintsOptions), { audioId: audioId || false, videoId: videoId || false, type: "exact" }), { replaceStream });
1859
+ if (error) {
1860
+ const deviceId = audioId || videoId;
1861
+ if (onlySwitchingOne && typeof deviceId === "string") {
1862
+ dispatch(deviceBusy({
1863
+ deviceId,
1864
+ }));
1865
+ }
1855
1866
  }
1856
1867
  return { replacedTracks, beforeEffectTracks };
1857
1868
  }
1858
1869
  catch (error) {
1859
- console.error(error);
1860
1870
  const deviceId = audioId || videoId;
1861
- if (onlySwitchingOne && deviceId) {
1871
+ if (onlySwitchingOne && typeof deviceId === "string") {
1862
1872
  dispatch(deviceBusy({
1863
1873
  deviceId,
1864
1874
  }));
@@ -1998,13 +2008,17 @@ createReactor([selectLocalMediaShouldStartWithOptions], ({ dispatch }, options)
1998
2008
  dispatch(doStartLocalMedia(options));
1999
2009
  }
2000
2010
  });
2001
- const selectLocalMediaShouldStop = createSelector(selectAppIsActive, selectLocalMediaStatus, selectLocalMediaOptions, (appIsActive, localMediaStatus, localMediaOptions) => {
2002
- return !appIsActive && localMediaStatus !== "inactive" && !!localMediaOptions;
2003
- });
2004
- createReactor([selectLocalMediaShouldStop], ({ dispatch }, localMediaShouldStop) => {
2005
- if (localMediaShouldStop) {
2011
+ startAppListening({
2012
+ predicate: (_action, currentState, previousState) => {
2013
+ const oldValue = selectAppIsActive(previousState);
2014
+ const newValue = selectAppIsActive(currentState);
2015
+ const localMediaOptions = selectLocalMediaOptions(currentState);
2016
+ const localMediaStatus = selectLocalMediaStatus(currentState);
2017
+ return (oldValue === true && newValue === false) && localMediaStatus !== "inactive" && !!localMediaOptions;
2018
+ },
2019
+ effect: (_, { dispatch }) => {
2006
2020
  dispatch(doStopLocalMedia());
2007
- }
2021
+ },
2008
2022
  });
2009
2023
  startAppListening({
2010
2024
  predicate: (_action, currentState, previousState) => {
@@ -2045,10 +2059,25 @@ startAppListening({
2045
2059
  });
2046
2060
  startAppListening({
2047
2061
  predicate: (_action, currentState, previousState) => {
2048
- const oldValue = selectCurrentCameraDeviceId(previousState);
2049
- const newValue = selectCurrentCameraDeviceId(currentState);
2062
+ var _a, _b;
2063
+ const oldDeviceId = selectCurrentCameraDeviceId(previousState);
2064
+ const newDeviceId = selectCurrentCameraDeviceId(currentState);
2050
2065
  const isReady = selectLocalMediaStatus(previousState) === "started";
2051
- return isReady && oldValue !== newValue;
2066
+ const isSwitchingStream = selectLocalMediaIsSwitchingStream(currentState);
2067
+ if (isSwitchingStream) {
2068
+ return false;
2069
+ }
2070
+ if (!newDeviceId) {
2071
+ return false;
2072
+ }
2073
+ const currentTrack = (_b = (_a = selectLocalMediaStream(currentState)) === null || _a === void 0 ? void 0 : _a.getVideoTracks()) === null || _b === void 0 ? void 0 : _b[0];
2074
+ if (currentTrack && currentTrack.readyState === "live") {
2075
+ const currentDeviceId = currentTrack.getSettings().deviceId;
2076
+ if (currentDeviceId === newDeviceId) {
2077
+ return false;
2078
+ }
2079
+ }
2080
+ return isReady && oldDeviceId !== newDeviceId;
2052
2081
  },
2053
2082
  effect: (_action, { dispatch }) => {
2054
2083
  dispatch(doSetDevice({ audio: false, video: true }));
@@ -2056,10 +2085,25 @@ startAppListening({
2056
2085
  });
2057
2086
  startAppListening({
2058
2087
  predicate: (_action, currentState, previousState) => {
2059
- const oldValue = selectCurrentMicrophoneDeviceId(previousState);
2060
- const newValue = selectCurrentMicrophoneDeviceId(currentState);
2088
+ var _a, _b;
2089
+ const oldDeviceId = selectCurrentMicrophoneDeviceId(previousState);
2090
+ const newDeviceId = selectCurrentMicrophoneDeviceId(currentState);
2061
2091
  const isReady = selectLocalMediaStatus(previousState) === "started";
2062
- return isReady && oldValue !== newValue;
2092
+ const isSwitchingStream = selectLocalMediaIsSwitchingStream(currentState);
2093
+ if (isSwitchingStream) {
2094
+ return false;
2095
+ }
2096
+ if (!newDeviceId) {
2097
+ return false;
2098
+ }
2099
+ const currentTrack = (_b = (_a = selectLocalMediaStream(currentState)) === null || _a === void 0 ? void 0 : _a.getVideoTracks()) === null || _b === void 0 ? void 0 : _b[0];
2100
+ if (currentTrack && currentTrack.readyState === "live") {
2101
+ const currentDeviceId = currentTrack.getSettings().deviceId;
2102
+ if (currentDeviceId === newDeviceId) {
2103
+ return false;
2104
+ }
2105
+ }
2106
+ return isReady && oldDeviceId !== newDeviceId;
2063
2107
  },
2064
2108
  effect: (_action, { dispatch }) => {
2065
2109
  dispatch(doSetDevice({ audio: true, video: false }));
@@ -2878,15 +2922,6 @@ startAppListening({
2878
2922
  },
2879
2923
  });
2880
2924
 
2881
- function isDeferrable({ client, breakoutCurrentId }) {
2882
- if (!client)
2883
- return false;
2884
- if (!breakoutCurrentId && client.breakoutGroup)
2885
- return true;
2886
- if (!client.isAudioEnabled && !client.isVideoEnabled)
2887
- return true;
2888
- return false;
2889
- }
2890
2925
  const createWebRtcEmitter = (dispatch) => {
2891
2926
  return {
2892
2927
  emit: (eventName, data) => {
@@ -2974,22 +3009,12 @@ const doConnectRtc = createAppThunk(() => (dispatch, getState) => {
2974
3009
  const state = getState();
2975
3010
  const socket = selectSignalConnectionRaw(state).socket;
2976
3011
  const dispatcher = selectRtcConnectionRaw(state).rtcManagerDispatcher;
2977
- const isCameraEnabled = selectIsCameraEnabled(state);
2978
- const isMicrophoneEnabled = selectIsMicrophoneEnabled(state);
2979
3012
  const isNodeSdk = selectAppIsNodeSdk(state);
2980
3013
  if (dispatcher || !socket) {
2981
3014
  return;
2982
3015
  }
2983
3016
  const webrtcProvider = {
2984
- getMediaConstraints: () => ({
2985
- audio: isMicrophoneEnabled,
2986
- video: isCameraEnabled,
2987
- }),
2988
- deferrable(clientId) {
2989
- const client = selectRemoteParticipants(getState()).find((p) => p.id === clientId);
2990
- const breakoutCurrentId = selectBreakoutCurrentId(getState()) || "";
2991
- return isDeferrable({ client, breakoutCurrentId });
2992
- },
3017
+ getMediaConstraints: () => selectLocalMediaConstraintsOptions(state),
2993
3018
  };
2994
3019
  const rtcManagerDispatcher = new RtcManagerDispatcher({
2995
3020
  emitter: createWebRtcEmitter(dispatch),
@@ -4619,6 +4644,10 @@ class LocalMediaClient extends BaseClient {
4619
4644
  }
4620
4645
  startMedia() {
4621
4646
  return __awaiter(this, arguments, void 0, function* (options = { audio: true, video: true }) {
4647
+ const localMediaStatus = this.store.getState().localMedia.status;
4648
+ if (["started", "starting"].includes(localMediaStatus)) {
4649
+ return;
4650
+ }
4622
4651
  return yield this.store.dispatch(doStartLocalMedia(options));
4623
4652
  });
4624
4653
  }