Selaa lähdekoodia

ref(hangup): clean up some UI state on hangup

- Reset some state on the singletons conference
  and VideoLayout.
- Add a way for LocalVideo to clean itself up
  by sharing logic with the other SmallVideos.
- Add clearing of chat messages so they don't
  linger.
- Remove some UI event listeners.
j8
Leonard Kim 6 vuotta sitten
vanhempi
commit
14cc4ea54a

+ 15
- 2
conference.js Näytä tiedosto

88
 import { updateSettings } from './react/features/base/settings';
88
 import { updateSettings } from './react/features/base/settings';
89
 import {
89
 import {
90
     createLocalTracksF,
90
     createLocalTracksF,
91
+    destroyLocalTracks,
91
     isLocalTrackMuted,
92
     isLocalTrackMuted,
92
     replaceLocalTrack,
93
     replaceLocalTrack,
93
     trackAdded,
94
     trackAdded,
2466
      */
2467
      */
2467
     hangup(requestFeedback = false) {
2468
     hangup(requestFeedback = false) {
2468
         eventEmitter.emit(JitsiMeetConferenceEvents.BEFORE_HANGUP);
2469
         eventEmitter.emit(JitsiMeetConferenceEvents.BEFORE_HANGUP);
2469
-        APP.UI.removeLocalMedia();
2470
+
2471
+        APP.store.dispatch(destroyLocalTracks());
2472
+        this._localTracksInitialized = false;
2473
+        this.localVideo = null;
2474
+        this.localAudio = null;
2470
 
2475
 
2471
         // Remove unnecessary event listeners from firing callbacks.
2476
         // Remove unnecessary event listeners from firing callbacks.
2472
         if (this.deviceChangeListener) {
2477
         if (this.deviceChangeListener) {
2475
                 this.deviceChangeListener);
2480
                 this.deviceChangeListener);
2476
         }
2481
         }
2477
 
2482
 
2483
+        APP.UI.removeAllListeners();
2484
+        APP.remoteControl.removeAllListeners();
2485
+
2478
         let requestFeedbackPromise;
2486
         let requestFeedbackPromise;
2479
 
2487
 
2480
         if (requestFeedback) {
2488
         if (requestFeedback) {
2508
     leaveRoomAndDisconnect() {
2516
     leaveRoomAndDisconnect() {
2509
         APP.store.dispatch(conferenceWillLeave(room));
2517
         APP.store.dispatch(conferenceWillLeave(room));
2510
 
2518
 
2511
-        return room.leave().then(disconnect, disconnect);
2519
+        return room.leave()
2520
+            .then(disconnect, disconnect)
2521
+            .then(() => {
2522
+                this._room = undefined;
2523
+                room = undefined;
2524
+            });
2512
     },
2525
     },
2513
 
2526
 
2514
     /**
2527
     /**

+ 9
- 19
modules/UI/UI.js Näytä tiedosto

18
     getLocalParticipant,
18
     getLocalParticipant,
19
     showParticipantJoinedNotification
19
     showParticipantJoinedNotification
20
 } from '../../react/features/base/participants';
20
 } from '../../react/features/base/participants';
21
-import { destroyLocalTracks } from '../../react/features/base/tracks';
22
 import { toggleChat } from '../../react/features/chat';
21
 import { toggleChat } from '../../react/features/chat';
23
 import { openDisplayNamePrompt } from '../../react/features/display-name';
22
 import { openDisplayNamePrompt } from '../../react/features/display-name';
24
 import { setEtherpadHasInitialzied } from '../../react/features/etherpad';
23
 import { setEtherpadHasInitialzied } from '../../react/features/etherpad';
294
 UI.registerListeners
293
 UI.registerListeners
295
     = () => UIListeners.forEach((value, key) => UI.addListener(key, value));
294
     = () => UIListeners.forEach((value, key) => UI.addListener(key, value));
296
 
295
 
297
-/**
298
- * Unregister some UI event listeners.
299
- */
300
-UI.unregisterListeners
301
-    = () => UIListeners.forEach((value, key) => UI.removeListener(key, value));
302
-
303
 /**
296
 /**
304
  * Setup some DOM event listeners.
297
  * Setup some DOM event listeners.
305
  */
298
  */
577
     eventEmitter.on(type, listener);
570
     eventEmitter.on(type, listener);
578
 };
571
 };
579
 
572
 
573
+/**
574
+ * Removes the all listeners for all events.
575
+ *
576
+ * @returns {void}
577
+ */
578
+UI.removeAllListeners = function() {
579
+    eventEmitter.removeAllListeners();
580
+};
581
+
580
 /**
582
 /**
581
  * Removes the given listener for the given type of event.
583
  * Removes the given listener for the given type of event.
582
  *
584
  *
968
     VideoLayout.setLocalRemoteControlActiveChanged();
970
     VideoLayout.setLocalRemoteControlActiveChanged();
969
 };
971
 };
970
 
972
 
971
-/**
972
- * Remove media tracks and UI elements so the user no longer sees media in the
973
- * UI. The intent is to provide a feeling that the meeting has ended.
974
- *
975
- * @returns {void}
976
- */
977
-UI.removeLocalMedia = function() {
978
-    APP.store.dispatch(destroyLocalTracks());
979
-    VideoLayout.resetLargeVideo();
980
-    $('#videospace').hide();
981
-};
982
-
983
 // TODO: Export every function separately. For now there is no point of doing
973
 // TODO: Export every function separately. For now there is no point of doing
984
 // this because we are importing everything.
974
 // this because we are importing everything.
985
 export default UI;
975
 export default UI;

+ 0
- 12
modules/UI/shared_video/SharedVideoThumb.js Näytä tiedosto

64
     return container;
64
     return container;
65
 };
65
 };
