浏览代码

ref(notifications): bring hiding of notifications into redux

j8
Leonard Kim 8 年前
父节点
当前提交
cd66a7fcb7

+ 3
- 26
modules/UI/UI.js 查看文件

@@ -40,7 +40,8 @@ import {
40 40
     showToolbox
41 41
 } from '../../react/features/toolbox';
42 42
 import {
43
-    maybeShowNotificationWithDoNotDisplay
43
+    maybeShowNotificationWithDoNotDisplay,
44
+    setNotificationsEnabled
44 45
 } from '../../react/features/notifications';
45 46
 
46 47
 var EventEmitter = require("events");
@@ -51,17 +52,6 @@ import FollowMe from "../FollowMe";
51 52
 var eventEmitter = new EventEmitter();
52 53
 UI.eventEmitter = eventEmitter;
53 54
 
54
-/**
55
- * Whether an overlay is visible or not.
56
- *
57
- * FIXME: This is temporary solution. Don't use this variable!
58
- * Should be removed when all the code is move to react.
59
- *
60
- * @type {boolean}
61
- * @public
62
- */
63
-UI.overlayVisible = false;
64
-
65 55
 let etherpadManager;
66 56
 let sharedVideoManager;
67 57
 
@@ -335,7 +325,7 @@ UI.start = function () {
335 325
         $("body").addClass("filmstrip-only");
336 326
         UI.showToolbar();
337 327
         Filmstrip.setFilmstripOnly();
338
-        messageHandler.enableNotifications(false);
328
+        APP.store.dispatch(setNotificationsEnabled(false));
339 329
         JitsiPopover.enabled = false;
340 330
     }
341 331
 
@@ -1307,19 +1297,6 @@ UI.onSharedVideoStop = function (id, attributes) {
1307 1297
         sharedVideoManager.onSharedVideoStop(id, attributes);
1308 1298
 };
1309 1299
 
1310
-/**
1311
- * Indicates if any the "top" overlays are currently visible. The check includes
1312
- * the call/ring overlay, the suspended overlay, the GUM permissions overlay,
1313
- * and the page-reload overlay.
1314
- *
1315
- * @returns {*|boolean} {true} if an overlay is visible; {false}, otherwise
1316
- */
1317
-UI.isOverlayVisible = function () {
1318
-    return (
1319
-        this.overlayVisible
1320
-            || APP.store.getState()['features/jwt'].callOverlayVisible);
1321
-};
1322
-
1323 1300
 /**
1324 1301
  * Handles user's features changes.
1325 1302
  */

+ 2
- 1
modules/UI/recording/Recording.js 查看文件

@@ -22,6 +22,7 @@ import VideoLayout from '../videolayout/VideoLayout';
22 22
 import Feedback from '../feedback/Feedback.js';
23 23
 
24 24
 import { setToolboxEnabled } from '../../../react/features/toolbox';
25
+import { setNotificationsEnabled } from '../../../react/features/notifications';
25 26
 
26 27
 /**
27 28
  * The dialog for user input.
@@ -309,7 +310,7 @@ var Recording = {
309 310
             VideoLayout.setLocalVideoVisible(false);
310 311
             Feedback.enableFeedback(false);
311 312
             APP.store.dispatch(setToolboxEnabled(false));
312
-            APP.UI.messageHandler.enableNotifications(false);
313
+            APP.store.dispatch(setNotificationsEnabled(false));
313 314
             APP.UI.messageHandler.enablePopups(false);
314 315
         }
315 316
 

+ 0
- 23
modules/UI/util/MessageHandler.js 查看文件

@@ -8,12 +8,6 @@ import {
8 8
     showNotification
9 9
 } from '../../../react/features/notifications';
10 10
 
11
-/**
12
- * Flag for enable/disable of the notifications.
13
- * @type {boolean}
14
- */
15
-let notificationsEnabled = true;
16
-
17 11
 /**
18 12
  * Flag for enabling/disabling popups.
19 13
  * @type {boolean}
@@ -456,11 +450,6 @@ var messageHandler = {
456 450
      */
