From 57b302da3e93c950680a4ef375334ec3a28a4c6e Mon Sep 17 00:00:00 2001 From: paweldomas Date: Thu, 7 Jun 2018 15:05:00 +0200 Subject: [PATCH] feat(base/conference): CONFERENCE_FAILED on CONNECTION_FAILED Emits CONFERENCE_FAILED in response to CONNECTION_FAILED event which then triggers JitsiConference.leave() through the middleware processing. Also base/conference state will be adjusted. It is to have a consistent redux state in which both connection and conference are failed. It could happen that in a buggy environment the XMPP connection is dropped, but the media is still flowing which would result in weird user experience. --- react/features/base/conference/actions.js | 3 +- react/features/base/conference/middleware.js | 62 +++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/react/features/base/conference/actions.js b/react/features/base/conference/actions.js index 0f9abe049..fda72e5dc 100644 --- a/react/features/base/conference/actions.js +++ b/react/features/base/conference/actions.js @@ -199,7 +199,8 @@ export function conferenceFailed(conference: Object, error: string) { // Make the error resemble an Error instance (to the extent that // jitsi-meet needs it). error: { - name: error + name: error, + recoverable: undefined } }; } diff --git a/react/features/base/conference/middleware.js b/react/features/base/conference/middleware.js index b997b7eb2..4049a451f 100644 --- a/react/features/base/conference/middleware.js +++ b/react/features/base/conference/middleware.js @@ -7,7 +7,7 @@ import { createPinnedEvent, sendAnalytics } from '../../analytics'; -import { CONNECTION_ESTABLISHED } from '../connection'; +import { CONNECTION_ESTABLISHED, CONNECTION_FAILED } from '../connection'; import { setVideoMuted, VIDEO_MUTISM_AUTHORITY } from '../media'; import { getLocalParticipant, @@ -20,6 +20,7 @@ import UIEvents from '../../../../service/UI/UIEvents'; import { TRACK_ADDED, TRACK_REMOVED } from '../tracks'; import { + conferenceFailed, conferenceLeft, createConference, setLastN, @@ -62,6 +63,9 @@ MiddlewareRegistry.register(store => next => action => { case CONNECTION_ESTABLISHED: return _connectionEstablished(store, next, action); + case CONNECTION_FAILED: + return _connectionFailed(store, next, action); + case DATA_CHANNEL_OPENED: return _syncReceiveVideoQuality(store, next, action); @@ -168,6 +172,62 @@ function _connectionEstablished({ dispatch }, next, action) { return result; } +/** + * Notifies the feature base/conference that the action + * {@code CONNECTION_FAILED} is being dispatched within a specific redux + * store. + * + * @param {Store} store - The redux store in which the specified {@code action} + * is being dispatched. + * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the + * specified {@code action} to the specified {@code store}. + * @param {Action} action - The redux action {@code CONNECTION_FAILED} which is + * being dispatched in the specified {@code store}. + * @private + * @returns {Object} The value returned by {@code next(action)}. + */ +function _connectionFailed({ dispatch, getState }, next, action) { + const result = next(action); + + // FIXME: Workaround for the web version. Currently, the creation of the + // conference is handled by /conference.js and appropriate failure handlers + // are set there. + if (typeof APP === 'undefined') { + const { connection } = action; + const { error } = action; + + forEachConference(getState, conference => { + // It feels that it would make things easier if JitsiConference + // in lib-jitsi-meet would monitor it's connection and emit + // CONFERENCE_FAILED when it's dropped. It has more knowledge on + // whether it can recover or not. But because the reload screen + // and the retry logic is implemented in the app maybe it can be + // left this way for now. + if (conference.getConnection() === connection) { + // XXX Note that on mobile the error type passed to + // connectionFailed is always an object with .name property. + // This fact needs to be checked prior to enabling this logic on + // web. + const conferenceAction + = conferenceFailed(conference, error.name); + + // Copy the recoverable flag if set on the CONNECTION_FAILED + // action to not emit recoverable action caused by + // a non-recoverable one. + if (typeof error.recoverable !== 'undefined') { + conferenceAction.error.recoverable = error.recoverable; + } + + dispatch(conferenceAction); + } + + return true; + }); + } + + return result; +} + /** * Notifies the feature base/conference that the action {@code PIN_PARTICIPANT} * is being dispatched within a specific redux store. Pins the specified remote