66
 
66
 
67
-/**
68
- * Removes RemoteVideo from the page.
69
- */
70
-SharedVideoThumb.prototype.remove = function() {
71
-    logger.log('Remove shared video thumb', this.id);
72
-
73
-    // Remove whole container
74
-    if (this.container.parentNode) {
75
-        this.container.parentNode.removeChild(this.container);
76
-    }
77
-};
78
-
79
 /**
67
 /**
80
  * Sets the display name for the thumb.
68
  * Sets the display name for the thumb.
81
  */
69
  */

+ 2
- 0
modules/UI/videolayout/LargeVideoManager.js Näytä tiedosto

108
             this._onVideoResolutionUpdate);
108
             this._onVideoResolutionUpdate);
109
 
109
 
110
         this.removePresenceLabel();
110
         this.removePresenceLabel();
111
+
112
+        this.$container.css({ display: 'none' });
111
     }
113
     }
112
 
114
 
113
     /**
115
     /**

+ 1
- 24
modules/UI/videolayout/RemoteVideo.js Näytä tiedosto

437
  * Removes RemoteVideo from the page.
437
  * Removes RemoteVideo from the page.
438
  */
438
  */
439
 RemoteVideo.prototype.remove = function() {
439
 RemoteVideo.prototype.remove = function() {
440
-    logger.log('Remove thumbnail', this.id);
441
-
442
-    this.removeAudioLevelIndicator();
443
-
444
-    const toolbarContainer
445
-        = this.container.querySelector('.videocontainer__toolbar');
446
-
447
-    if (toolbarContainer) {
448
-        ReactDOM.unmountComponentAtNode(toolbarContainer);
449
-    }
450
-
451
-    this.removeConnectionIndicator();
452
-
453
-    this.removeDisplayName();
454
-
455
-    this.removeAvatar();
440
+    SmallVideo.prototype.remove.call(this);
456
 
441
 
457
     this.removePresenceLabel();
442
     this.removePresenceLabel();
458
-
459
-    this._unmountIndicators();
460
-
461
     this.removeRemoteVideoMenu();
443
     this.removeRemoteVideoMenu();
462
-
463
-    // Remove whole container
464
-    if (this.container.parentNode) {
465
-        this.container.parentNode.removeChild(this.container);
466
-    }
467
 };
444
 };
