瀏覽代碼

[RN] Automatically dispatch CONFERENCE_LEFT

master
Lyubo Marinov 7 年之前
父節點
當前提交
a30412ba65

+ 63
- 1
react/features/base/conference/middleware.js 查看文件

@@ -20,6 +20,7 @@ import UIEvents from '../../../../service/UI/UIEvents';
20 20
 import { TRACK_ADDED, TRACK_REMOVED } from '../tracks';
21 21
 
22 22
 import {
23
+    conferenceLeft,
23 24
     createConference,
24 25
     setAudioOnly,
25 26
     setLastN,
@@ -32,8 +33,10 @@ import {
32 33
     DATA_CHANNEL_OPENED,
33 34
     SET_AUDIO_ONLY,
34 35
     SET_LASTN,
35
-    SET_RECEIVE_VIDEO_QUALITY
36
+    SET_RECEIVE_VIDEO_QUALITY,
37
+    SET_ROOM
36 38
 } from './actionTypes';
39
+import { JITSI_CONFERENCE_URL_KEY } from './constants';
37 40
 import {
38 41
     _addLocalTracksToConference,
39 42
     _handleParticipantError,
@@ -77,6 +80,9 @@ MiddlewareRegistry.register(store => next => action => {
77 80
     case SET_RECEIVE_VIDEO_QUALITY:
78 81
         return _setReceiveVideoQuality(store, next, action);
79 82
 
83
+    case SET_ROOM:
84
+        return _setRoom(store, next, action);
85
+
80 86
     case TRACK_ADDED:
81 87
     case TRACK_REMOVED:
82 88
         return _trackAddedOrRemoved(store, next, action);
@@ -330,6 +336,62 @@ function _setReceiveVideoQuality({ dispatch, getState }, next, action) {
330 336
     return next(action);
331 337
 }
332 338
 
339
+/**
340
+ * Notifies the feature {@code base/conference} that the redix action
341
+ * {@link SET_ROOM} is being dispatched within a specific redux store.
342
+ *
343
+ * @param {Store} store - The redux store in which the specified action is being
344
+ * dispatched.
345
+ * @param {Dispatch} next - The redux dispatch function to dispatch the
346
+ * specified action to the specified store.
347
+ * @param {Action} action - The redux action {@code SET_ROOM} which is being
348
+ * dispatched in the specified store.
349
+ * @private
350
+ * @returns {Object} The value returned by {@code next(action)}.
351
+ */
352
+function _setRoom({ dispatch, getState }, next, action) {
353
+    const result = next(action);
354
+
355
+    // By the time SET_ROOM is dispatched, base/connection's locationURL and
356
+    // base/conference's leaving should be the only conference-related sources
357
+    // of truth.
358
+    const state = getState();
359
+    const {
360
+        leaving,
361
+        ...stateFeaturesBaseConference
362
+    } = state['features/base/conference'];
363
+    const { locationURL } = state['features/base/connection'];
364
+    const dispatchConferenceLeft = new Set();
365
+
366
+    // Figure out which of the JitsiConferences referenced by base/conference
367
+    // have not dispatched or are not likely to dispatch CONFERENCE_FAILED and
368
+    // CONFERENCE_LEFT.
369
+
370
+    // eslint-disable-next-line guard-for-in
371
+    for (const p in stateFeaturesBaseConference) {
372
+        const v = stateFeaturesBaseConference[p];
373
+
374
+        // Does the value of the base/conference's property look like a
375
+        // JitsiConference?
376
+        if (v && typeof v === 'object') {
377
+            const url = v[JITSI_CONFERENCE_URL_KEY];
378
+
379
+            if (url && v !== leaving && url !== locationURL) {
380
+                dispatchConferenceLeft.add(v);
381
+            }
382
+        }
383
+    }
384
+
385
+    // Dispatch CONFERENCE_LEFT for the JitsiConferences referenced by
386
+    // base/conference which have not dispatched or are not likely to dispatch
387
+    // CONFERENCE_FAILED or CONFERENCE_LEFT.
388
+    for (const conference of dispatchConferenceLeft) {
389
+        dispatch(conferenceLeft(conference));
390
+    }
391
+
392
+    return result;
393
+}
394
+
333 395
 /**
334 396
  * Synchronizes local tracks from state with local tracks in JitsiConference
335 397
  * instance.

+ 11
- 2
react/features/base/connection/actions.native.js 查看文件

@@ -3,7 +3,7 @@
3 3
 import _ from 'lodash';
4 4
 import type { Dispatch } from 'redux';
5 5
 
6
-import { conferenceWillLeave } from '../conference';
6
+import { conferenceLeft, conferenceWillLeave } from '../conference';
7 7
 import JitsiMeetJS, { JitsiConnectionEvents } from '../lib-jitsi-meet';
8 8
 import { parseStandardURIString } from '../util';
9 9
 
@@ -281,7 +281,16 @@ export function disconnect() {
281 281
             // intention to leave the conference.
282 282
             dispatch(conferenceWillLeave(conference_));
283 283
 
284
-            promise = conference_.leave();
284
+            promise
285
+                = conference_.leave()
286
+                    .catch(() => {
287
+                        // The library lib-jitsi-meet failed to make the
288
+                        // JitsiConference leave. Which may be because
289
+                        // JitsiConference thinks it has already left.
290
+                        // Regardless of the failure reason, continue in
291
+                        // jitsi-meet as if the leave has succeeded.
292
+                        dispatch(conferenceLeft(conference_));
293
+                    });
285 294
         } else {
286 295
             promise = Promise.resolve();
287 296
         }

+ 70
- 2
react/features/mobile/external-api/middleware.js 查看文件

@@ -125,11 +125,13 @@ function _getSymbolDescription(symbol: Symbol) {
125 125
  */
126 126
 function _sendConferenceEvent(
127 127
         store: Object,
128
-        { conference, type, ...data }: {
128
+        action: {
129 129
             conference: Object,
130 130
             type: Symbol,
131 131
             url: ?string
132 132
         }) {
133
+    const { conference, type, ...data } = action;
134
+
133 135
     // For these (redux) actions, conference identifies a JitsiConference
134 136
     // instance. The external API cannot transport such an object so we have to
135 137
     // transport an "equivalent".
@@ -137,7 +139,8 @@ function _sendConferenceEvent(
137 139
         data.url = toURLString(conference[JITSI_CONFERENCE_URL_KEY]);
138 140
     }
139 141
 
140
-    _sendEvent(store, _getSymbolDescription(type), data);
142
+    _swallowEvent(store, action, data)
143
+        || _sendEvent(store, _getSymbolDescription(type), data);
141 144
 }
142 145
 
143 146
 /**
@@ -169,3 +172,68 @@ function _sendEvent(
169 172
         }
170 173
     }
171 174
 }
175
+
176
+/**
177
+ * Determines whether to not send a {@code CONFERENCE_LEFT} event to the native
178
+ * counterpart of the External API.
179
+ *
180
+ * @param {Object} store - The redux store.
181
+ * @param {Action} action - The redux action which is causing the sending of the
182
+ * event.
183
+ * @param {Object} data - The details/specifics of the event to send determined
184
+ * by/associated with the specified {@code action}.
185
+ * @returns {boolean} If the specified event is to not be sent, {@code true};
186
+ * otherwise, {@code false}.
187
+ */
188
+function _swallowConferenceLeft({ getState }, action, { url }) {
189
+    // XXX Internally, we work with JitsiConference instances. Externally
190
+    // though, we deal with URL strings. The relation between the two is many to
191
+    // one so it's technically and practically possible (by externally loading
192
+    // the same URL string multiple times) to try to send CONFERENCE_LEFT
193
+    // externally for a URL string which identifies a JitsiConference that the
194
+    // app is internally legitimately working with.
195
+
196
+    if (url) {
197
+        const stateFeaturesBaseConference
198
+            = getState()['features/base/conference'];
199
+
200
+        // eslint-disable-next-line guard-for-in
201
+        for (const p in stateFeaturesBaseConference) {
202
+            const v = stateFeaturesBaseConference[p];
203
+
204
+            // Does the value of the base/conference's property look like a
205
+            // JitsiConference?
206
+            if (v && typeof v === 'object') {
207
+                const vURL = v[JITSI_CONFERENCE_URL_KEY];
208
+
209
+                if (vURL && vURL.toString() === url) {
210
+                    return true;
211
+                }
212
+            }
213
+        }
214
+    }
215
+
216
+    return false;
217
+}
218
+
219
+/**
220
+ * Determines whether to not send a specific event to the native counterpart of
221
+ * the External API.
222
+ *
223
+ * @param {Object} store - The redux store.
224
+ * @param {Action} action - The redux action which is causing the sending of the
225
+ * event.
226
+ * @param {Object} data - The details/specifics of the event to send determined
227
+ * by/associated with the specified {@code action}.
228
+ * @returns {boolean} If the specified event is to not be sent, {@code true};
229
+ * otherwise, {@code false}.
230
+ */
231
+function _swallowEvent(store, action, data) {
232
+    switch (action.type) {
233
+    case CONFERENCE_LEFT:
234
+        return _swallowConferenceLeft(store, action, data);
235
+
236
+    default:
237
+        return false;
238
+    }
239
+}

Loading…
取消
儲存