浏览代码

ref(notifications): bring hiding of notifications into redux

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

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

40
     showToolbox
40
     showToolbox
41
 } from '../../react/features/toolbox';
41
 } from '../../react/features/toolbox';
42
 import {
42
 import {
43
-    maybeShowNotificationWithDoNotDisplay
43
+    maybeShowNotificationWithDoNotDisplay,
44
+    setNotificationsEnabled
44
 } from '../../react/features/notifications';
45
 } from '../../react/features/notifications';
45
 
46
 
46
 var EventEmitter = require("events");
47
 var EventEmitter = require("events");
51
 var eventEmitter = new EventEmitter();
52
 var eventEmitter = new EventEmitter();
52
 UI.eventEmitter = eventEmitter;
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
 let etherpadManager;
55
 let etherpadManager;
66
 let sharedVideoManager;
56
 let sharedVideoManager;
67
 
57
 
335
         $("body").addClass("filmstrip-only");
325
         $("body").addClass("filmstrip-only");
336
         UI.showToolbar();
326
         UI.showToolbar();
337
         Filmstrip.setFilmstripOnly();
327
         Filmstrip.setFilmstripOnly();
338
-        messageHandler.enableNotifications(false);
328
+        APP.store.dispatch(setNotificationsEnabled(false));
339
         JitsiPopover.enabled = false;
329
         JitsiPopover.enabled = false;
340
     }
330
     }
341
 
331
 
1307
         sharedVideoManager.onSharedVideoStop(id, attributes);
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
  * Handles user's features changes.
1301
  * Handles user's features changes.
1325
  */
1302
  */

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

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

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

8
     showNotification
8
     showNotification
9
 } from '../../../react/features/notifications';
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
  * Flag for enabling/disabling popups.
12
  * Flag for enabling/disabling popups.
19
  * @type {boolean}
13
  * @type {boolean}
456
      */
450
      */
457
     participantNotification: function(displayName, displayNameKey, cls,
451
     participantNotification: function(displayName, displayNameKey, cls,
458
                     messageKey, messageArguments, timeout = 2500) {
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
         APP.store.dispatch(
453
         APP.store.dispatch(
465
             showNotification(
454
             showNotification(
466
                 Notification,
455
                 Notification,
485
      * @returns {void}
474
      * @returns {void}
486
      */
475
      */
487
     notify: function(titleKey, messageKey, messageArguments) {
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
         this.participantNotification(
477
         this.participantNotification(
494
             null, titleKey, null, messageKey, messageArguments);
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
     enablePopups: function (enable) {
481
     enablePopups: function (enable) {
505
         popupEnabled = enable;
482
         popupEnabled = enable;
506
     },
483
     },

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

79
                 { filmStripOnly ? null : <Toolbox /> }
79
                 { filmStripOnly ? null : <Toolbox /> }
80
 
80
 
81
                 <DialogContainer />
81
                 <DialogContainer />
82
-                { filmStripOnly ? null : <NotificationsContainer /> }
82
+                <NotificationsContainer />
83
                 <OverlayContainer />
83
                 <OverlayContainer />
84
 
84
 
85
                 {/*
85
                 {/*

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

1
-/*
1
+/**
2
  * The type of (redux) action which signals that a specific notification should
2
  * The type of (redux) action which signals that a specific notification should
3
  * not be displayed anymore.
3
  * not be displayed anymore.
4
  *
4
  *
9
  */
9
  */
10
 export const HIDE_NOTIFICATION = Symbol('HIDE_NOTIFICATION');
10
 export const HIDE_NOTIFICATION = Symbol('HIDE_NOTIFICATION');
11
 
11
 
12
-/*
12
+/**
13
  * The type of (redux) action which signals that a notification component should
13
  * The type of (redux) action which signals that a notification component should
14
  * be displayed.
14
  * be displayed.
15
  *
15
  *
22
  * }
22
  * }
23
  */
23
  */
24
 export const SHOW_NOTIFICATION = Symbol('SHOW_NOTIFICATION');
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
 
2
 
3
 import {
3
 import {
4
     HIDE_NOTIFICATION,
4
     HIDE_NOTIFICATION,
5
+    SET_NOTIFICATIONS_ENABLED,
5
     SHOW_NOTIFICATION
6
     SHOW_NOTIFICATION
6
 } from './actionTypes';
7
 } from './actionTypes';
7
 import { NotificationWithToggle } from './components';
8
 import { NotificationWithToggle } from './components';
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
  * Queues a notification for display.
44
  * Queues a notification for display.
28
  *
45
  *

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

24
          */
24
          */
25
         _notifications: React.PropTypes.array,
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
          * Invoked to update the redux store in order to remove notifications.
34
          * Invoked to update the redux store in order to remove notifications.
29
          */
35
          */
59
      * returns {void}
65
      * returns {void}
60
      */
66
      */
61
     componentDidUpdate() {
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
             const notification = _notifications[0];
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
      * @returns {ReactElement}
106
      * @returns {ReactElement}
92
      */
107
      */
93
     render() {
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
         return (
109
         return (
114
             <FlagGroup onDismissed = { this._onDismissed }>
110
             <FlagGroup onDismissed = { this._onDismissed }>
115
-                { flags }
111
+                { this._renderFlags() }
116
             </FlagGroup>
112
             </FlagGroup>
117
         );
113
         );
118
     }
114
     }
131
 
127
 
132
         this.props.dispatch(hideNotification(flagUid));
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
  * }}
172
  * }}
145
  */
173
  */
146
 function _mapStateToProps(state) {
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
     return {
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
 
2
 
3
 import {
3
 import {
4
     HIDE_NOTIFICATION,
4
     HIDE_NOTIFICATION,
5
+    SET_NOTIFICATIONS_ENABLED,
5
     SHOW_NOTIFICATION
6
     SHOW_NOTIFICATION
6
 } from './actionTypes';
7
 } from './actionTypes';
7
 
8
 
10
  *
11
  *
11
  * @type {array}
12
  * @type {array}
12
  */
13
  */
13
-const DEFAULT_STATE = [];
14
+const DEFAULT_STATE = {
15
+    enabled: true,
16
+    notifications: []
17
+};
14
 
18
 
15
 /**
19
 /**
16
  * Reduces redux actions which affect the display of notifications.
20
  * Reduces redux actions which affect the display of notifications.
24
     (state = DEFAULT_STATE, action) => {
28
     (state = DEFAULT_STATE, action) => {
25
         switch (action.type) {
29
         switch (action.type) {
26
         case HIDE_NOTIFICATION:
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
         case SHOW_NOTIFICATION:
43
         case SHOW_NOTIFICATION:
31
-            return [
44
+            return {
32
                 ...state,
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
         return state;
58
         return state;

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

11
     from './UserMediaPermissionsFilmstripOnlyOverlay';
11
     from './UserMediaPermissionsFilmstripOnlyOverlay';
12
 import UserMediaPermissionsOverlay from './UserMediaPermissionsOverlay';
12
 import UserMediaPermissionsOverlay from './UserMediaPermissionsOverlay';
13
 
13
 
14
-declare var APP: Object;
15
 declare var interfaceConfig: Object;
14
 declare var interfaceConfig: Object;
16
 
15
 
17
 /**
16
 /**
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
      * Implements React's {@link Component#render()}.
136
      * Implements React's {@link Component#render()}.
155
      *
137
      *

正在加载...
取消
保存