468
 
445
 
469
 RemoteVideo.prototype.waitForPlayback = function(streamElement, stream) {
446
 RemoteVideo.prototype.waitForPlayback = function(streamElement, stream) {

+ 32
- 0
modules/UI/videolayout/SmallVideo.js Näytä tiedosto

745
     }
745
     }
746
 };
746
 };
747
 
747
 
748
+/**
749
+ * Cleans up components on {@code SmallVideo} and removes itself from the DOM.
750
+ *
751
+ * @returns {void}
752
+ */
753
+SmallVideo.prototype.remove = function() {
754
+    logger.log('Remove thumbnail', this.id);
755
+
756
+    this.removeAudioLevelIndicator();
757
+
758
+    const toolbarContainer
759
+        = this.container.querySelector('.videocontainer__toolbar');
760
+
761
+    if (toolbarContainer) {
762
+        ReactDOM.unmountComponentAtNode(toolbarContainer);
763
+    }
764
+
765
+    this.removeConnectionIndicator();
766
+
767
+    this.removeDisplayName();
768
+
769
+    this.removeAvatar();
770
+
771
+    this._unmountIndicators();
772
+
773
+    // Remove whole container
774
+    if (this.container.parentNode) {
775
+        this.container.parentNode.removeChild(this.container);
776
+    }
777
+};
778
+
748
 /**
779
 /**
749
  * Helper function for re-rendering multiple react components of the small
780
  * Helper function for re-rendering multiple react components of the small
750
  * video.
781
  * video.
938
     this.updateView();
969
     this.updateView();
939
 };
970
 };
940
 
971
 
972
+
941
 export default SmallVideo;
973
 export default SmallVideo;

+ 43
- 11
modules/UI/videolayout/VideoLayout.js Näytä tiedosto

133
     },
133
     },
134
 
134
 
135
     /**
135
     /**
136
-     * Cleans up any existing largeVideo instance.
136
+     * Registering listeners for UI events in Video layout component.
137
      *
137
      *
138
      * @returns {void}
138
      * @returns {void}
139
      */
139
      */
140
-    resetLargeVideo() {
141
-        if (largeVideo) {
142
-            largeVideo.destroy();
143
-        }
144
-        largeVideo = null;
140
+    registerListeners() {
141
+        eventEmitter.addListener(UIEvents.LOCAL_FLIPX_CHANGED,
142
+            onLocalFlipXChanged);
145
     },
143
     },
146
 
144
 
147
     /**
145
     /**
148
-     * Registering listeners for UI events in Video layout component.
146
+     * Cleans up state of this singleton {@code VideoLayout}.
149
      *
147
      *
150
      * @returns {void}
148
      * @returns {void}
151
      */
149
      */
152
-    registerListeners() {
153
-        eventEmitter.addListener(UIEvents.LOCAL_FLIPX_CHANGED,
154
-            onLocalFlipXChanged);
150
+    reset() {
151
+        this._resetLargeVideo();
152
+        this._resetFilmstrip();
155
     },
153
     },
156
 
154
 
157
     initLargeVideo() {
155
     initLargeVideo() {
158
-        this.resetLargeVideo();
156
+        this._resetLargeVideo();
159
 
157
 
160
         largeVideo = new LargeVideoManager(eventEmitter);
158
         largeVideo = new LargeVideoManager(eventEmitter);
161
         if (localFlipX) {
159
         if (localFlipX) {
1165
         );
1163
         );
1166
     },
1164
     },
1167
 
1165
 
