Kaynağa Gözat

[RN] Refactor video muting

Simplify the code by using a bitfied instead of a couple of boolean flags. This
allows us to mute the video from multiple places and only make the unmute
effective once they have all unmuted.

Alas, this cannot be applied to the web without a massive refactor, because it
uses the track muted state as the source of truth instead of the media state.
j8
Saúl Ibarra Corretgé 7 yıl önce
ebeveyn
işleme
d600504d85

+ 0
- 14
react/features/base/conference/actionTypes.js Dosyayı Görüntüle

75
  */
75
  */
76
 export const SET_AUDIO_ONLY = Symbol('SET_AUDIO_ONLY');
76
 export const SET_AUDIO_ONLY = Symbol('SET_AUDIO_ONLY');
77
 
77
 
78
-/**
79
- * The type of (redux) action which signals that video will be muted because the
80
- * audio-only mode was enabled/disabled.
81
- *
82
- * {
83
- *     type: _SET_AUDIO_ONLY_VIDEO_MUTED,
84
- *     muted: boolean
85
- * }
86
- *
87
- * @protected
88
- */
89
-export const _SET_AUDIO_ONLY_VIDEO_MUTED
90
-    = Symbol('_SET_AUDIO_ONLY_VIDEO_MUTED');
91
-
92
 /**
78
 /**
93
  * The type of (redux) action to set whether or not the displayed large video is
79
  * The type of (redux) action to set whether or not the displayed large video is
94
  * in high-definition.
80
  * in high-definition.

+ 16
- 44
react/features/base/conference/actions.js Dosyayı Görüntüle

1
 import { JitsiConferenceEvents } from '../lib-jitsi-meet';
1
 import { JitsiConferenceEvents } from '../lib-jitsi-meet';
2
-import { setVideoMuted } from '../media';
2
+import { setAudioMuted, setVideoMuted } from '../media';
3
 import {
3
 import {
4
     dominantSpeakerChanged,
4
     dominantSpeakerChanged,
5
     getLocalParticipant,
5
     getLocalParticipant,
19
     CONFERENCE_WILL_LEAVE,
19
     CONFERENCE_WILL_LEAVE,
20
     LOCK_STATE_CHANGED,
20
     LOCK_STATE_CHANGED,
21
     SET_AUDIO_ONLY,
21
     SET_AUDIO_ONLY,
22
-    _SET_AUDIO_ONLY_VIDEO_MUTED,
23
     SET_LARGE_VIDEO_HD_STATUS,
22
     SET_LARGE_VIDEO_HD_STATUS,
24
     SET_LASTN,
23
     SET_LASTN,
25
     SET_PASSWORD,
24
     SET_PASSWORD,
61
         JitsiConferenceEvents.LOCK_STATE_CHANGED,
60
         JitsiConferenceEvents.LOCK_STATE_CHANGED,
62
         (...args) => dispatch(lockStateChanged(conference, ...args)));
61
         (...args) => dispatch(lockStateChanged(conference, ...args)));
63
 
62
 
63
+    // Dispatches into features/base/media follow:
64
+
65
+    // FIXME: This is needed because when Jicofo tells us to start muted
66
+    // lib-jitsi-meet does the actual muting. Perhaps this should be refactored
67
+    // so applications are hinted to start muted, but lib-jitsi-meet doesn't
68
+    // take action.
69
+    conference.on(
70
+        JitsiConferenceEvents.STARTED_MUTED,
71
+        () => {
72
+            dispatch(setAudioMuted(Boolean(conference.startAudioMuted)));
73
+            dispatch(setVideoMuted(Boolean(conference.startVideoMuted)));
74
+        });
75
+
64
     // Dispatches into features/base/tracks follow:
76
     // Dispatches into features/base/tracks follow:
65
 
77
 
66
     conference.on(
78
     conference.on(
296
  *
308
  *
297
  * @param {boolean} audioOnly - True if the conference should be audio only;
309
  * @param {boolean} audioOnly - True if the conference should be audio only;
298
  * false, otherwise.
310
  * false, otherwise.
299
- * @private
300
  * @returns {{
311
  * @returns {{
301
  *     type: SET_AUDIO_ONLY,
312
  *     type: SET_AUDIO_ONLY,
302
  *     audioOnly: boolean
313
  *     audioOnly: boolean
303
  * }}
314
  * }}
304
  */
