瀏覽代碼

fix: leaking listeners while waiting on auth dialog (#11288)

* fix: Drop duplicate call of wait for owner.

* fix: Fixes leaking listeners while waiting for host to join.

While waiting for the host to join on the dialog we attempt to join over and over again till we are admitted to enter the meeting. While doing that authRequired flag is on, and we were adding listeners on and on.

* feat: Introduces conference join in progress action.

This event is coming from lib-jitsi-meet and is fired when we receive the first presence of series when joining. It is always fired before joined event.

* fix: Moves testing middleware to use CONFERENCE_JOIN_IN_PROGRESS.

* fix: Moves follow-me middleware to use CONFERENCE_JOIN_IN_PROGRESS.

* fix: Moves some polls logic to middleware and use CONFERENCE_JOIN_IN_PROGRESS.

* fix: Moves reactions middleware to use CONFERENCE_JOIN_IN_PROGRESS.

* fix: Moves recordings middleware to use CONFERENCE_JOIN_IN_PROGRESS.

* fix: Moves shared-video middleware to use CONFERENCE_JOIN_IN_PROGRESS.

* fix: Moves videosipgw middleware to use CONFERENCE_JOIN_IN_PROGRESS.

* squash: Fix comments.

* fix: Fixes join in progress on web.

* fix: Moves variable extraction inside handlers.

* fix: Moves variable extraction inside handlers again.

* fix: Moves etherpad middleware to use CONFERENCE_JOIN_IN_PROGRESS.
master
Дамян Минков 3 年之前
父節點
當前提交
a99532b0d8
沒有連結到貢獻者的電子郵件帳戶。

+ 5
- 5
conference.js 查看文件

@@ -37,6 +37,7 @@ import {
37 37
     commonUserLeftHandling,
38 38
     conferenceFailed,
39 39
     conferenceJoined,
40
+    conferenceJoinInProgress,
40 41
     conferenceLeft,
41 42
     conferenceSubjectChanged,
42 43
     conferenceTimestampChanged,
@@ -142,8 +143,7 @@ import {
142 143
     initPrejoin,
143 144
     isPrejoinPageVisible,
144 145
     makePrecallTest,
145
-    setJoiningInProgress,
146
-    setPrejoinPageVisibility
146
+    setJoiningInProgress
147 147
 } from './react/features/prejoin';
148 148
 import { disableReceiver, stopReceiver } from './react/features/remote-control';
149 149
 import { setScreenAudioShareState, isScreenAudioShared } from './react/features/screen-share/';
@@ -2068,9 +2068,9 @@ export default {
2068 2068
         room.on(JitsiConferenceEvents.CONFERENCE_JOINED, () => {
2069 2069
             this._onConferenceJoined();
2070 2070
         });
2071
-        room.on(JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS, () => {
2072
-            APP.store.dispatch(setPrejoinPageVisibility(false));
2073
-        });
2071
+        room.on(
2072
+            JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS,
2073
+            () => APP.store.dispatch(conferenceJoinInProgress(room)));
2074 2074
 
2075 2075
         room.on(
2076 2076
             JitsiConferenceEvents.CONFERENCE_LEFT,

+ 7
- 4
modules/UI/authentication/AuthHandler.js 查看文件

@@ -6,7 +6,10 @@ import { openConnection } from '../../../connection';
6 6
 import {
7 7
     openAuthDialog,
8 8
     openLoginDialog } from '../../../react/features/authentication/actions.web';
9
-import { WaitForOwnerDialog } from '../../../react/features/authentication/components';
9
+import {
10
+    LoginDialog,
11
+    WaitForOwnerDialog
12
+} from '../../../react/features/authentication/components';
10 13
 import {
11 14
     isTokenAuthEnabled,
12 15
     getTokenAuthUrl
@@ -16,7 +19,7 @@ import { isDialogOpen } from '../../../react/features/base/dialog';
16 19
 import { setJWT } from '../../../react/features/base/jwt';
17 20
 import UIUtil from '../util/UIUtil';
18 21
 
19
-import LoginDialog from './LoginDialog';
22
+import ExternalLoginDialog from './LoginDialog';
20 23
 
21 24
 
22 25
 let externalAuthWindow;
@@ -51,7 +54,7 @@ function doExternalAuth(room, lockPassword) {
51 54
             getUrl = room.getExternalAuthUrl(true);
52 55
         }
53 56
         getUrl.then(url => {
54
-            externalAuthWindow = LoginDialog.showExternalAuthDialog(
57
+            externalAuthWindow = ExternalLoginDialog.showExternalAuthDialog(
55 58
                 url,
56 59
                 () => {
57 60
                     externalAuthWindow = null;
@@ -187,7 +190,7 @@ function authenticate(room: Object, lockPassword: string) {
187 190
  * @param {string} [lockPassword] password to use if the conference is locked
188 191
  */
189 192
 function requireAuth(room: Object, lockPassword: string) {
190
-    if (!isDialogOpen(APP.store, WaitForOwnerDialog)) {
193
+    if (isDialogOpen(APP.store, WaitForOwnerDialog) || isDialogOpen(APP.store, LoginDialog)) {
191 194
         return;
192 195
     }
193 196
 

+ 0
- 1
react/features/app/middlewares.any.js 查看文件

@@ -37,7 +37,6 @@ import '../lobby/middleware';
37 37
 import '../notifications/middleware';
38 38
 import '../overlay/middleware';
39 39
 import '../polls/middleware';
40
-import '../polls/subscriber';
41 40
 import '../reactions/middleware';
42 41
 import '../recent-list/middleware';
43 42
 import '../recording/middleware';

+ 6
- 3
react/features/authentication/middleware.web.js 查看文件

@@ -22,8 +22,7 @@ import {
22 22
 import {
23 23
     hideLoginDialog,
24 24
     openWaitForOwnerDialog,
25
-    stopWaitForOwner,
26
-    waitForOwner
25
+    stopWaitForOwner
27 26
 } from './actions.web';
28 27
 import { LoginDialog, WaitForOwnerDialog } from './components';
29 28
 
@@ -72,7 +71,11 @@ MiddlewareRegistry.register(store => next => action => {
72 71
             recoverable = error.recoverable;
73 72
         }
74 73
         if (recoverable) {
75
-            store.dispatch(waitForOwner());
74
+            // we haven't migrated all the code from AuthHandler, and we need for now conference.js to trigger
75
+            // the dialog to pass all required parameters to WaitForOwnerDialog
76
+            // keep it commented, so we do not trigger sending iqs to jicofo twice
77
+            // and showing the broken dialog with no handler
78
+            // store.dispatch(waitForOwner());
76 79
         } else {
77 80
             store.dispatch(stopWaitForOwner());
78 81
         }

+ 11
- 0
react/features/base/conference/actionTypes.js 查看文件

@@ -32,6 +32,17 @@ export const CONFERENCE_FAILED = 'CONFERENCE_FAILED';
32 32
  */
33 33
 export const CONFERENCE_JOINED = 'CONFERENCE_JOINED';
34 34
 
35
+/**
36
+ * The type of (redux) action which signals that a specific conference joining is in progress.
37
+ * A CONFERENCE_JOINED is guaranteed to follow.
38
+ *
39
+ * {
40
+ *     type: CONFERENCE_JOIN_IN_PROGRESS,
41
+ *     conference: JitsiConference
42
+ * }
43
+ */
44
+export const CONFERENCE_JOIN_IN_PROGRESS = 'CONFERENCE_JOIN_IN_PROGRESS';
45
+
35 46
 /**
36 47
  * The type of (redux) action which signals that a specific conference was left.
37 48
  *

+ 21
- 0
react/features/base/conference/actions.js 查看文件

@@ -39,6 +39,7 @@ import { getBackendSafeRoomName } from '../util';
39 39
 import {
40 40
     AUTH_STATUS_CHANGED,
41 41
     CONFERENCE_FAILED,
42
+    CONFERENCE_JOIN_IN_PROGRESS,
42 43
     CONFERENCE_JOINED,
43 44
     CONFERENCE_LEFT,
44 45
     CONFERENCE_LOCAL_SUBJECT_CHANGED,
@@ -105,6 +106,9 @@ function _addConferenceListeners(conference, dispatch, state) {
105 106
     conference.on(
106 107
         JitsiConferenceEvents.CONFERENCE_JOINED,
107 108
         (...args) => dispatch(conferenceJoined(conference, ...args)));
109
+    conference.on(
110
+        JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS,
111
+        (...args) => dispatch(conferenceJoinInProgress(conference, ...args)));
108 112
     conference.on(
109 113
         JitsiConferenceEvents.CONFERENCE_LEFT,
110 114
         (...args) => {
@@ -350,6 +354,23 @@ export function conferenceJoined(conference: Object) {
350 354
     };
351 355
 }
352 356
 
357
+/**
358
+ * Signals that a specific conference join is in progress.
359
+ *
360
+ * @param {JitsiConference} conference - The JitsiConference instance for which join by the local participant
361
+ * is in progress.
362
+ * @returns {{
363
+ *     type: CONFERENCE_JOIN_IN_PROGRESS,
364
+ *     conference: JitsiConference
365
+ * }}
366
+ */
367
+export function conferenceJoinInProgress(conference: Object) {
368
+    return {
369
+        type: CONFERENCE_JOIN_IN_PROGRESS,
370
+        conference
371
+    };
372
+}
373
+
353 374
 /**
354 375
  * Signals that a specific conference has been left.
355 376
  *

+ 10
- 2
react/features/base/conference/middleware.web.js 查看文件

@@ -2,7 +2,10 @@
2 2
 
3 3
 import { AUDIO_ONLY_SCREEN_SHARE_NO_TRACK } from '../../../../modules/UI/UIErrors';
4 4
 import { showNotification, NOTIFICATION_TIMEOUT_TYPE } from '../../notifications';
5
-import { setSkipPrejoinOnReload } from '../../prejoin';
5
+import {
6
+    setPrejoinPageVisibility,
7
+    setSkipPrejoinOnReload
8
+} from '../../prejoin';
6 9
 import { setScreenAudioShareState, setScreenshareAudioTrack } from '../../screen-share';
7 10
 import { AudioMixerEffect } from '../../stream-effects/audio-mixer/AudioMixerEffect';
8 11
 import { setAudioOnly } from '../audio-only';
@@ -19,7 +22,7 @@ import {
19 22
     TOGGLE_SCREENSHARING
20 23
 } from '../tracks';
21 24
 
22
-import { CONFERENCE_FAILED, CONFERENCE_JOINED } from './actionTypes';
25
+import { CONFERENCE_FAILED, CONFERENCE_JOIN_IN_PROGRESS, CONFERENCE_JOINED } from './actionTypes';
23 26
 import { getCurrentConference } from './functions';
24 27
 import './middleware.any';
25 28
 
@@ -28,6 +31,11 @@ MiddlewareRegistry.register(store => next => action => {
28 31
     const { enableForcedReload } = getState()['features/base/config'];
29 32
 
30 33
     switch (action.type) {
34
+    case CONFERENCE_JOIN_IN_PROGRESS: {
35
+        dispatch(setPrejoinPageVisibility(false));
36
+
37
+        break;
38
+    }
31 39
     case CONFERENCE_JOINED: {
32 40
         if (enableForcedReload) {
33 41
             dispatch(setSkipPrejoinOnReload(false));

+ 2
- 2
react/features/base/testing/middleware.js 查看文件

@@ -1,6 +1,6 @@
1 1
 // @flow
2 2
 
3
-import { CONFERENCE_WILL_JOIN } from '../conference';
3
+import { CONFERENCE_JOIN_IN_PROGRESS } from '../conference/actionTypes';
4 4
 import { SET_CONFIG } from '../config';
5 5
 import { JitsiConferenceEvents } from '../lib-jitsi-meet';
6 6
 import { MiddlewareRegistry } from '../redux';
@@ -24,7 +24,7 @@ import logger from './logger';
24 24
  */
25 25
 MiddlewareRegistry.register(store => next => action => {
26 26
     switch (action.type) {
27
-    case CONFERENCE_WILL_JOIN:
27
+    case CONFERENCE_JOIN_IN_PROGRESS:
28 28
         _bindConferenceConnectionListener(action.conference, store);
29 29
         break;
30 30
     case SET_CONFIG: {

+ 19
- 18
react/features/etherpad/middleware.js 查看文件

@@ -2,6 +2,7 @@
2 2
 
3 3
 import UIEvents from '../../../service/UI/UIEvents';
4 4
 import { getCurrentConference } from '../base/conference';
5
+import { CONFERENCE_JOIN_IN_PROGRESS } from '../base/conference/actionTypes';
5 6
 import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
6 7
 
7 8
 import { TOGGLE_DOCUMENT_EDITING } from './actionTypes';
@@ -21,6 +22,23 @@ const ETHERPAD_COMMAND = 'etherpad';
21 22
 // eslint-disable-next-line no-unused-vars
22 23
 MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
23 24
     switch (action.type) {
25
+    case CONFERENCE_JOIN_IN_PROGRESS: {
26
+        const { conference } = action;
27
+
28
+        conference.addCommandListener(ETHERPAD_COMMAND,
29
+            ({ value }) => {
30
+                let url;
31
+                const { etherpad_base: etherpadBase } = getState()['features/base/config'];
32
+
33
+                if (etherpadBase) {
34
+                    url = new URL(value, etherpadBase).toString();
35
+                }
36
+
37
+                dispatch(setDocumentUrl(url));
38
+            }
39
+        );
40
+        break;
41
+    }
24 42
     case TOGGLE_DOCUMENT_EDITING: {
25 43
         if (typeof APP !== 'undefined') {
26 44
             APP.UI.emitEvent(UIEvents.ETHERPAD_CLICKED);
@@ -39,24 +57,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
39 57
  */
40 58
 StateListenerRegistry.register(
41 59
     state => getCurrentConference(state),
42
-    (conference, { dispatch, getState }, previousConference) => {
43
-        if (conference) {
44
-            conference.addCommandListener(ETHERPAD_COMMAND,
45
-                ({ value }) => {
46
-                    let url;
47
-                    const { etherpad_base: etherpadBase } = getState()['features/base/config'];
48
-
49
-                    if (etherpadBase) {
50
-                        const u = new URL(value, etherpadBase);
51
-
52
-                        url = u.toString();
53
-                    }
54
-
55
-                    dispatch(setDocumentUrl(url));
56
-                }
57
-            );
58
-        }
59
-
60
+    (conference, { dispatch }, previousConference) => {
60 61
         if (previousConference) {
61 62
             dispatch(setDocumentUrl(undefined));
62 63
         }

+ 2
- 2
react/features/follow-me/middleware.js 查看文件

@@ -2,7 +2,7 @@
2 2
 
3 3
 import _ from 'lodash';
4 4
 
5
-import { CONFERENCE_WILL_JOIN } from '../base/conference/actionTypes';
5
+import { CONFERENCE_JOIN_IN_PROGRESS } from '../base/conference/actionTypes';
6 6
 import {
7 7
     getParticipantById,
8 8
     getPinnedParticipant,
@@ -61,7 +61,7 @@ let nextOnStageTimer = 0;
61 61
  */
62 62
 MiddlewareRegistry.register(store => next => action => {
63 63
     switch (action.type) {
64
-    case CONFERENCE_WILL_JOIN: {
64
+    case CONFERENCE_JOIN_IN_PROGRESS: {
65 65
         const { conference } = action;
66 66
 
67 67
         conference.addCommandListener(

+ 150
- 1
react/features/polls/middleware.js 查看文件

@@ -1,16 +1,95 @@
1 1
 // @flow
2 2
 
3
-import { MiddlewareRegistry } from '../base/redux';
3
+import { getCurrentConference } from '../base/conference';
4
+import { CONFERENCE_JOIN_IN_PROGRESS } from '../base/conference/actionTypes';
5
+import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
6
+import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
4 7
 import { playSound } from '../base/sounds';
5 8
 import { INCOMING_MSG_SOUND_ID } from '../chat/constants';
9
+import {
10
+    NOTIFICATION_TIMEOUT_TYPE,
11
+    NOTIFICATION_TYPE,
12
+    showNotification
13
+} from '../notifications';
6 14
 
7 15
 import { RECEIVE_POLL } from './actionTypes';
16
+import { clearPolls, receiveAnswer, receivePoll } from './actions';
17
+import {
18
+    COMMAND_ANSWER_POLL,
19
+    COMMAND_NEW_POLL,
20
+    COMMAND_OLD_POLLS
21
+} from './constants';
22
+import type { Answer, Poll } from './types';
8 23
 
24
+/**
25
+ * Set up state change listener to perform maintenance tasks when the conference
26
+ * is left or failed, e.g. Clear messages or close the chat modal if it's left
27
+ * open.
28
+ */
29
+StateListenerRegistry.register(
30
+    state => getCurrentConference(state),
31
+    (conference, { dispatch }, previousConference) => {
32
+        if (conference !== previousConference) {
33
+            // conference changed, left or failed...
34
+            // clean old polls
35
+            dispatch(clearPolls());
36
+        }
37
+    });
38
+
39
+const parsePollData = (pollData): Poll | null => {
40
+    if (typeof pollData !== 'object' || pollData === null) {
41
+        return null;
42
+    }
43
+    const { id, senderId, senderName, question, answers } = pollData;
44
+
45
+    if (typeof id !== 'string' || typeof senderId !== 'string' || typeof senderName !== 'string'
46
+        || typeof question !== 'string' || !(answers instanceof Array)) {
47
+        return null;
48
+    }
49
+
50
+    const answersParsed = [];
51
+
52
+    for (const answer of answers) {
53
+        const voters = new Map();
54
+
55
+        for (const [ voterId, voter ] of Object.entries(answer.voters)) {
56
+            if (typeof voter !== 'string') {
57
+                return null;
58
+            }
59
+            voters.set(voterId, voter);
60
+        }
61
+
62
+        answersParsed.push({
63
+            name: answer.name,
64
+            voters
65
+        });
66
+    }
67
+
68
+    return {
69
+        changingVote: false,
70
+        senderId,
71
+        senderName,
72
+        question,
73
+        showResults: true,
74
+        lastVote: null,
75
+        answers: answersParsed
76
+    };
77
+};
9 78
 
10 79
 MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
11 80
     const result = next(action);
12 81
 
13 82
     switch (action.type) {
83
+    case CONFERENCE_JOIN_IN_PROGRESS: {
84
+        const { conference } = action;
85
+
86
+        conference.on(JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
87
+            (_, data) => _handleReceivePollsMessage(data, dispatch));
88
+        conference.on(JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED,
89
+            (_, data) => _handleReceivePollsMessage(data, dispatch));
90
+
91
+        break;
92
+    }
14 93
 
15 94
     // Middleware triggered when a poll is received
16 95
     case RECEIVE_POLL: {
@@ -30,3 +109,73 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
30 109
 
31 110
     return result;
32 111
 });
112
+
113
+/**
114
+ * Handles receiving of polls message command.
115
+ *
116
+ * @param {Object} data - The json data carried by the polls message.
117
+ * @param {Function} dispatch - The dispatch function.
118
+ *
119
+ * @returns {void}
120
+ */
121
+function _handleReceivePollsMessage(data, dispatch) {
122
+    switch (data.type) {
123
+    case COMMAND_NEW_POLL: {
124
+        const { question, answers, pollId, senderId, senderName } = data;
125
+
126
+        const poll = {
127
+            changingVote: false,
128
+            senderId,
129
+            senderName,
130
+            showResults: false,
131
+            lastVote: null,
132
+            question,
133
+            answers: answers.map(answer => {
134
+                return {
135
+                    name: answer,
136
+                    voters: new Map()
137
+                };
138
+            })
139
+        };
140
+
141
+        dispatch(receivePoll(pollId, poll, true));
142
+        dispatch(showNotification({
143
+            appearance: NOTIFICATION_TYPE.NORMAL,
144
+            titleKey: 'polls.notification.title',
145
+            descriptionKey: 'polls.notification.description'
146
+        }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
147
+        break;
148
+
149
+    }
150
+
151
+    case COMMAND_ANSWER_POLL: {
152
+        const { pollId, answers, voterId, voterName } = data;
153
+
154
+        const receivedAnswer: Answer = {
155
+            voterId,
156
+            voterName,
157
+            pollId,
158
+            answers
159
+        };
160
+
161
+        dispatch(receiveAnswer(pollId, receivedAnswer));
162
+        break;
163
+
164
+    }
165
+
166
+    case COMMAND_OLD_POLLS: {
167
+        const { polls } = data;
168
+
169
+        for (const pollData of polls) {
170
+            const poll = parsePollData(pollData);
171
+
172
+            if (poll === null) {
173
+                console.warn('[features/polls] Invalid old poll data');
174
+            } else {
175
+                dispatch(receivePoll(pollData.id, poll, false));
176
+            }
177
+        }
178
+        break;
179
+    }
180
+    }
181
+}

+ 0
- 130
react/features/polls/subscriber.js 查看文件

@@ -1,130 +0,0 @@
1
-// @flow
2
-
3
-import { getCurrentConference } from '../base/conference';
4
-import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
5
-import { StateListenerRegistry } from '../base/redux';
6
-import {
7
-    NOTIFICATION_TIMEOUT_TYPE,
8
-    NOTIFICATION_TYPE,
9
-    showNotification
10
-} from '../notifications';
11
-
12
-import { clearPolls, receiveAnswer, receivePoll } from './actions';
13
-import { COMMAND_NEW_POLL, COMMAND_ANSWER_POLL, COMMAND_OLD_POLLS } from './constants';
14
-import type { Answer, Poll } from './types';
15
-
16
-
17
-const parsePollData = (pollData): Poll | null => {
18
-    if (typeof pollData !== 'object' || pollData === null) {
19
-        return null;
20
-    }
21
-    const { id, senderId, senderName, question, answers } = pollData;
22
-
23
-    if (typeof id !== 'string' || typeof senderId !== 'string' || typeof senderName !== 'string'
24
-        || typeof question !== 'string' || !(answers instanceof Array)) {
25
-        return null;
26
-    }
27
-
28
-    const answersParsed = [];
29
-
30
-    for (const answer of answers) {
31
-        const voters = new Map();
32
-
33
-        for (const [ voterId, voter ] of Object.entries(answer.voters)) {
34
-            if (typeof voter !== 'string') {
35
-                return null;
36
-            }
37
-            voters.set(voterId, voter);
38
-        }
39
-
40
-        answersParsed.push({
41
-            name: answer.name,
42
-            voters
43
-        });
44
-    }
45
-
46
-    return {
47
-        changingVote: false,
48
-        senderId,
49
-        senderName,
50
-        question,
51
-        showResults: true,
52
-        lastVote: null,
53
-        answers: answersParsed
54
-    };
55
-};
56
-
57
-StateListenerRegistry.register(
58
-    state => getCurrentConference(state),
59
-    (conference, store, previousConference) => {
60
-        if (conference && conference !== previousConference) {
61
-            const receiveMessage = (_, data) => {
62
-                switch (data.type) {
63
-                case COMMAND_NEW_POLL: {
64
-                    const { question, answers, pollId, senderId, senderName } = data;
65
-
66
-                    const poll = {
67
-                        changingVote: false,
68
-                        senderId,
69
-                        senderName,
70
-                        showResults: false,
71
-                        lastVote: null,
72
-                        question,
73
-                        answers: answers.map(answer => {
74
-                            return {
75
-                                name: answer,
76
-                                voters: new Map()
77
-                            };
78
-                        })
79
-                    };
80
-
81
-                    store.dispatch(receivePoll(pollId, poll, true));
82
-                    store.dispatch(showNotification({
83
-                        appearance: NOTIFICATION_TYPE.NORMAL,
84
-                        titleKey: 'polls.notification.title',
85
-                        descriptionKey: 'polls.notification.description'
86
-                    }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
87
-                    break;
88
-
89
-                }
90
-
91
-                case COMMAND_ANSWER_POLL: {
92
-                    const { pollId, answers, voterId, voterName } = data;
93
-
94
-                    const receivedAnswer: Answer = {
95
-                        voterId,
96
-                        voterName,
97
-                        pollId,
98
-                        answers
99
-                    };
100
-
101
-                    store.dispatch(receiveAnswer(pollId, receivedAnswer));
102
-                    break;
103
-
104
-                }
105
-
106
-                case COMMAND_OLD_POLLS: {
107
-                    const { polls } = data;
108
-
109
-                    for (const pollData of polls) {
110
-                        const poll = parsePollData(pollData);
111
-
112
-                        if (poll === null) {
113
-                            console.warn('[features/polls] Invalid old poll data');
114
-                        } else {
115
-                            store.dispatch(receivePoll(pollData.id, poll, false));
116
-                        }
117
-                    }
118
-                    break;
119
-                }
120
-                }
121
-            };
122
-
123
-            conference.on(JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED, receiveMessage);
124
-            conference.on(JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED, receiveMessage);
125
-
126
-            // clean old polls
127
-            store.dispatch(clearPolls());
128
-        }
129
-    }
130
-);

+ 2
- 2
react/features/reactions/middleware.js 查看文件

@@ -5,7 +5,7 @@ import { batch } from 'react-redux';
5 5
 import { createReactionSoundsDisabledEvent, sendAnalytics } from '../analytics';
6 6
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
7 7
 import {
8
-    CONFERENCE_WILL_JOIN,
8
+    CONFERENCE_JOIN_IN_PROGRESS,
9 9
     SET_START_REACTIONS_MUTED,
10 10
     setStartReactionsMuted
11 11
 } from '../base/conference';
@@ -104,7 +104,7 @@ MiddlewareRegistry.register(store => next => action => {
104 104
 
105 105
         break;
106 106
     }
107
-    case CONFERENCE_WILL_JOIN: {
107
+    case CONFERENCE_JOIN_IN_PROGRESS: {
108 108
         const { conference } = action;
109 109
 
110 110
         conference.addCommandListener(

+ 4
- 10
react/features/recording/middleware.js 查看文件

@@ -6,7 +6,7 @@ import {
6 6
     sendAnalytics
7 7
 } from '../analytics';
8 8
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
9
-import { CONFERENCE_WILL_JOIN, getCurrentConference } from '../base/conference';
9
+import { CONFERENCE_JOIN_IN_PROGRESS, getCurrentConference } from '../base/conference';
10 10
 import JitsiMeetJS, {
11 11
     JitsiConferenceEvents,
12 12
     JitsiRecordingConstants
@@ -106,21 +106,15 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
106 106
 
107 107
         break;
108 108
 
109
-    case CONFERENCE_WILL_JOIN: {
109
+    case CONFERENCE_JOIN_IN_PROGRESS: {
110 110
         const { conference } = action;
111 111
 
112 112
         conference.on(
113 113
             JitsiConferenceEvents.RECORDER_STATE_CHANGED,
114 114
             recorderSession => {
115
-
116 115
                 if (recorderSession) {
117
-                    recorderSession.getID()
118
-                        && dispatch(
119
-                            updateRecordingSessionData(recorderSession));
120
-
121
-                    recorderSession.getError()
122
-                        && _showRecordingErrorNotification(
123
-                            recorderSession, dispatch);
116
+                    recorderSession.getID() && dispatch(updateRecordingSessionData(recorderSession));
117
+                    recorderSession.getError() && _showRecordingErrorNotification(recorderSession, dispatch);
124 118
                 }
125 119
 
126 120
                 return;

+ 43
- 40
react/features/shared-video/middleware.any.js 查看文件

@@ -2,7 +2,8 @@
2 2
 
3 3
 import { batch } from 'react-redux';
4 4
 
5
-import { CONFERENCE_LEFT, getCurrentConference } from '../base/conference';
5
+import { CONFERENCE_JOIN_IN_PROGRESS, CONFERENCE_LEFT } from '../base/conference/actionTypes';
6
+import { getCurrentConference } from '../base/conference/functions';
6 7
 import {
7 8
     PARTICIPANT_LEFT,
8 9
     getLocalParticipant,
@@ -10,7 +11,7 @@ import {
10 11
     participantLeft,
11 12
     pinParticipant
12 13
 } from '../base/participants';
13
-import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
14
+import { MiddlewareRegistry } from '../base/redux';
14 15
 
15 16
 import { SET_SHARED_VIDEO_STATUS, RESET_SHARED_VIDEO_STATUS } from './actionTypes';
16 17
 import {
@@ -30,16 +31,37 @@ import { isSharingStatus } from './functions';
30 31
 MiddlewareRegistry.register(store => next => action => {
31 32
     const { dispatch, getState } = store;
32 33
     const state = getState();
33
-    const conference = getCurrentConference(state);
34
-    const localParticipantId = getLocalParticipant(state)?.id;
35
-    const { videoUrl, status, ownerId, time, muted, volume } = action;
36
-    const { ownerId: stateOwnerId, videoUrl: statevideoUrl } = state['features/shared-video'];
37 34
 
38 35
     switch (action.type) {
36
+    case CONFERENCE_JOIN_IN_PROGRESS: {
37
+        const { conference } = action;
38
+        const localParticipantId = getLocalParticipant(state)?.id;
39
+
40
+        conference.addCommandListener(SHARED_VIDEO,
41
+            ({ value, attributes }) => {
42
+
43
+                const { from } = attributes;
44
+                const sharedVideoStatus = attributes.state;
45
+
46
+                if (isSharingStatus(sharedVideoStatus)) {
47
+                    handleSharingVideoStatus(store, value, attributes, conference);
48
+                } else if (sharedVideoStatus === 'stop') {
49
+                    dispatch(participantLeft(value, conference));
50
+                    if (localParticipantId !== from) {
51
+                        dispatch(resetSharedVideoStatus());
52
+                    }
53
+                }
54
+            }
55
+        );
56
+        break;
57
+    }
39 58
     case CONFERENCE_LEFT:
40 59
         dispatch(resetSharedVideoStatus());
41 60
         break;
42
-    case PARTICIPANT_LEFT:
61
+    case PARTICIPANT_LEFT: {
62
+        const conference = getCurrentConference(state);
63
+        const { ownerId: stateOwnerId, videoUrl: statevideoUrl } = state['features/shared-video'];
64
+
43 65
         if (action.participant.id === stateOwnerId) {
44 66
             batch(() => {
45 67
                 dispatch(resetSharedVideoStatus());
@@ -47,7 +69,12 @@ MiddlewareRegistry.register(store => next => action => {
47 69
             });
48 70
         }
49 71
         break;
50
-    case SET_SHARED_VIDEO_STATUS:
72
+    }
73
+    case SET_SHARED_VIDEO_STATUS: {
74
+        const conference = getCurrentConference(state);
75
+        const localParticipantId = getLocalParticipant(state)?.id;
76
+        const { videoUrl, status, ownerId, time, muted, volume } = action;
77
+
51 78
         if (localParticipantId === ownerId) {
52 79
             sendShareVideoCommand({
53 80
                 conference,
@@ -60,8 +87,14 @@ MiddlewareRegistry.register(store => next => action => {
60 87
             });
61 88
         }
62 89
         break;
63
-    case RESET_SHARED_VIDEO_STATUS:
90
+    }
91
+    case RESET_SHARED_VIDEO_STATUS: {
92
+        const localParticipantId = getLocalParticipant(state)?.id;
93
+        const { ownerId: stateOwnerId, videoUrl: statevideoUrl } = state['features/shared-video'];
94
+
64 95
         if (localParticipantId === stateOwnerId) {
96
+            const conference = getCurrentConference(state);
97
+
65 98
             sendShareVideoCommand({
66 99
                 conference,
67 100
                 id: statevideoUrl,
@@ -74,41 +107,11 @@ MiddlewareRegistry.register(store => next => action => {
74 107
         }
75 108
         break;
76 109
     }
110
+    }
77 111
 
78 112
     return next(action);
79 113
 });
80 114
 
81
-/**
82
- * Set up state change listener to perform maintenance tasks when the conference
83
- * is left or failed, e.g. Clear messages or close the chat modal if it's left
84
- * open.
85
- */
86
-StateListenerRegistry.register(
87
-    state => getCurrentConference(state),
88
-    (conference, store, previousConference) => {
89
-        if (conference && conference !== previousConference) {
90
-            conference.addCommandListener(SHARED_VIDEO,
91
-                ({ value, attributes }) => {
92
-
93
-                    const { dispatch, getState } = store;
94
-                    const { from } = attributes;
95
-                    const localParticipantId = getLocalParticipant(getState()).id;
96
-                    const status = attributes.state;
97
-
98
-                    if (isSharingStatus(status)) {
99
-                        handleSharingVideoStatus(store, value, attributes, conference);
100
-                    } else if (status === 'stop') {
101
-                        dispatch(participantLeft(value, conference));
102
-                        if (localParticipantId !== from) {
103
-                            dispatch(resetSharedVideoStatus());
104
-                        }
105
-                    }
106
-                }
107
-            );
108
-        }
109
-    }
110
-);
111
-
112 115
 /**
113 116
  * Handles the playing, pause and start statuses for the shared video.
114 117
  * Dispatches participantJoined event and, if necessary, pins it.

+ 26
- 27
react/features/shared-video/middleware.web.js 查看文件

@@ -1,38 +1,37 @@
1 1
 // @flow
2 2
 
3
-import { getCurrentConference } from '../base/conference';
3
+import { CONFERENCE_JOIN_IN_PROGRESS } from '../base/conference/actionTypes';
4 4
 import { getLocalParticipant } from '../base/participants';
5
-import { StateListenerRegistry } from '../base/redux';
5
+import { MiddlewareRegistry } from '../base/redux';
6 6
 
7 7
 import { setDisableButton } from './actions.web';
8 8
 import { SHARED_VIDEO } from './constants';
9 9
 
10 10
 import './middleware.any';
11 11
 
12
-/**
13
- * Set up state change listener to disable or enable the share video button in
14
- * the toolbar menu.
15
- */
16
-StateListenerRegistry.register(
17
-    state => getCurrentConference(state),
18
-    (conference, store, previousConference) => {
19
-        if (conference && conference !== previousConference) {
20
-            conference.addCommandListener(SHARED_VIDEO,
21
-                ({ attributes }) => {
22
-                    const { dispatch, getState } = store;
23
-                    const { from } = attributes;
24
-                    const localParticipantId = getLocalParticipant(getState()).id;
25
-                    const status = attributes.state;
26
-
27
-                    if (status === 'playing') {
28
-                        if (localParticipantId !== from) {
29
-                            dispatch(setDisableButton(true));
30
-                        }
31
-                    } else if (status === 'stop') {
32
-                        dispatch(setDisableButton(false));
33
-                    }
12
+MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
13
+    const state = getState();
14
+    const localParticipantId = getLocalParticipant(state)?.id;
15
+
16
+    switch (action.type) {
17
+    case CONFERENCE_JOIN_IN_PROGRESS: {
18
+        const { conference } = action;
19
+
20
+        conference.addCommandListener(SHARED_VIDEO, ({ attributes }) => {
21
+            const { from } = attributes;
22
+            const status = attributes.state;
23
+
24
+            if (status === 'playing') {
25
+                if (localParticipantId !== from) {
26
+                    dispatch(setDisableButton(true));
34 27
                 }
35
-            );
36
-        }
28
+            } else if (status === 'stop') {
29
+                dispatch(setDisableButton(false));
30
+            }
31
+        });
32
+        break;
37 33
     }
38
-);
34
+    }
35
+
36
+    return next(action);
37
+});

+ 4
- 4
react/features/videosipgw/middleware.js 查看文件

@@ -1,6 +1,6 @@
1 1
 // @flow
2 2
 
3
-import { CONFERENCE_WILL_JOIN } from '../base/conference';
3
+import { CONFERENCE_JOIN_IN_PROGRESS } from '../base/conference/actionTypes';
4 4
 import {
5 5
     JitsiConferenceEvents,
6 6
     JitsiSIPVideoGWStatus
@@ -29,12 +29,12 @@ import logger from './logger';
29 29
  * @param {Store} store - The redux store.
30 30
  * @returns {Function}
31 31
  */
32
-MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
32
+MiddlewareRegistry.register(({ dispatch }) => next => action => {
33 33
     const result = next(action);
34 34
 
35 35
     switch (action.type) {
36
-    case CONFERENCE_WILL_JOIN: {
37
-        const conference = getState()['features/base/conference'].joining;
36
+    case CONFERENCE_JOIN_IN_PROGRESS: {
37
+        const { conference } = action;
38 38
 
39 39
         conference.on(
40 40
             JitsiConferenceEvents.VIDEO_SIP_GW_AVAILABILITY_CHANGED,

Loading…
取消
儲存