1166
+    /**
1167
+     * Cleans up any existing largeVideo instance.
1168
+     *
1169
+     * @private
1170
+     * @returns {void}
1171
+     */
1172
+    _resetLargeVideo() {
1173
+        if (largeVideo) {
1174
+            largeVideo.destroy();
1175
+        }
1176
+
1177
+        largeVideo = null;
1178
+    },
1179
+
1180
+    /**
1181
+     * Cleans up filmstrip state. While a separate {@code Filmstrip} exists, its
1182
+     * implementation is mainly for querying and manipulating the DOM while
1183
+     * state mostly remains in {@code VideoLayout}.
1184
+     *
1185
+     * @private
1186
+     * @returns {void}
1187
+     */
1188
+    _resetFilmstrip() {
1189
+        Object.keys(remoteVideos).forEach(remoteVideoId => {
1190
+            this.removeParticipantContainer(remoteVideoId);
1191
+            delete remoteVideos[remoteVideoId];
1192
+        });
1193
+
1194
+        if (localVideoThumbnail) {
1195
+            localVideoThumbnail.remove();
1196
+            localVideoThumbnail = null;
1197
+        }
1198
+    },
1199
+
1168
     /**
1200
     /**
1169
      * Triggers an update of large video if the passed in participant is
1201
      * Triggers an update of large video if the passed in participant is
1170
      * currently displayed on large video.
1202
      * currently displayed on large video.

+ 9
- 0
react/features/chat/actionTypes.js Näytä tiedosto

13
  */
13
  */
14
 export const ADD_MESSAGE = Symbol('ADD_MESSAGE');
14
 export const ADD_MESSAGE = Symbol('ADD_MESSAGE');
15
 
15
 
16
+/**
17
+ * The type of the action which signals to remove all saved chat messages.
18
+ *
19
+ * {
20
+ *     type: CLEAR_MESSAGES
21
+ * }
22
+ */
23
+export const CLEAR_MESSAGES = Symbol('CLEAR_MESSAGES');
24
+
16
 /**
25
 /**
17
  * The type of the action which signals a send a chat message to everyone in the
26
  * The type of the action which signals a send a chat message to everyone in the
18
  * conference.
27
  * conference.

+ 19
- 3
react/features/chat/actions.js Näytä tiedosto

1
-import { ADD_MESSAGE, SEND_MESSAGE, TOGGLE_CHAT } from './actionTypes';
2
-
3
-/* eslint-disable max-params */
1
+import {
2
+    ADD_MESSAGE,
3
+    CLEAR_MESSAGES,
4
+    SEND_MESSAGE,
5
+    TOGGLE_CHAT
6
+} from './actionTypes';
4
 
7
 