315
  */
305
-function _setAudioOnly(audioOnly) {
316
+export function setAudioOnly(audioOnly) {
306
     return {
317
     return {
307
         type: SET_AUDIO_ONLY,
318
         type: SET_AUDIO_ONLY,
308
         audioOnly
319
         audioOnly
309
     };
320
     };
310
 }
321
 }
311
 
322
 
312
-/**
313
- * Signals that the app should mute video because it's now in audio-only mode,
314
- * or unmute it because it no longer is. If video was already muted, nothing
315
- * will happen; otherwise, it will be muted. When audio-only mode is disabled,
316
- * the previous state will be restored.
317
- *
318
- * @param {boolean} muted - True if video should be muted; false, otherwise.
319
- * @protected
320
- * @returns {Function}
321
- */
322
-export function _setAudioOnlyVideoMuted(muted: boolean) {
323
-    return (dispatch, getState) => {
324
-        if (muted) {
325
-            const { video } = getState()['features/base/media'];
326
-
327
-            if (video.muted) {
328
-                // Video is already muted, do nothing.
329
-                return;
330
-            }
331
-        } else {
332
-            const { audioOnlyVideoMuted }
333
-                = getState()['features/base/conference'];
334
-
335
-            if (!audioOnlyVideoMuted) {
336
-                // We didn't mute video, do nothing.
337
-                return;
338
-            }
339
-        }
340
-
341
-        // Remember that local video was muted due to the audio-only mode
342
-        // vs user's choice.
343
-        dispatch({
344
-            type: _SET_AUDIO_ONLY_VIDEO_MUTED,
345
-            muted
346
-        });
347
-        dispatch(setVideoMuted(muted));
348
-    };
349
-}
350
-
351
 /**
323
 /**
352
  * Action to set whether or not the currently displayed large video is in
324
  * Action to set whether or not the currently displayed large video is in
353
  * high-definition.
325
  * high-definition.
488
     return (dispatch: Dispatch<*>, getState: Function) => {
460
     return (dispatch: Dispatch<*>, getState: Function) => {
489
         const { audioOnly } = getState()['features/base/conference'];
461
         const { audioOnly } = getState()['features/base/conference'];
490
 
462
 
491
-        return dispatch(_setAudioOnly(!audioOnly));
463
+        return dispatch(setAudioOnly(!audioOnly));
492
     };
464
     };
493
 }
465
 }

+ 40
- 6
react/features/base/conference/middleware.js Dosyayı Görüntüle

2
 import UIEvents from '../../../../service/UI/UIEvents';
2
 import UIEvents from '../../../../service/UI/UIEvents';
3
 
3
 
4
 import { CONNECTION_ESTABLISHED } from '../connection';
4
 import { CONNECTION_ESTABLISHED } from '../connection';
5
+import { setVideoMuted, VIDEO_MUTISM_AUTHORITY } from '../media';
5
 import {
6
 import {
6
     getLocalParticipant,
7
     getLocalParticipant,
7
     getParticipantById,
8
     getParticipantById,
12
 
13
 
13
 import {
14
 import {
14
     createConference,
15
     createConference,
15
-    _setAudioOnlyVideoMuted,
16
+    setAudioOnly,
16
     setLastN
17
     setLastN
17
 } from './actions';
18
 } from './actions';
18
-import { CONFERENCE_JOINED, SET_AUDIO_ONLY, SET_LASTN } from './actionTypes';
19
+import {
20
+    CONFERENCE_FAILED,
21
+    CONFERENCE_JOINED,
22
+    CONFERENCE_LEFT,
23
+    SET_AUDIO_ONLY,
24
+    SET_LASTN
25
+} from './actionTypes';
19
 import {
26
 import {
20
     _addLocalTracksToConference,
27
     _addLocalTracksToConference,
21
     _handleParticipantError,
28
     _handleParticipantError,
36
     case CONFERENCE_JOINED:
43
     case CONFERENCE_JOINED:
37
         return _conferenceJoined(store, next, action);
44
         return _conferenceJoined(store, next, action);
38
 
45
 
46
+    case CONFERENCE_FAILED:
47
+    case CONFERENCE_LEFT:
48
+        return _conferenceFailedOrLeft(store, next, action);
49
+
39
     case PIN_PARTICIPANT:
50
     case PIN_PARTICIPANT:
40
         return _pinParticipant(store, next, action);
51
         return _pinParticipant(store, next, action);
41
 
52
 
79
     return result;
90
     return result;
80
 }
91
 }
81
 
92
 
93
+/**
94
+ * Does extra sync up on properties that may need to be updated, after
95
+ * the conference failed or was left.
96
+ *
97
+ * @param {Store} store - The Redux store in which the specified action is being
98
+ * dispatched.
99
+ * @param {Dispatch} next - The Redux dispatch function to dispatch the
100
+ * specified action to the specified store.
101
+ * @param {Action} action - The Redux action {@link CONFERENCE_FAILED} or
102
+ * {@link CONFERENCE_LEFT} which is being dispatched in the specified store.
103
+ * @private
104
+ * @returns {Object} The new state that is the result of the reduction of the
105
+ * specified action.
106
+ */
107
+function _conferenceFailedOrLeft(store, next, action) {
108
+    const result = next(action);
109
+    const { audioOnly } = store.getState()['features/base/conference'];
110
+
111
+    audioOnly && store.dispatch(setAudioOnly(false));
112
+
113
+    return result;
114
+}
115
+
82
 /**
116
 /**
83
  * Does extra sync up on properties that may need to be updated, after
117
  * Does extra sync up on properties that may need to be updated, after
84
  * the conference was joined.
118
  * the conference was joined.
171
  * @returns {Object} The new state that is the result of the reduction of the
205
  * @returns {Object} The new state that is the result of the reduction of the
172
  * specified action.
206
  * specified action.
173
  */