457 451
     participantNotification: function(displayName, displayNameKey, cls,
458 452
                     messageKey, messageArguments, timeout = 2500) {
459
-        // If we're in ringing state we skip all notifications.
460
-        if (!notificationsEnabled || APP.UI.isOverlayVisible()) {
461
-            return;
462
-        }
463
-
464 453
         APP.store.dispatch(
465 454
             showNotification(
466 455
                 Notification,
@@ -485,22 +474,10 @@ var messageHandler = {
485 474
      * @returns {void}
486 475
      */
487 476
     notify: function(titleKey, messageKey, messageArguments) {
488
-
489
-        // If we're in ringing state we skip all notifications.
490
-        if(!notificationsEnabled || APP.UI.isOverlayVisible())
491
-            return;
492
-
493 477
         this.participantNotification(
494 478
             null, titleKey, null, messageKey, messageArguments);
495 479
     },
496 480
 
497
-    /**
498
-     * Enables / disables notifications.
499
-     */
500
-    enableNotifications: function (enable) {
501
-        notificationsEnabled = enable;
502
-    },
503
-
504 481
     enablePopups: function (enable) {
505 482
         popupEnabled = enable;
506 483
     },

+ 1
- 1
react/features/conference/components/Conference.web.js 查看文件

@@ -79,7 +79,7 @@ class Conference extends Component {
79 79
                 { filmStripOnly ? null : <Toolbox /> }
80 80
 
81 81
                 <DialogContainer />
82
-                { filmStripOnly ? null : <NotificationsContainer /> }
82
+                <NotificationsContainer />
83 83
                 <OverlayContainer />
84 84
 
85 85
                 {/*

+ 13
- 2
react/features/notifications/actionTypes.js 查看文件

@@ -1,4 +1,4 @@
1
-/*
1
+/**
2 2
  * The type of (redux) action which signals that a specific notification should
3 3
  * not be displayed anymore.
4 4
  *
@@ -9,7 +9,7 @@
9 9
  */
10 10
 export const HIDE_NOTIFICATION = Symbol('HIDE_NOTIFICATION');
11 11
 
12
-/*
12
+/**
13 13
  * The type of (redux) action which signals that a notification component should
14 14
  * be displayed.
15 15
  *
@@ -22,3 +22,14 @@ export const HIDE_NOTIFICATION = Symbol('HIDE_NOTIFICATION');
22 22
  * }
23 23
  */
24 24
 export const SHOW_NOTIFICATION = Symbol('SHOW_NOTIFICATION');
25
+
26
+/**
27
+ * The type of (redux) action which signals that notifications should not
28
+ * display.
29
+ *
30
+ * {
31
+ *     type: SET_NOTIFICATIONS_ENABLED,
32
+ *     enabled: Boolean
33
+ * }
34
+ */
35
+export const SET_NOTIFICATIONS_ENABLED = Symbol('SET_NOTIFICATIONS_ENABLED');

+ 17
- 0
react/features/notifications/actions.js 查看文件

@@ -2,6 +2,7 @@ import jitsiLocalStorage from '../../../modules/util/JitsiLocalStorage';
2 2
 
3 3
 import {
4 4
     HIDE_NOTIFICATION,
5
+    SET_NOTIFICATIONS_ENABLED,
5 6
     SHOW_NOTIFICATION
6 7
 } from './actionTypes';
7 8
 import { NotificationWithToggle } from './components';
@@ -23,6 +24,22 @@ export function hideNotification(uid) {
23 24
     };
24 25
 }
25 26
 
27
+/**
28
+ * Stops notifications from being displayed.
29
+ *
30
+ * @param {boolean} enabled - Whether or not notifications should display.
31
+ * @returns {{
32
+ *     type: SET_NOTIFICATIONS_ENABLED,
33
+ *     enabled: boolean
34
+ * }}
35
+ */
36
+export function setNotificationsEnabled(enabled) {
37
+    return {
38
+        type: SET_NOTIFICATIONS_ENABLED,
39
+        enabled
40
+    };
41
+}
42
+
26 43
 /**
27 44
  * Queues a notification for display.
28 45
  *

+ 76
- 31
react/features/notifications/components/NotificationsContainer.web.js 查看文件

@@ -24,6 +24,12 @@ class NotificationsContainer extends Component {
24 24
          */
25 25
         _notifications: React.PropTypes.array,
26 26
 
27
+        /**
28
+         * Whether or not notifications should be displayed at all. If not,
29
+         * notifications will be dismissed immediately.
30
+         */
31
+        _showNotifications: React.PropTypes.bool,
32
+
27 33
         /**
28 34
          * Invoked to update the redux store in order to remove notifications.
29 35
          */
@@ -59,18 +65,27 @@ class NotificationsContainer extends Component {
59 65
      * returns {void}
60 66
      */
61 67
     componentDidUpdate() {
62
-        const { _notifications } = this.props;
68
+        const { _notifications, _showNotifications } = this.props;
63 69
 
64
-        if (_notifications.length && !this._notificationDismissTimeout) {
70
+        if (_notifications.length) {
65 71
             const notification = _notifications[0];
66
-            const { timeout, uid } = notification;
67
-
68
-            this._notificationDismissTimeout = setTimeout(() => {
69
-                // Perform a no-op if a timeout is not specified.
70
-                if (Number.isInteger(timeout)) {
71
-                    this._onDismissed(uid);
72
-                }
73
-            }, timeout);
72
+
73
+            if (!_showNotifications) {
74
+                this._onDismissed(notification.uid);
75
+            } else if (this._notificationDismissTimeout) {
76
+
77
+                // No-op because there should already be a notification that
78
+                // is waiting for dismissal.
79
+            } else {
80
+                const { timeout, uid } = notification;
81
+
82
+                this._notificationDismissTimeout = setTimeout(() => {
83
+                    // Perform a no-op if a timeout is not specified.
84
+                    if (Number.isInteger(timeout)) {
85
+                        this._onDismissed(uid);
86
+                    }
87
+                }, timeout);
88
+            }
74 89
         }
75 90
     }
76 91
 
@@ -91,28 +106,9 @@ class NotificationsContainer extends Component {
91 106
      * @returns {ReactElement}
92 107
      */
93 108
     render() {
94
-        const { _notifications } = this.props;
95
-
96
-        const flags = _notifications.map(notification => {
97
-            const Notification = notification.component;
98
-            const { props, uid } = notification;
99
-
100
-            // The id attribute is necessary as {@code FlagGroup} looks for
101
-            // either id or key to set a key on notifications, but accessing
102
-            // props.key will cause React to print an error.
103
-            return (
104
-                <Notification
105
-                    { ...props }
106
-                    id = { uid }
107
-                    key = { uid }
108
-                    uid = { uid } />
109
-
110
-            );
111
-        });
112
-
113 109
         return (
114 110
             <FlagGroup onDismissed = { this._onDismissed }>
115
-                { flags }
111
+                { this._renderFlags() }
116 112
             </FlagGroup>
117 113
         );
118 114
     }
@@ -131,6 +127,38 @@ class NotificationsContainer extends Component {
131 127
 
132 128
         this.props.dispatch(hideNotification(flagUid));
133 129
     }
130
+
131
+    /**
132
+     * Renders notifications to display as ReactElements. An empty array will
133
+     * be returned if notifications are disabled.
134
+     *
135
+     * @private
136
+     * @returns {ReactElement[]}
137
+     */
138
+    _renderFlags() {
139
+        const { _notifications, _showNotifications } = this.props;
140
+
141
+        if (!_showNotifications) {
142
+            return [];
143
+        }
144
+
145
+        return _notifications.map(notification => {
146
+            const Notification = notification.component;
147
+            const { props, uid } = notification;
148
+
149
+            // The id attribute is necessary as {@code FlagGroup} looks for
150
+            // either id or key to set a key on notifications, but accessing
151
+            // props.key will cause React to print an error.
152
+            return (
153
+                <Notification
154
+                    { ...props }
155
+                    id = { uid }
156
+                    key = { uid }
157
+                    uid = { uid } />
158
+
159
+            );
160
+        });
161
+    }
134 162
 }
135 163
 
136 164
 /**
@@ -144,8 +172,25 @@ class NotificationsContainer extends Component {
144 172
  * }}
145 173
  */
146 174
 function _mapStateToProps(state) {
175
+    // TODO: Per existing behavior, notifications should not display when an
176
+    // overlay is visible. This logic for checking overlay display can likely be
177
+    // simplified.
178
+    const {
179
+        connectionEstablished,
180
+        haveToReload,
181
+        isMediaPermissionPromptVisible,
182
+        suspendDetected
183
+    } = state['features/overlay'];
184
+    const isAnyOverlayVisible = (connectionEstablished && haveToReload)
185
+        || isMediaPermissionPromptVisible
186
+        || suspendDetected
187
+        || state['features/jwt'].callOverlayVisible;
188
+
189
+    const { enabled, notifications } = state['features/notifications'];
190
+
147 191
     return {
148
-        _notifications: state['features/notifications']
192
+        _notifications: notifications,
193
+        _showNotifications: enabled && !isAnyOverlayVisible
149 194
     };
150 195
 }
151 196
 

+ 27
- 11
react/features/notifications/reducer.js 查看文件

@@ -2,6 +2,7 @@ import { ReducerRegistry } from '../base/redux';
2 2
 
3 3
 import {
4 4
     HIDE_NOTIFICATION,
5
+    SET_NOTIFICATIONS_ENABLED,
5 6
     SHOW_NOTIFICATION
6 7
 } from './actionTypes';
7 8
 
@@ -10,7 +11,10 @@ import {
10 11
  *
11 12
  * @type {array}
12 13
  */
13
-const DEFAULT_STATE = [];
14
+const DEFAULT_STATE = {
15
+    enabled: true,
16
+    notifications: []
17
+};
14 18
 
15 19
 /**
16 20
  * Reduces redux actions which affect the display of notifications.
@@ -24,19 +28,31 @@ ReducerRegistry.register('features/notifications',
24 28
     (state = DEFAULT_STATE, action) => {
25 29
         switch (action.type) {
26 30
         case HIDE_NOTIFICATION:
27
-            return state.filter(
28
-                notification => notification.uid !== action.uid);
31
+            return {
32
+                ...state,
33
+                notifications: state.notifications.filter(
34
+                    notification => notification.uid !== action.uid)
35
+            };
36
+
37
+        case SET_NOTIFICATIONS_ENABLED:
38
+            return {
39
+                ...state,
40
+                enabled: action.enabled
41
+            };
29 42
 
30 43
         case SHOW_NOTIFICATION:
31
-            return [
44
+            return {
32 45
                 ...state,
33
-                {
34
-                    component: action.component,
35
-                    props: action.props,
36
-                    timeout: action.timeout,
37
-                    uid: action.uid
38
-                }
39
-            ];
46
+                notifications: [
47
+                    ...state.notifications,
48
+                    {
49
+                        component: action.component,
50
+                        props: action.props,
51
+                        timeout: action.timeout,
52
+                        uid: action.uid
53
+                    }
54
+                ]
55
+            };
40 56
         }
41 57
 
42 58
         return state;

+ 0
- 18
react/features/overlay/components/OverlayContainer.js 查看文件

@@ -11,7 +11,6 @@ import UserMediaPermissionsFilmstripOnlyOverlay
11 11
     from './UserMediaPermissionsFilmstripOnlyOverlay';
12 12
 import UserMediaPermissionsOverlay from './UserMediaPermissionsOverlay';
13 13
 
14
-declare var APP: Object;
15 14
 declare var interfaceConfig: Object;
16 15
 
17 16
 /**
@@ -133,23 +132,6 @@ class OverlayContainer extends Component {
133 132
         };
134 133
     }
135 134
 
136
-    /**
137
-     * React Component method that executes once component is updated.
138
-     *
139
-     * @inheritdoc
140
-     * @returns {void}
141
-     * @protected
142
-     */
143
-    componentDidUpdate() {
144
-        if (typeof APP === 'object') {
145
-            APP.UI.overlayVisible
146
-                = (this.props._connectionEstablished
147
-                        && this.props._haveToReload)
148
-                    || this.props._suspendDetected
149
-                    || this.props._isMediaPermissionPromptVisible;
150
-        }
151
-    }
152
-
153 135
     /**
154 136
      * Implements React's {@link Component#render()}.
155 137
      *

正在加载...
取消
保存