5
 /**
8
 /**
6
  * Adds a chat message to the collection of messages.
9
  * Adds a chat message to the collection of messages.
31
     };
34
     };
32
 }
35
 }
33
 
36
 
37
+/**
38
+ * Removes all stored chat messages.
39
+ *
40
+ * @returns {{
41
+ *     type: CLEAR_MESSAGES
42
+ * }}
43
+ */
44
+export function clearMessages() {
45
+    return {
46
+        type: CLEAR_MESSAGES
47
+    };
48
+}
49
+
34
 /**
50
 /**
35
  * Sends a chat message to everyone in the conference.
51
  * Sends a chat message to everyone in the conference.
36
  *
52
  *

+ 6
- 2
react/features/chat/middleware.js Näytä tiedosto

3
 import UIUtil from '../../../modules/UI/util/UIUtil';
3
 import UIUtil from '../../../modules/UI/util/UIUtil';
4
 
4
 
5
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
5
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
6
-import { CONFERENCE_JOINED } from '../base/conference';
6
+import { CONFERENCE_JOINED, CONFERENCE_WILL_LEAVE } from '../base/conference';
7
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
7
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
8
 import { getParticipantById } from '../base/participants';
8
 import { getParticipantById } from '../base/participants';
9
 import { MiddlewareRegistry } from '../base/redux';
9
 import { MiddlewareRegistry } from '../base/redux';
11
 import { isButtonEnabled, showToolbox } from '../toolbox';
11
 import { isButtonEnabled, showToolbox } from '../toolbox';
12
 
12
 
13
 import { SEND_MESSAGE } from './actionTypes';
13
 import { SEND_MESSAGE } from './actionTypes';
14
-import { addMessage } from './actions';
14
+import { addMessage, clearMessages } from './actions';
15
 import { INCOMING_MSG_SOUND_ID } from './constants';
15
 import { INCOMING_MSG_SOUND_ID } from './constants';
16
 import { INCOMING_MSG_SOUND_FILE } from './sounds';
16
 import { INCOMING_MSG_SOUND_FILE } from './sounds';
17
 
17
 
46
             || _addChatMsgListener(action.conference, store);
46
             || _addChatMsgListener(action.conference, store);
47
         break;
47
         break;
48
 
48
 
49
+    case CONFERENCE_WILL_LEAVE:
50
+        store.dispatch(clearMessages());
51
+        break;
52
+
49
     case SEND_MESSAGE:
53
     case SEND_MESSAGE:
50
         if (typeof APP !== 'undefined') {
54
         if (typeof APP !== 'undefined') {
51
             const { conference } = store.getState()['features/base/conference'];
55
             const { conference } = store.getState()['features/base/conference'];

+ 8
- 1
react/features/chat/reducer.js Näytä tiedosto

2
 
2
 
3
 import { ReducerRegistry } from '../base/redux';
3
 import { ReducerRegistry } from '../base/redux';
4
 
4
 
5
-import { ADD_MESSAGE, TOGGLE_CHAT } from './actionTypes';
5
+import { ADD_MESSAGE, CLEAR_MESSAGES, TOGGLE_CHAT } from './actionTypes';
6
 
6
 
7
 const DEFAULT_STATE = {
7
 const DEFAULT_STATE = {
8
     isOpen: false,
8
     isOpen: false,
33
         };
33
         };
34
     }
34
     }
35
 
35
 
36
+    case CLEAR_MESSAGES:
37
+        return {
38
+            ...state,
39
+            lastReadMessage: undefined,
40
+            messages: []
41
+        };
42
+
36
     case TOGGLE_CHAT:
43
     case TOGGLE_CHAT:
37
         return {
44
         return {
38
             ...state,
45
             ...state,

+ 0
- 1
react/features/conference/components/Conference.web.js Näytä tiedosto

182
      * @inheritdoc
182
      * @inheritdoc
183
      */
183
      */
184
     componentWillUnmount() {
184
     componentWillUnmount() {
185
-        APP.UI.unregisterListeners();
186
         APP.UI.unbindEvents();
185
         APP.UI.unbindEvents();
187
 
186
 
188
         FULL_SCREEN_EVENTS.forEach(name =>
187
         FULL_SCREEN_EVENTS.forEach(name =>

+ 5
- 1
react/features/video-layout/middleware.web.js Näytä tiedosto

3
 import VideoLayout from '../../../modules/UI/videolayout/VideoLayout.js';
3
 import VideoLayout from '../../../modules/UI/videolayout/VideoLayout.js';
4
 import UIEvents from '../../../service/UI/UIEvents';
4
 import UIEvents from '../../../service/UI/UIEvents';
5
 
5
 
6
-import { CONFERENCE_JOINED } from '../base/conference';
6
+import { CONFERENCE_JOINED, CONFERENCE_WILL_LEAVE } from '../base/conference';
7
 import {
7
 import {
8
     DOMINANT_SPEAKER_CHANGED,
8
     DOMINANT_SPEAKER_CHANGED,
9
     PARTICIPANT_JOINED,
9
     PARTICIPANT_JOINED,
40
         VideoLayout.mucJoined();
40
         VideoLayout.mucJoined();
41
         break;
41
         break;
42
 
42
 
43
+    case CONFERENCE_WILL_LEAVE:
44
+        VideoLayout.reset();
45
+        break;
46
+
43
     case PARTICIPANT_JOINED:
47
     case PARTICIPANT_JOINED:
44
         if (!action.participant.local) {
48
         if (!action.participant.local) {
45
             VideoLayout.addRemoteParticipantContainer(
49
             VideoLayout.addRemoteParticipantContainer(

Loading…
Peruuta
Tallenna