207
  */
174
-function _setAudioOnly(store, next, action) {
208
+function _setAudioOnly({ dispatch }, next, action) {
175
     const result = next(action);
209
     const result = next(action);
176
 
210
 
177
     const { audioOnly } = action;
211
     const { audioOnly } = action;
178
 
212
 
179
     // Set lastN to 0 in case audio-only is desired; leave it as undefined,
213
     // Set lastN to 0 in case audio-only is desired; leave it as undefined,
180
     // otherwise, and the default lastN value will be chosen automatically.
214
     // otherwise, and the default lastN value will be chosen automatically.
181
-    store.dispatch(setLastN(audioOnly ? 0 : undefined));
215
+    dispatch(setLastN(audioOnly ? 0 : undefined));
182
 
216
 
183
-    // Mute local video
184
-    store.dispatch(_setAudioOnlyVideoMuted(audioOnly));
217
+    // Mute the local video.
218
+    dispatch(setVideoMuted(audioOnly, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY));
185
 
219
 
186
     if (typeof APP !== 'undefined') {
220
     if (typeof APP !== 'undefined') {
187
         // TODO This should be a temporary solution that lasts only until
221
         // TODO This should be a temporary solution that lasts only until

+ 0
- 23
react/features/base/conference/reducer.js Dosyayı Görüntüle

11
     CONFERENCE_WILL_LEAVE,
11
     CONFERENCE_WILL_LEAVE,
12
     LOCK_STATE_CHANGED,
12
     LOCK_STATE_CHANGED,
13
     SET_AUDIO_ONLY,
13
     SET_AUDIO_ONLY,
14
-    _SET_AUDIO_ONLY_VIDEO_MUTED,
15
     SET_LARGE_VIDEO_HD_STATUS,
14
     SET_LARGE_VIDEO_HD_STATUS,
16
     SET_PASSWORD,
15
     SET_PASSWORD,
17
     SET_ROOM
16
     SET_ROOM
45
     case SET_AUDIO_ONLY:
44
     case SET_AUDIO_ONLY:
46
         return _setAudioOnly(state, action);
45
         return _setAudioOnly(state, action);
47
 
46
 
48
-    case _SET_AUDIO_ONLY_VIDEO_MUTED:
49
-        return _setAudioOnlyVideoMuted(state, action);
50
-
51
     case SET_LARGE_VIDEO_HD_STATUS:
47
     case SET_LARGE_VIDEO_HD_STATUS:
52
         return _setLargeVideoHDStatus(state, action);
48
         return _setLargeVideoHDStatus(state, action);
53
 
49
 
82
             : undefined;
78
             : undefined;
83
 
79
 
84
     return assign(state, {
80
     return assign(state, {
85
-        audioOnly: undefined,
86
-        audioOnlyVideoMuted: undefined,
87
         conference: undefined,
81
         conference: undefined,
88
         joining: undefined,
82
         joining: undefined,
89
         leaving: undefined,
83
         leaving: undefined,
161
     }
155
     }
162
 
156
 
163
     return assign(state, {
157
     return assign(state, {
164
-        audioOnly: undefined,
165
-        audioOnlyVideoMuted: undefined,
166
         conference: undefined,
158
         conference: undefined,
167
         joining: undefined,
159
         joining: undefined,
168
         leaving: undefined,
160
         leaving: undefined,
250
     return set(state, 'audioOnly', action.audioOnly);
242
     return set(state, 'audioOnly', action.audioOnly);
251
 }
243
 }
252
 
244
 
253
-/**
254
- * Reduces a specific Redux action _SET_AUDIO_ONLY_VIDEO_MUTED of the feature
255
- * base/conference.
256
- *
257
- * @param {Object} state - The Redux state of the feature base/conference.
258
- * @param {Action} action - The Redux action SET_AUDIO_ONLY_VIDEO_MUTED to
259
- * reduce.
260
- * @private
261
- * @returns {Object} The new state of the feature base/conference after the
262
- * reduction of the specified action.
263
- */
264
-function _setAudioOnlyVideoMuted(state, action) {
265
-    return set(state, 'audioOnlyVideoMuted', action.muted);
266
-}
267
-
268
 /**
245
 /**
269
  * Reduces a specific Redux action SET_LARGE_VIDEO_HD_STATUS of the feature
246
  * Reduces a specific Redux action SET_LARGE_VIDEO_HD_STATUS of the feature
270
  * base/conference.
247
  * base/conference.

+ 20
- 10
react/features/base/media/actions.js Dosyayı Görüntüle

10
     SET_VIDEO_MUTED,
10
     SET_VIDEO_MUTED,
11
     TOGGLE_CAMERA_FACING_MODE
11
     TOGGLE_CAMERA_FACING_MODE
12
 } from './actionTypes';
12
 } from './actionTypes';
13
-import { CAMERA_FACING_MODE } from './constants';
13
+import { CAMERA_FACING_MODE, VIDEO_MUTISM_AUTHORITY } from './constants';
14
 
14
 
15
 /**
15
 /**
16
  * Action to adjust the availability of the local audio.
16
  * Action to adjust the availability of the local audio.
84
  *
84
  *
85
  * @param {boolean} muted - True if the local video is to be muted or false if
85
  * @param {boolean} muted - True if the local video is to be muted or false if
86
  * the local video is to be unmuted.
86
  * the local video is to be unmuted.
87
- * @returns {{
88
- *     type: SET_VIDEO_MUTED,
89
- *     muted: boolean
90
- * }}
87
+ * @param {number} authority - The {@link VIDEO_MUTISM_AUTHORITY} which is
88
+ * muting/unmuting the local video.
89
+ * @returns {Function}
91
  */
90
  */
92
-export function setVideoMuted(muted: boolean) {
93
-    return {
94
-        type: SET_VIDEO_MUTED,
95
-        muted
91
+export function setVideoMuted(
92
+        muted: boolean,
93
+        authority: number = VIDEO_MUTISM_AUTHORITY.USER) {
94
+    return (dispatch: Dispatch<*>, getState: Function) => {
95
+        const oldValue = getState()['features/base/media'].video.muted;
96
+
97
+        // eslint-disable-next-line no-bitwise
98
+        const newValue = muted ? oldValue | authority : oldValue & ~authority;
99
+
100
+        return dispatch({
101
+            type: SET_VIDEO_MUTED,
102
+            muted: newValue
103
+        });
96
     };
104
     };
97
 }
105
 }
98
 
106
 
135
     return (dispatch: Dispatch<*>, getState: Function) => {
143
     return (dispatch: Dispatch<*>, getState: Function) => {
136
         const muted = getState()['features/base/media'].video.muted;
144
         const muted = getState()['features/base/media'].video.muted;
137
 
145
 
138
-        return dispatch(setVideoMuted(!muted));
146
+        // XXX The following directly invokes the action creator in order to
147
+        // silence Flow.
148
+        return setVideoMuted(!muted)(dispatch, getState);
139
     };
149
     };
140
 }
150
 }

+ 18
- 2
react/features/base/media/constants.js Dosyayı Görüntüle

9
 };
9
 };
10
 
10
 
11
 /**
11
 /**
12
- * The set of media types for a track.
12
+ * The set of media types.
13
  *
13
  *
14
  * @enum {string}
14
  * @enum {string}
15
  */
15
  */
18
     VIDEO: 'video'
18
     VIDEO: 'video'
19
 };
19
 };
20
 
20
 
21
+/* eslint-disable no-bitwise */
22
+
23
+/**
24
+ * The types of authorities which may mute/unmute the local video.
25
+ *
26
+ * @enum {number}
27
+ */
28
+export const VIDEO_MUTISM_AUTHORITY = {
29
+    AUDIO_ONLY: 1 << 0,
30
+    BACKGROUND: 1 << 1,
31
+    USER: 1 << 2
32
+};
33
+
34
+/* eslint-enable no-bitwise */
35
+
21
 /**
36
 /**
22
- * The set of video types for a video track.
37
+ * The types of video tracks.
38
+ *
23
  * @enum {string}
39
  * @enum {string}
24
  */
40
  */
25
 export const VIDEO_TYPE = {
41
 export const VIDEO_TYPE = {

+ 3
- 2
react/features/base/media/middleware.js Dosyayı Görüntüle

80
     (audio.muted !== audioMuted) && dispatch(setAudioMuted(audioMuted));
80
     (audio.muted !== audioMuted) && dispatch(setAudioMuted(audioMuted));
81
     (video.facingMode !== CAMERA_FACING_MODE.USER)
81
     (video.facingMode !== CAMERA_FACING_MODE.USER)
82
         && dispatch(setCameraFacingMode(CAMERA_FACING_MODE.USER));
82
         && dispatch(setCameraFacingMode(CAMERA_FACING_MODE.USER));
83
-    (video.muted !== videoMuted) && dispatch(setVideoMuted(videoMuted));
83
+    (Boolean(video.muted) !== videoMuted)
84
+        && dispatch(setVideoMuted(videoMuted));
84
 
85
 
85
     return next(action);
86
     return next(action);
86
 }
87
 }
95
  */
96
  */
96
 function _syncTrackMutedState({ dispatch, getState }, track) {
97
 function _syncTrackMutedState({ dispatch, getState }, track) {
97
     const state = getState()['features/base/media'];
98
     const state = getState()['features/base/media'];
98
-    const muted = state[track.mediaType].muted;
99
+    const muted = Boolean(state[track.mediaType].muted);
99
 
100
 
100
     // XXX If muted state of track when it was added is different from our media
101
     // XXX If muted state of track when it was added is different from our media
101
     // muted state, we need to mute track and explicitly modify 'muted' property
102
     // muted state, we need to mute track and explicitly modify 'muted' property

+ 1
- 1
react/features/base/media/reducer.js Dosyayı Görüntüle

73
 const VIDEO_INITIAL_MEDIA_STATE = {
73
 const VIDEO_INITIAL_MEDIA_STATE = {
74
     available: true,
74
     available: true,
75
     facingMode: CAMERA_FACING_MODE.USER,
75
     facingMode: CAMERA_FACING_MODE.USER,
76
-    muted: false
76
+    muted: 0
77
 };
77
 };
78
 
78
 
79
 /**
79
 /**

+ 5
- 0
react/features/base/tracks/actions.js Dosyayı Görüntüle

358
  */
358
  */
359
 export function setTrackMuted(track, muted) {
359
 export function setTrackMuted(track, muted) {
360
     return dispatch => {
360
     return dispatch => {
361
+        muted = Boolean(muted); // eslint-disable-line no-param-reassign
362
+
361
         if (track.isMuted() === muted) {
363
         if (track.isMuted() === muted) {
362
             return Promise.resolve();
364
             return Promise.resolve();
363
         }
365
         }
364
 
366
 
365
         const f = muted ? 'mute' : 'unmute';
367
         const f = muted ? 'mute' : 'unmute';
366
 
368
 
369
+        // FIXME: This operation disregards the authority. It is not a problem
370
+        // (on mobile) at the moment, but it will be once we start not creating
371
+        // tracks early. Refactor this then.
367
         return track[f]().catch(error => {
372
         return track[f]().catch(error => {
368
             console.error(`set track ${f} failed`, error);
373
             console.error(`set track ${f} failed`, error);
369
 
374
 

+ 7
- 1
react/features/base/tracks/middleware.js Dosyayı Görüntüle

123
             } else {
123
             } else {
124
                 APP.UI.setAudioMuted(participantID, isMuted);
124
                 APP.UI.setAudioMuted(participantID, isMuted);
125
             }
125
             }
126
+
127
+            // XXX This function synchronizes track states with media states.
128
+            // This is not required in React, because media is the source of
129
+            // truth, synchronization should always happen in the media -> track
130
+            // direction. The old web, however, does the opposite, hence the
131
+            // need for this.
132
+            return _trackUpdated(store, next, action);
126
         }
133
         }
127
 
134
 
128
-        return _trackUpdated(store, next, action);
129
     }
135
     }
130
 
136
 
131
     return next(action);
137
     return next(action);

+ 11
- 3
react/features/mobile/audio-mode/middleware.js Dosyayı Görüntüle

39
             break;
39
             break;
40
         }
40
         }
41
 
41
 
42
-        case SET_AUDIO_ONLY:
43
-            mode
44
-                = action.audioOnly
42
+        case SET_AUDIO_ONLY: {
43
+            const { conference } = store.getState()['features/base/conference'];
44
+
45
+            if (conference) {
46
+                mode
47
+                    = action.audioOnly
45
                     ? AudioMode.AUDIO_CALL
48
                     ? AudioMode.AUDIO_CALL
46
                     : AudioMode.VIDEO_CALL;
49
                     : AudioMode.VIDEO_CALL;
50
+            } else {
51
+                mode = null;
52
+            }
53
+
47
             break;
54
             break;
55
+        }
48
 
56
 
49
         default:
57
         default:
50
             mode = null;
58
             mode = null;

+ 0
- 14
react/features/mobile/background/actionTypes.js Dosyayı Görüntüle

10
  */
10
  */
11
 export const _SET_APP_STATE_LISTENER = Symbol('_SET_APP_STATE_LISTENER');
11
 export const _SET_APP_STATE_LISTENER = Symbol('_SET_APP_STATE_LISTENER');
12
 
12
 
13
-/**
14
- * The type of redux action which signals that video will be muted because the
15
- * app is going to the background.
16
- *
17
- * {
18
- *     type: _SET_BACKGROUND_VIDEO_MUTED,
19
- *     muted: boolean
20
- * }
21
- *
22
- * @protected
23
- */
24
-export const _SET_BACKGROUND_VIDEO_MUTED
25
-    = Symbol('_SET_BACKGROUND_VIDEO_MUTED');
26
-
27
 /**
13
 /**
28
  * The type of redux action which signals that the app state has changed (in
14
  * The type of redux action which signals that the app state has changed (in
29
  * terms of execution mode). The app state can be one of 'active', 'inactive',
15
  * terms of execution mode). The app state can be one of 'active', 'inactive',

+ 3
- 31
react/features/mobile/background/actions.js Dosyayı Görüntüle

1
 import { setLastN } from '../../base/conference';
1
 import { setLastN } from '../../base/conference';
2
-import { setVideoMuted } from '../../base/media';
2
+import { setVideoMuted, VIDEO_MUTISM_AUTHORITY } from '../../base/media';
3
 
3
 
4
 import {
4
 import {
5
     _SET_APP_STATE_LISTENER,
5
     _SET_APP_STATE_LISTENER,
6
-    _SET_BACKGROUND_VIDEO_MUTED,
7
     APP_STATE_CHANGED
6
     APP_STATE_CHANGED
8
 } from './actionTypes';
7
 } from './actionTypes';
9
 
8
 
42
         // for last N will be chosen automatically.
41
         // for last N will be chosen automatically.
43
         const { audioOnly } = getState()['features/base/conference'];
42
         const { audioOnly } = getState()['features/base/conference'];
44
 
43
 
45
-        if (audioOnly) {
46
-            return;
47
-        }
48
-
49
-        dispatch(setLastN(muted ? 0 : undefined));
50
-
51
-        if (muted) {
52
-            const { video } = getState()['features/base/media'];
53
-
54
-            if (video.muted) {
55
-                // Video is already muted, do nothing.
56
-                return;
57
-            }
58
-        } else {
59
-            const { videoMuted } = getState()['features/background'];
60
-
61
-            if (!videoMuted) {
62
-                // We didn't mute video, do nothing.
63
-                return;
64
-            }
65
-        }
66
-
67
-        // Remember that local video was muted due to the app going to the
68
-        // background vs user's choice.
69
-        dispatch({
70
-            type: _SET_BACKGROUND_VIDEO_MUTED,
71
-            muted
72
-        });
73
-        dispatch(setVideoMuted(muted));
44
+        !audioOnly && dispatch(setLastN(muted ? 0 : undefined));
45
+        dispatch(setVideoMuted(muted, VIDEO_MUTISM_AUTHORITY.BACKGROUND));
74
     };
46
     };
75
 }
47
 }
76
 
48
 

+ 0
- 7
react/features/mobile/background/reducer.js Dosyayı Görüntüle

2
 
2
 
3
 import {
3
 import {
4
     _SET_APP_STATE_LISTENER,
4
     _SET_APP_STATE_LISTENER,
5
-    _SET_BACKGROUND_VIDEO_MUTED,
6
     APP_STATE_CHANGED
5
     APP_STATE_CHANGED
7
 } from './actionTypes';
6
 } from './actionTypes';
8
 
7
 
14
             appStateListener: action.listener
13
             appStateListener: action.listener
15
         };
14
         };
16
 
15
 
17
-    case _SET_BACKGROUND_VIDEO_MUTED:
18
-        return {
19
-            ...state,
20
-            videoMuted: action.muted
21
-        };
22
-
23
     case APP_STATE_CHANGED:
16
     case APP_STATE_CHANGED:
24
         return {
17
         return {
25
             ...state,
18
             ...state,

+ 5
- 2
react/features/mobile/full-screen/middleware.js Dosyayı Görüntüle

61
         break;
61
         break;
62
     }
62
     }
63
 
63
 
64
-    case SET_AUDIO_ONLY:
65
-        fullScreen = !action.audioOnly;
64
+    case SET_AUDIO_ONLY: {
65
+        const { conference } = store.getState()['features/base/conference'];
66
+
67
+        fullScreen = conference ? !action.audioOnly : false;
66
         break;
68
         break;
67
     }
69
     }
70
+    }
68
 
71
 
69
     if (fullScreen !== null) {
72
     if (fullScreen !== null) {
70
         _setFullScreen(fullScreen)
73
         _setFullScreen(fullScreen)

+ 5
- 2
react/features/mobile/proximity/middleware.js Dosyayı Görüntüle

31
         _setProximityEnabled(false);
31
         _setProximityEnabled(false);
32
         break;
32
         break;
33
 
33
 
34
-    case SET_AUDIO_ONLY:
35
-        _setProximityEnabled(action.audioOnly);
34
+    case SET_AUDIO_ONLY: {
35
+        const { conference } = store.getState()['features/base/conference'];
36
+
37
+        conference && _setProximityEnabled(action.audioOnly);
36
         break;
38
         break;
37
     }
39
     }
40
+    }
38
 
41
 
39
     return next(action);
42
     return next(action);
40
 });
43
 });

Loading…
İptal
Kaydet