Преглед на файлове

Fix toolbar's mute buttons when starting muted

The toolbar's mute buttons depict respective features/base/media states.
However, (un)muting is practically carried out by features/base/tracks.
When the mobile app enters a conference configured to invite the joining
participant to mute themselves, the tracks would be muted but the
toolbar's mute buttons would not reflect that.
master
Lyubomir Marinov преди 9 години
родител
ревизия
4997ae79e3

+ 1
- 1
react/features/base/lib-jitsi-meet/actions.js Целия файл

@@ -34,7 +34,7 @@ export function disposeLib() {
34 34
  */
35 35
 export function initLib() {
36 36
     return (dispatch, getState) => {
37
-        const config = getState()['features/base/lib'].config;
37
+        const config = getState()['features/base/lib-jitsi-meet'].config;
38 38
 
39 39
         if (!config) {
40 40
             throw new Error('Cannot initialize lib-jitsi-meet without config');

+ 6
- 9
react/features/base/lib-jitsi-meet/middleware.js Целия файл

@@ -19,26 +19,23 @@ import { SET_CONFIG } from './actionTypes';
19 19
 MiddlewareRegistry.register(store => next => action => {
20 20
     switch (action.type) {
21 21
     case PARTICIPANT_LEFT:
22
-        if (action.participant.local) {
23
-            store.dispatch(disposeLib());
24
-        }
22
+        action.participant.local && store.dispatch(disposeLib());
25 23
         break;
26 24
 
27 25
     case SET_CONFIG: {
28 26
         const { dispatch, getState } = store;
29
-        const libInitialized = getState()['features/base/lib'].initialized;
27
+        const initialized
28
+            = getState()['features/base/lib-jitsi-meet'].initialized;
30 29
 
31 30
         // XXX If we already have config, that means new config is coming, which
32 31
         // means that we should dispose instance of lib initialized with
33 32
         // previous config first.
34 33
         // TODO Currently 'disposeLib' actually does not dispose lib-jitsi-meet.
35 34
         // This functionality should be implemented.
36
-        const promise = libInitialized
37
-            ? dispatch(disposeLib())
38
-            : Promise.resolve();
35
+        const promise
36
+            = initialized ? dispatch(disposeLib()) : Promise.resolve();
39 37
 
40
-        promise
41
-            .then(dispatch(initLib()));
38
+        promise.then(dispatch(initLib()));
42 39
 
43 40
         break;
44 41
     }

+ 2
- 2
react/features/base/lib-jitsi-meet/reducer.js Целия файл

@@ -8,7 +8,7 @@ import {
8 8
 } from './actionTypes';
9 9
 
10 10
 /**
11
- * Initial state of 'features/base/lib'.
11
+ * Initial state of 'features/base/lib-jitsi-meet'.
12 12
  *
13 13
  * @type {{
14 14
  *      initializationError: null,
@@ -31,7 +31,7 @@ const INITIAL_STATE = {
31 31
 };
32 32
 
33 33
 ReducerRegistry.register(
34
-    'features/base/lib',
34
+    'features/base/lib-jitsi-meet',
35 35
     (state = INITIAL_STATE, action) => {
36 36
         switch (action.type) {
37 37
         case LIB_DISPOSED:

+ 4
- 9
react/features/base/media/middleware.js Целия файл

@@ -42,15 +42,10 @@ function resetInitialMediaState(store) {
42 42
     const { dispatch, getState } = store;
43 43
     const state = getState()['features/base/media'];
44 44
 
45
-    if (state.audio.muted) {
46
-        dispatch(audioMutedChanged(false));
47
-    }
48
-    if (state.video.facingMode !== CAMERA_FACING_MODE.USER) {
49
-        dispatch(cameraFacingModeChanged(CAMERA_FACING_MODE.USER));
50
-    }
51
-    if (state.video.muted) {
52
-        dispatch(videoMutedChanged(false));
53
-    }
45
+    state.audio.muted && dispatch(audioMutedChanged(false));
46
+    (state.video.facingMode !== CAMERA_FACING_MODE.USER)
47
+        && dispatch(cameraFacingModeChanged(CAMERA_FACING_MODE.USER));
48
+    state.video.muted && dispatch(videoMutedChanged(false));
54 49
 }
55 50
 
56 51
 /**

+ 8
- 4
react/features/base/tracks/functions.js Целия файл

@@ -72,14 +72,18 @@ export function getTracksByMediaType(tracks, mediaType) {
72 72
 }
73 73
 
74 74
 /**
75
- * Mute or unmute local track if any.
75
+ * Mutes or unmutes a specific <tt>JitsiLocalTrack</tt>. If the muted state of
76
+ * the specified <tt>track</tt> is already in accord with the specified
77
+ * <tt>muted</tt> value, then does nothing.
76 78
  *
77
- * @param {JitsiLocalTrack} track - Track instance.
78
- * @param {boolean} muted - If audio stream should be muted or unmuted.
79
+ * @param {JitsiLocalTrack} track - The <tt>JitsiLocalTrack</tt> to mute or
80
+ * unmute.
81
+ * @param {boolean} muted - If the specified <tt>track</tt> is to be muted, then
82
+ * <tt>true</tt>; otherwise, <tt>false</tt>.
79 83
  * @returns {Promise}
80 84
  */
81 85
 export function setTrackMuted(track, muted) {
82
-    if (!track) {
86
+    if (track.isMuted() === muted) {
83 87
         return Promise.resolve();
84 88
     }
85 89
 

+ 84
- 3
react/features/base/tracks/middleware.js Целия файл

@@ -4,9 +4,11 @@ import {
4 4
 } from '../lib-jitsi-meet';
5 5
 import {
6 6
     AUDIO_MUTED_CHANGED,
7
+    audioMutedChanged,
7 8
     CAMERA_FACING_MODE_CHANGED,
8 9
     MEDIA_TYPE,
9
-    VIDEO_MUTED_CHANGED
10
+    VIDEO_MUTED_CHANGED,
11
+    videoMutedChanged
10 12
 } from '../media';
11 13
 import { MiddlewareRegistry } from '../redux';
12 14
 
@@ -14,6 +16,7 @@ import {
14 16
     createLocalTracks,
15 17
     destroyLocalTracks
16 18
 } from './actions';
19
+import { TRACK_UPDATED } from './actionTypes';
17 20
 import {
18 21
     getLocalTrack,
19 22
     setTrackMuted
@@ -50,6 +53,9 @@ MiddlewareRegistry.register(store => next => action => {
50 53
         store.dispatch(destroyLocalTracks());
51 54
         break;
52 55
 
56
+    case TRACK_UPDATED:
57
+        return _trackUpdated(store, next, action);
58
+
53 59
     case VIDEO_MUTED_CHANGED:
54 60
         _mutedChanged(store, action, MEDIA_TYPE.VIDEO);
55 61
         break;
@@ -58,6 +64,22 @@ MiddlewareRegistry.register(store => next => action => {
58 64
     return next(action);
59 65
 });
60 66
 
67
+/**
68
+ * Gets the local track associated with a specific <tt>MEDIA_TYPE</tt> in a
69
+ * specific Redux store.
70
+ *
71
+ * @param {Store} store - The Redux store from which the local track associated
72
+ * with the specified <tt>mediaType</tt> is to be retrieved.
73
+ * @param {MEDIA_TYPE} mediaType - The <tt>MEDIA_TYPE</tt> of the local track to
74
+ * be retrieved from the specified <tt>store</tt>.
75
+ * @private
76
+ * @returns {Track} The local <tt>Track</tt> associated with the specified
77
+ * <tt>mediaType</tt> in the specified <tt>store</tt>.
78
+ */
79
+function _getLocalTrack(store, mediaType) {
80
+    return getLocalTrack(store.getState()['features/base/tracks'], mediaType);
81
+}
82
+
61 83
 /**
62 84
  * Mutes or unmutes a local track with a specific media type.
63 85
  *
@@ -70,8 +92,67 @@ MiddlewareRegistry.register(store => next => action => {
70 92
  * @returns {void}
71 93
  */
72 94
 function _mutedChanged(store, action, mediaType) {
73
-    const tracks = store.getState()['features/base/tracks'];
74
-    const localTrack = getLocalTrack(tracks, mediaType);
95
+    const localTrack = _getLocalTrack(store, mediaType);
75 96
 
76 97
     localTrack && setTrackMuted(localTrack.jitsiTrack, action.muted);
77 98
 }
99
+
100
+/**
101
+ * Intercepts the action <tt>TRACK_UPDATED</tt> in order to synchronize the
102
+ * muted states of the local tracks of features/base/tracks with the muted
103
+ * states of features/base/media.
104
+ *
105
+ * @param {Store} store - The Redux store in which the specified <tt>action</tt>
106
+ * is being dispatched.
107
+ * @param {Dispatch} next - The Redux dispatch function to dispatch the
108
+ * specified <tt>action</tt> to the specified <tt>store</tt>.
109
+ * @param {Action} action - The Redux action <tt>TRACK_UPDATED</tt> which is
110
+ * being dispatched in the specified <tt>store</tt>.
111
+ * @private
112
+ * @returns {void}
113
+ */
114
+function _trackUpdated(store, next, action) {
115
+    // Determine the muted state of the local track before the update.
116
+    const track = action.track;
117
+    let mediaType;
118
+    let oldMuted;
119
+
120
+    if ('muted' in track) {
121
+        // XXX The return value of JitsiTrack.getType() is of type MEDIA_TYPE
122
+        // that happens to be compatible with the type MEDIA_TYPE defined by
123
+        // jitsi-meet-react.
124
+        mediaType = track.jitsiTrack.getType();
125
+
126
+        const localTrack = _getLocalTrack(store, mediaType);
127
+
128
+        if (localTrack) {
129
+            oldMuted = localTrack.muted;
130
+        }
131
+    }
132
+
133
+    const result = next(action);
134
+
135
+    if (typeof oldMuted !== 'undefined') {
136
+        // Determine the muted state of the local track after the update. If the
137
+        // muted states before and after the update differ, then the respective
138
+        // media state should by synchronized.
139
+        const localTrack = _getLocalTrack(store, mediaType);
140
+
141
+        if (localTrack) {
142
+            const newMuted = localTrack.muted;
143
+
144
+            if (oldMuted !== newMuted) {
145
+                switch (mediaType) {
146
+                case MEDIA_TYPE.AUDIO:
147
+                    store.dispatch(audioMutedChanged(newMuted));
148
+                    break;
149
+                case MEDIA_TYPE.VIDEO:
150
+                    store.dispatch(videoMutedChanged(newMuted));
151
+                    break;
152
+                }
153
+            }
154
+        }
155
+    }
156
+
157
+    return result;
158
+}

+ 2
- 3
react/features/largeVideo/middleware.js Целия файл

@@ -49,9 +49,8 @@ MiddlewareRegistry.register(store => next => action => {
49 49
                     action.track.jitsiTrack);
50 50
             const participantId = state['features/largeVideo'].participantId;
51 51
 
52
-            if (track.participantId === participantId) {
53
-                store.dispatch(selectParticipant());
54
-            }
52
+            (track.participantId === participantId)
53
+                && store.dispatch(selectParticipant());
55 54
         }
56 55
         break;
57 56
     }

Loading…
Отказ
Запис