Просмотр исходного кода

feat(notifications) revisit timeouts and make them configurable

master
Tudor D. Pop 3 лет назад
Родитель
Сommit
a618697e34
Аккаунт пользователя с таким Email не найден
42 измененных файлов: 220 добавлений и 206 удалений
  1. 16
    4
      conference.js
  2. 7
    0
      config.js
  3. 0
    7
      interface_config.js
  4. 10
    28
      modules/UI/UI.js
  5. 3
    32
      modules/UI/util/MessageHandler.js
  6. 2
    2
      react/features/app/actions.js
  7. 3
    2
      react/features/av-moderation/middleware.js
  8. 4
    4
      react/features/base/conference/middleware.any.js
  9. 1
    0
      react/features/base/config/configWhitelist.js
  10. 0
    1
      react/features/base/config/interfaceConfigWhitelist.js
  11. 4
    6
      react/features/base/devices/middleware.js
  12. 3
    3
      react/features/base/participants/actions.js
  13. 2
    2
      react/features/base/participants/middleware.js
  14. 6
    4
      react/features/base/tracks/actions.js
  15. 2
    1
      react/features/conference/actions.web.js
  16. 2
    2
      react/features/conference/functions.web.js
  17. 2
    2
      react/features/invite/components/add-people-dialog/AbstractAddPeopleDialog.js
  18. 38
    20
      react/features/lobby/middleware.js
  19. 3
    2
      react/features/local-recording/middleware.js
  20. 2
    2
      react/features/no-audio-signal/middleware.js
  21. 2
    2
      react/features/noise-detection/middleware.js
  22. 32
    12
      react/features/notifications/actions.js
  23. 4
    13
      react/features/notifications/components/web/NotificationsContainer.js
  24. 16
    1
      react/features/notifications/constants.js
  25. 4
    7
      react/features/notifications/middleware.js
  26. 2
    2
      react/features/old-client-notification/middleware.js
  27. 2
    2
      react/features/polls/subscriber.js
  28. 5
    5
      react/features/prejoin/actions.js
  29. 2
    2
      react/features/reactions/middleware.js
  30. 6
    6
      react/features/recording/actions.any.js
  31. 2
    2
      react/features/recording/actions.native.js
  32. 2
    2
      react/features/recording/actions.web.js
  33. 2
    2
      react/features/recording/components/Recording/AbstractStartRecordingDialog.js
  34. 5
    5
      react/features/remote-control/actions.js
  35. 3
    3
      react/features/room-lock/middleware.js
  36. 2
    1
      react/features/shared-video/components/web/AbstractVideoManager.js
  37. 3
    2
      react/features/stream-effects/virtual-background/index.js
  38. 2
    1
      react/features/talk-while-muted/middleware.js
  39. 4
    4
      react/features/transcribing/actions.js
  40. 6
    5
      react/features/videosipgw/middleware.js
  41. 2
    2
      react/features/virtual-background/components/VirtualBackgroundDialog.js
  42. 2
    1
      react/features/virtual-background/components/VirtualBackgroundPreview.js

+ 16
- 4
conference.js Просмотреть файл

123
     maybeOpenFeedbackDialog,
123
     maybeOpenFeedbackDialog,
124
     submitFeedback
124
     submitFeedback
125
 } from './react/features/feedback';
125
 } from './react/features/feedback';
126
-import { isModerationNotificationDisplayed, showNotification } from './react/features/notifications';
126
+import {
127
+    isModerationNotificationDisplayed,
128
+    showNotification,
129
+    NOTIFICATION_TIMEOUT_TYPE
130
+} from './react/features/notifications';
127
 import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
131
 import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
128
 import { suspendDetected } from './react/features/power-monitor';
132
 import { suspendDetected } from './react/features/power-monitor';
129
 import {
133
 import {
357
         case JitsiConferenceErrors.FOCUS_DISCONNECTED: {
361
         case JitsiConferenceErrors.FOCUS_DISCONNECTED: {
358
             const [ focus, retrySec ] = params;
362
             const [ focus, retrySec ] = params;
359
 
363
 
360
-            APP.UI.notifyFocusDisconnected(focus, retrySec);
364
+            APP.store.dispatch(showNotification({
365
+                descriptionKey: focus,
366
+                titleKey: retrySec
367
+            }, NOTIFICATION_TIMEOUT_TYPE.SHORT));
361
             break;
368
             break;
362
         }
369
         }
363
 
370
 
755
             APP.store.dispatch(showNotification({
762
             APP.store.dispatch(showNotification({
756
                 descriptionKey: 'notify.startSilentDescription',
763
                 descriptionKey: 'notify.startSilentDescription',
757
                 titleKey: 'notify.startSilentTitle'
764
                 titleKey: 'notify.startSilentTitle'
758
-            }));
765
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
759
         }
766
         }
760
 
767
 
761
         // XXX The API will take care of disconnecting from the XMPP
768
         // XXX The API will take care of disconnecting from the XMPP
2364
             }
2371
             }
2365
 
2372
 
2366
             Promise.allSettled(promises)
2373
             Promise.allSettled(promises)
2367
-                .then(() => APP.UI.notifyInitiallyMuted());
2374
+                .then(() => {
2375
+                    APP.store.dispatch(showNotification({
2376
+                        titleKey: 'notify.mutedTitle',
2377
+                        descriptionKey: 'notify.muted'
2378
+                    }, NOTIFICATION_TIMEOUT_TYPE.SHORT));
2379
+                });
2368
         });
2380
         });
2369
 
2381
 
2370
         room.on(
2382
         room.on(

+ 7
- 0
config.js Просмотреть файл

375
     //    resizeDesktopForPresenter: false
375
     //    resizeDesktopForPresenter: false
376
     // },
376
     // },
377
 
377
 
378
+    // Notification timeouts
379
+    // notificationTimeouts: {
380
+    //     short: 2500,
381
+    //     medium: 5000,
382
+    //     long: 10000
383
+    // },
384
+
378
     // // Options for the recording limit notification.
385
     // // Options for the recording limit notification.
379
     // recordingLimit: {
386
     // recordingLimit: {
380
     //
387
     //

+ 0
- 7
interface_config.js Просмотреть файл

225
      */
225
      */
226
     // ANDROID_APP_PACKAGE: 'org.jitsi.meet',
226
     // ANDROID_APP_PACKAGE: 'org.jitsi.meet',
227
 
227
 
228
-    /**
229
-     * Override the behavior of some notifications to remain displayed until
230
-     * explicitly dismissed through a user action. The value is how long, in
231
-     * milliseconds, those notifications should remain displayed.
232
-     */
233
-    // ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT: 15000,
234
-
235
     // List of undocumented settings
228
     // List of undocumented settings
236
     /**
229
     /**
237
      INDICATOR_FONT_SIZES
230
      INDICATOR_FONT_SIZES

+ 10
- 28
modules/UI/UI.js Просмотреть файл

10
 import { setColorAlpha } from '../../react/features/base/util';
10
 import { setColorAlpha } from '../../react/features/base/util';
11
 import { setDocumentUrl } from '../../react/features/etherpad';
11
 import { setDocumentUrl } from '../../react/features/etherpad';
12
 import { setFilmstripVisible } from '../../react/features/filmstrip';
12
 import { setFilmstripVisible } from '../../react/features/filmstrip';
13
-import { joinLeaveNotificationsDisabled, setNotificationsEnabled } from '../../react/features/notifications';
13
+import {
14
+    joinLeaveNotificationsDisabled,
15
+    setNotificationsEnabled,
16
+    showNotification,
17
+    NOTIFICATION_TIMEOUT_TYPE
18
+} from '../../react/features/notifications';
14
 import {
19
 import {
15
     dockToolbox,
20
     dockToolbox,
16
     setToolboxEnabled,
21
     setToolboxEnabled,
215
 
220
 
216
     const displayName = user.getDisplayName();
221
     const displayName = user.getDisplayName();
217
 
222
 
218
-    messageHandler.participantNotification(
219
-        displayName,
220
-        '',
221
-        'connected',
222
-        'dialOut.statusMessage',
223
-        { status: UIUtil.escapeHtml(status) });
223
+    APP.store.dispatch(showNotification({
224
+        titleKey: `${displayName} connected`,
225
+        descriptionKey: 'dialOut.statusMessage'
226
+    }, NOTIFICATION_TIMEOUT_TYPE.SHORT));
224
 };
227
 };
225
 
228
 
226
 /**
229
 /**
333
     });
336
     });
334
 };
337
 };
335
 
338
 
336
-/**
337
- * Notify user that he was automatically muted when joned the conference.
338
- */
339
-UI.notifyInitiallyMuted = function() {
340
-    messageHandler.participantNotification(
341
-        null,
342
-        'notify.mutedTitle',
343
-        'connected',
344
-        'notify.muted',
345
-        null);
346
-};
347
-
348
 UI.handleLastNEndpoints = function(leavingIds, enteringIds) {
339
 UI.handleLastNEndpoints = function(leavingIds, enteringIds) {
349
     VideoLayout.onLastNEndpointsChanged(leavingIds, enteringIds);
340
     VideoLayout.onLastNEndpointsChanged(leavingIds, enteringIds);
350
 };
341
 };
363
     });
354
     });
364
 };
355
 };
365
 
356
 
366
-UI.notifyFocusDisconnected = function(focus, retrySec) {
367
-    messageHandler.participantNotification(
368
-        null, 'notify.focus',
369
-        'disconnected', 'notify.focusFail',
370
-        { component: focus,
371
-            ms: retrySec }
372
-    );
373
-};
374
-
375
 /**
357
 /**
376
  * Update list of available physical devices.
358
  * Update list of available physical devices.
377
  */
359
  */

+ 3
- 32
modules/UI/util/MessageHandler.js Просмотреть файл

1
 /* global APP */
1
 /* global APP */
2
 
2
 
3
 import {
3
 import {
4
-    NOTIFICATION_TIMEOUT,
4
+    NOTIFICATION_TIMEOUT_TYPE,
5
     showErrorNotification,
5
     showErrorNotification,
6
-    showNotification,
7
     showWarningNotification
6
     showWarningNotification
8
 } from '../../../react/features/notifications';
7
 } from '../../../react/features/notifications';
9
 
8
 
48
      * showErrorNotification action.
47
      * showErrorNotification action.
49
      */
48
      */
50
     showError(props) {
49
     showError(props) {
51
-        APP.store.dispatch(showErrorNotification(props));
50
+        APP.store.dispatch(showErrorNotification(props, NOTIFICATION_TIMEOUT_TYPE.LONG));
52
     },
51
     },
53
 
52
 
54
     /**
53
     /**
58
      * showWarningNotification action.
57
      * showWarningNotification action.
59
      */
58
      */
60
     showWarning(props) {
59
     showWarning(props) {
61
-        APP.store.dispatch(showWarningNotification(props));
62
-    },
63
-
64
-    /**
65
-     * Displays a notification about participant action.
66
-     * @param displayName the display name of the participant that is
67
-     * associated with the notification.
68
-     * @param displayNameKey the key from the language file for the display
69
-     * name. Only used if displayName is not provided.
70
-     * @param cls css class for the notification
71
-     * @param messageKey the key from the language file for the text of the
72
-     * message.
73
-     * @param messageArguments object with the arguments for the message.
74
-     * @param optional configurations for the notification (e.g. timeout)
75
-     */
76
-    participantNotification( // eslint-disable-line max-params
77
-            displayName,
78
-            displayNameKey,
79
-            cls,
80
-            messageKey,
81
-            messageArguments,
82
-            timeout = NOTIFICATION_TIMEOUT) {
83
-        APP.store.dispatch(showNotification({
84
-            descriptionArguments: messageArguments,
85
-            descriptionKey: messageKey,
86
-            titleKey: displayNameKey,
87
-            title: displayName
88
-        },
89
-        timeout));
60
+        APP.store.dispatch(showWarningNotification(props, NOTIFICATION_TIMEOUT_TYPE.LONG));
90
     }
61
     }
91
 };
62
 };
92
 
63
 

+ 2
- 2
react/features/app/actions.js Просмотреть файл

25
     toURLString
25
     toURLString
26
 } from '../base/util';
26
 } from '../base/util';
27
 import { isVpaasMeeting } from '../jaas/functions';
27
 import { isVpaasMeeting } from '../jaas/functions';
28
-import { clearNotifications, showNotification } from '../notifications';
28
+import { NOTIFICATION_TIMEOUT_TYPE, clearNotifications, showNotification } from '../notifications';
29
 import { setFatalError } from '../overlay';
29
 import { setFatalError } from '../overlay';
30
 
30
 
31
 import {
31
 import {
328
             dispatch(showNotification({
328
             dispatch(showNotification({
329
                 titleArguments: { appName: getName() },
329
                 titleArguments: { appName: getName() },
330
                 titleKey: 'dialog.thankYou'
330
                 titleKey: 'dialog.thankYou'
331
-            }));
331
+            }, NOTIFICATION_TIMEOUT_TYPE.STICKY));
332
         }
332
         }
333
 
333
 
334
         // if Welcome page is enabled redirect to welcome page after 3 sec, if
334
         // if Welcome page is enabled redirect to welcome page after 3 sec, if

+ 3
- 2
react/features/av-moderation/middleware.js Просмотреть файл

17
 import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
17
 import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
18
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
18
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
19
 import {
19
 import {
20
+    NOTIFICATION_TIMEOUT_TYPE,
20
     hideNotification,
21
     hideNotification,
21
     showNotification
22
     showNotification
22
 } from '../notifications';
23
 } from '../notifications';
106
             sticky: true,
107
             sticky: true,
107
             titleKey,
108
             titleKey,
108
             uid
109
             uid
109
-        }));
110
+        }, NOTIFICATION_TIMEOUT_TYPE.STICKY));
110
 
111
 
111
         break;
112
         break;
112
     }
113
     }
222
                         sticky: true,
223
                         sticky: true,
223
                         customActionNameKey: 'notify.unmute',
224
                         customActionNameKey: 'notify.unmute',
224
                         customActionHandler: () => dispatch(muteLocal(false, MEDIA_TYPE.AUDIO))
225
                         customActionHandler: () => dispatch(muteLocal(false, MEDIA_TYPE.AUDIO))
225
-                    }));
226
+                    }, NOTIFICATION_TIMEOUT_TYPE.STICKY));
226
                     dispatch(playSound(ASKED_TO_UNMUTE_SOUND_ID));
227
                     dispatch(playSound(ASKED_TO_UNMUTE_SOUND_ID));
227
                 }
228
                 }
228
             });
229
             });

+ 4
- 4
react/features/base/conference/middleware.any.js Просмотреть файл

9
 } from '../../analytics';
9
 } from '../../analytics';
10
 import { reloadNow } from '../../app/actions';
10
 import { reloadNow } from '../../app/actions';
11
 import { openDisplayNamePrompt } from '../../display-name';
11
 import { openDisplayNamePrompt } from '../../display-name';
12
-import { showErrorNotification } from '../../notifications';
12
+import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification } from '../../notifications';
13
 import { CONNECTION_ESTABLISHED, CONNECTION_FAILED, connectionDisconnected } from '../connection';
13
 import { CONNECTION_ESTABLISHED, CONNECTION_FAILED, connectionDisconnected } from '../connection';
14
 import { validateJwt } from '../jwt';
14
 import { validateJwt } from '../jwt';
15
 import { JitsiConferenceErrors } from '../lib-jitsi-meet';
15
 import { JitsiConferenceErrors } from '../lib-jitsi-meet';
129
         dispatch(showErrorNotification({
129
         dispatch(showErrorNotification({
130
             description: reason,
130
             description: reason,
131
             titleKey: 'dialog.sessTerminated'
131
             titleKey: 'dialog.sessTerminated'
132
-        }));
132
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
133
 
133
 
134
         break;
134
         break;
135
     }
135
     }
138
             dispatch(showErrorNotification({
138
             dispatch(showErrorNotification({
139
                 description: 'Restart initiated because of a bridge failure',
139
                 description: 'Restart initiated because of a bridge failure',
140
                 titleKey: 'dialog.sessionRestarted'
140
                 titleKey: 'dialog.sessionRestarted'
141
-            }));
141
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
142
         }
142
         }
143
 
143
 
144
         break;
144
         break;
151
             descriptionArguments: { msg },
151
             descriptionArguments: { msg },
152
             descriptionKey: msg ? 'dialog.connectErrorWithMsg' : 'dialog.connectError',
152
             descriptionKey: msg ? 'dialog.connectErrorWithMsg' : 'dialog.connectError',
153
             titleKey: 'connection.CONNFAIL'
153
             titleKey: 'connection.CONNFAIL'
154
-        }));
154
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
155
 
155
 
156
         break;
156
         break;
157
     }
157
     }

+ 1
- 0
react/features/base/config/configWhitelist.js Просмотреть файл

172
     'maxFullResolutionParticipants',
172
     'maxFullResolutionParticipants',
173
     'mouseMoveCallbackInterval',
173
     'mouseMoveCallbackInterval',
174
     'notifications',
174
     'notifications',
175
+    'notificationTimeouts',
175
     'openSharedDocumentOnJoin',
176
     'openSharedDocumentOnJoin',
176
     'opusMaxAverageBitrate',
177
     'opusMaxAverageBitrate',
177
     'p2p',
178
     'p2p',

+ 0
- 1
react/features/base/config/interfaceConfigWhitelist.js Просмотреть файл

26
     'DISPLAY_WELCOME_PAGE_CONTENT',
26
     'DISPLAY_WELCOME_PAGE_CONTENT',
27
     'ENABLE_DIAL_OUT',
27
     'ENABLE_DIAL_OUT',
28
     'ENABLE_FEEDBACK_ANIMATION',
28
     'ENABLE_FEEDBACK_ANIMATION',
29
-    'ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT',
30
     'FILM_STRIP_MAX_HEIGHT',
29
     'FILM_STRIP_MAX_HEIGHT',
31
     'GENERATE_ROOMNAMES_ON_WELCOME_PAGE',
30
     'GENERATE_ROOMNAMES_ON_WELCOME_PAGE',
32
     'HIDE_INVITE_MORE_HEADER',
31
     'HIDE_INVITE_MORE_HEADER',

+ 4
- 6
react/features/base/devices/middleware.js Просмотреть файл

2
 
2
 
3
 import UIEvents from '../../../../service/UI/UIEvents';
3
 import UIEvents from '../../../../service/UI/UIEvents';
4
 import { processExternalDeviceRequest } from '../../device-selection';
4
 import { processExternalDeviceRequest } from '../../device-selection';
5
-import { showNotification, showWarningNotification } from '../../notifications';
5
+import { NOTIFICATION_TIMEOUT_TYPE, showNotification, showWarningNotification } from '../../notifications';
6
 import { replaceAudioTrackById, replaceVideoTrackById, setDeviceStatusWarning } from '../../prejoin/actions';
6
 import { replaceAudioTrackById, replaceVideoTrackById, setDeviceStatusWarning } from '../../prejoin/actions';
7
 import { isPrejoinPageVisible } from '../../prejoin/functions';
7
 import { isPrejoinPageVisible } from '../../prejoin/functions';
8
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
8
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
50
     }
50
     }
51
 };
51
 };
52
 
52
 
53
-const WARNING_DISPLAY_TIMER = 4000;
54
-
55
 /**
53
 /**
56
  * A listener for device permissions changed reported from lib-jitsi-meet.
54
  * A listener for device permissions changed reported from lib-jitsi-meet.
57
  */
55
  */
134
             description: additionalCameraErrorMsg,
132
             description: additionalCameraErrorMsg,
135
             descriptionKey: cameraErrorMsg,
133
             descriptionKey: cameraErrorMsg,
136
             titleKey
134
             titleKey
137
-        }, WARNING_DISPLAY_TIMER));
135
+        }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
138
 
136
 
139
         if (isPrejoinPageVisible(store.getState())) {
137
         if (isPrejoinPageVisible(store.getState())) {
140
             store.dispatch(setDeviceStatusWarning(titleKey));
138
             store.dispatch(setDeviceStatusWarning(titleKey));
163
             description: additionalMicErrorMsg,
161
             description: additionalMicErrorMsg,
164
             descriptionKey: micErrorMsg,
162
             descriptionKey: micErrorMsg,
165
             titleKey
163
             titleKey
166
-        }, WARNING_DISPLAY_TIMER));
164
+        }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
167
 
165
 
168
         if (isPrejoinPageVisible(store.getState())) {
166
         if (isPrejoinPageVisible(store.getState())) {
169
             store.dispatch(setDeviceStatusWarning(titleKey));
167
             store.dispatch(setDeviceStatusWarning(titleKey));
298
                 titleKey,
296
                 titleKey,
299
                 customActionNameKey: 'notify.newDeviceAction',
297
                 customActionNameKey: 'notify.newDeviceAction',
300
                 customActionHandler: _useDevice.bind(undefined, store, devicesArray)
298
                 customActionHandler: _useDevice.bind(undefined, store, devicesArray)
301
-            }));
299
+            }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
302
         }
300
         }
303
     });
301
     });
304
 }
302
 }

+ 3
- 3
react/features/base/participants/actions.js Просмотреть файл

1
-import { NOTIFICATION_TIMEOUT, showNotification } from '../../notifications';
1
+import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../../notifications';
2
 import { set } from '../redux';
2
 import { set } from '../redux';
3
 
3
 
4
 import {
4
 import {
478
             titleArguments: {
478
             titleArguments: {
479
                 participantDisplayName: getParticipantDisplayName(getState, participant.getId())
479
                 participantDisplayName: getParticipantDisplayName(getState, participant.getId())
480
             }
480
             }
481
-        }));
481
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
482
     };
482
     };
483
 }
483
 }
484
 
484
 
510
                     getParticipantDisplayName(getState, kicker.getId())
510
                     getParticipantDisplayName(getState, kicker.getId())
511
             },
511
             },
512
             titleKey: 'notify.kickParticipant'
512
             titleKey: 'notify.kickParticipant'
513
-        }, NOTIFICATION_TIMEOUT * 2)); // leave more time for this
513
+        }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
514
     };
514
     };
515
 }
515
 }
516
 
516
 

+ 2
- 2
react/features/base/participants/middleware.js Просмотреть файл

6
 import { approveParticipant } from '../../av-moderation/actions';
6
 import { approveParticipant } from '../../av-moderation/actions';
7
 import { toggleE2EE } from '../../e2ee/actions';
7
 import { toggleE2EE } from '../../e2ee/actions';
8
 import { MAX_MODE } from '../../e2ee/constants';
8
 import { MAX_MODE } from '../../e2ee/constants';
9
-import { NOTIFICATION_TIMEOUT, showNotification } from '../../notifications';
9
+import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../../notifications';
10
 import { isForceMuted } from '../../participants-pane/functions';
10
 import { isForceMuted } from '../../participants-pane/functions';
11
 import { CALLING, INVITED } from '../../presence-status';
11
 import { CALLING, INVITED } from '../../presence-status';
12
 import { RAISE_HAND_SOUND_ID } from '../../reactions/constants';
12
 import { RAISE_HAND_SOUND_ID } from '../../reactions/constants';
562
             raiseHandNotification: true,
562
             raiseHandNotification: true,
563
             concatText: true,
563
             concatText: true,
564
             ...action
564
             ...action
565
-        }, NOTIFICATION_TIMEOUT * (shouldDisplayAllowAction ? 2 : 1)));
565
+        }, shouldDisplayAllowAction ? NOTIFICATION_TIMEOUT_TYPE.MEDIUM : NOTIFICATION_TIMEOUT_TYPE.SHORT));
566
         dispatch(playSound(RAISE_HAND_SOUND_ID));
566
         dispatch(playSound(RAISE_HAND_SOUND_ID));
567
     }
567
     }
568
 }
568
 }

+ 6
- 4
react/features/base/tracks/actions.js Просмотреть файл

4
     createTrackMutedEvent,
4
     createTrackMutedEvent,
5
     sendAnalytics
5
     sendAnalytics
6
 } from '../../analytics';
6
 } from '../../analytics';
7
-import { showErrorNotification, showNotification } from '../../notifications';
7
+import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification, showNotification } from '../../notifications';
8
 import { JitsiTrackErrors, JitsiTrackEvents, createLocalTrack } from '../lib-jitsi-meet';
8
 import { JitsiTrackErrors, JitsiTrackEvents, createLocalTrack } from '../lib-jitsi-meet';
9
 import {
9
 import {
10
     CAMERA_FACING_MODE,
10
     CAMERA_FACING_MODE,
245
             const notificationAction = await dispatch(showErrorNotification({
245
             const notificationAction = await dispatch(showErrorNotification({
246
                 descriptionKey: 'dialog.cameraNotSendingData',
246
                 descriptionKey: 'dialog.cameraNotSendingData',
247
                 titleKey: 'dialog.cameraNotSendingDataTitle'
247
                 titleKey: 'dialog.cameraNotSendingDataTitle'
248
-            }));
248
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
249
 
249
 
250
             notificationInfo = {
250
             notificationInfo = {
251
                 uid: notificationAction.uid
251
                 uid: notificationAction.uid
397
                     const notificationAction = await dispatch(showNotification({
397
                     const notificationAction = await dispatch(showNotification({
398
                         descriptionKey: 'dialog.micNotSendingData',
398
                         descriptionKey: 'dialog.micNotSendingData',
399
                         titleKey: 'dialog.micNotSendingDataTitle'
399
                         titleKey: 'dialog.micNotSendingDataTitle'
400
-                    }));
400
+                    }, NOTIFICATION_TIMEOUT_TYPE.LONG));
401
 
401
 
402
                     // Set the notification ID so that other parts of the application know that this was
402
                     // Set the notification ID so that other parts of the application know that this was
403
                     // displayed in the context of the current device.
403
                     // displayed in the context of the current device.
406
 
406
 
407
                     noDataFromSourceNotificationInfo = { uid: notificationAction.uid };
407
                     noDataFromSourceNotificationInfo = { uid: notificationAction.uid };
408
                 } else {
408
                 } else {
409
-                    const timeout = setTimeout(() => dispatch(showNoDataFromSourceVideoError(track)), 5000);
409
+                    const timeout = setTimeout(() => dispatch(
410
+                        showNoDataFromSourceVideoError(track)),
411
+                        NOTIFICATION_TIMEOUT_TYPE.MEDIUM);
410
 
412
 
411
                     noDataFromSourceNotificationInfo = { timeout };
413
                     noDataFromSourceNotificationInfo = { timeout };
412
                 }
414
                 }

+ 2
- 1
react/features/conference/actions.web.js Просмотреть файл

4
 
4
 
5
 import { getParticipantDisplayName } from '../base/participants';
5
 import { getParticipantDisplayName } from '../base/participants';
6
 import {
6
 import {
7
+    NOTIFICATION_TIMEOUT_TYPE,
7
     NOTIFICATION_TYPE,
8
     NOTIFICATION_TYPE,
8
     showNotification
9
     showNotification
9
 } from '../notifications';
10
 } from '../notifications';
34
             descriptionArguments: args,
35
             descriptionArguments: args,
35
             titleKey: 'dialog.kickTitle',
36
             titleKey: 'dialog.kickTitle',
36
             titleArguments: args
37
             titleArguments: args
37
-        }));
38
+        }, NOTIFICATION_TIMEOUT_TYPE.STICKY));
38
     };
39
     };
39
 }
40
 }

+ 2
- 2
react/features/conference/functions.web.js Просмотреть файл

1
 import { isSuboptimalBrowser } from '../base/environment';
1
 import { isSuboptimalBrowser } from '../base/environment';
2
 import { translateToHTML } from '../base/i18n';
2
 import { translateToHTML } from '../base/i18n';
3
-import { showWarningNotification } from '../notifications';
3
+import { NOTIFICATION_TIMEOUT_TYPE, showWarningNotification } from '../notifications';
4
 
4
 
5
 export * from './functions.any';
5
 export * from './functions.any';
6
 
6
 
24
                             recommendedBrowserPageLink: `${window.location.origin}/static/recommendedBrowsers.html`
24
                             recommendedBrowserPageLink: `${window.location.origin}/static/recommendedBrowsers.html`
25
                         }
25
                         }
26
                     )
26
                     )
27
-                }
27
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG
28
             )
28
             )
29
         );
29
         );
30
     }
30
     }

+ 2
- 2
react/features/invite/components/add-people-dialog/AbstractAddPeopleDialog.js Просмотреть файл

4
 
4
 
5
 import { createInviteDialogEvent, sendAnalytics } from '../../../analytics';
5
 import { createInviteDialogEvent, sendAnalytics } from '../../../analytics';
6
 import {
6
 import {
7
-    NOTIFICATION_TIMEOUT,
7
+    NOTIFICATION_TIMEOUT_TYPE,
8
     showNotification
8
     showNotification
9
 } from '../../../notifications';
9
 } from '../../../notifications';
10
 import { invite } from '../../actions';
10
 import { invite } from '../../actions';
203
 
203
 
204
                     if (notificationProps) {
204
                     if (notificationProps) {
205
                         dispatch(
205
                         dispatch(
206
-                            showNotification(notificationProps, NOTIFICATION_TIMEOUT));
206
+                            showNotification(notificationProps, NOTIFICATION_TIMEOUT_TYPE.SHORT));
207
                     }
207
                     }
208
                 }
208
                 }
209
 
209
 

+ 38
- 20
react/features/lobby/middleware.js Просмотреть файл

9
 import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
9
 import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
10
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
10
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
11
 import { isTestModeEnabled } from '../base/testing';
11
 import { isTestModeEnabled } from '../base/testing';
12
-import { NOTIFICATION_TYPE, showNotification } from '../notifications';
12
+import {
13
+    NOTIFICATION_TIMEOUT_TYPE,
14
+    NOTIFICATION_TYPE,
15
+    showNotification
16
+} from '../notifications';
13
 import { shouldAutoKnock } from '../prejoin/functions';
17
 import { shouldAutoKnock } from '../prejoin/functions';
14
 
18
 
15
 import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED } from './actionTypes';
19
 import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED } from './actionTypes';
66
 
70
 
67
             conference.on(JitsiConferenceEvents.LOBBY_USER_JOINED, (id, name) => {
71
             conference.on(JitsiConferenceEvents.LOBBY_USER_JOINED, (id, name) => {
68
                 batch(() => {
72
                 batch(() => {
69
-                    dispatch(participantIsKnockingOrUpdated({
70
-                        id,
71
-                        name
72
-                    }));
73
+                    dispatch(
74
+                        participantIsKnockingOrUpdated({
75
+                            id,
76
+                            name
77
+                        })
78
+                    );
73
                     dispatch(playSound(KNOCKING_PARTICIPANT_SOUND_ID));
79
                     dispatch(playSound(KNOCKING_PARTICIPANT_SOUND_ID));
74
                     if (typeof APP !== 'undefined') {
80
                     if (typeof APP !== 'undefined') {
75
                         APP.API.notifyKnockingParticipant({
81
                         APP.API.notifyKnockingParticipant({
81
             });
87
             });
82
 
88
 
83
             conference.on(JitsiConferenceEvents.LOBBY_USER_UPDATED, (id, participant) => {
89
             conference.on(JitsiConferenceEvents.LOBBY_USER_UPDATED, (id, participant) => {
84
-                dispatch(participantIsKnockingOrUpdated({
85
-                    ...participant,
86
-                    id
87
-                }));
90
+                dispatch(
91
+                    participantIsKnockingOrUpdated({
92
+                        ...participant,
93
+                        id
94
+                    })
95
+                );
88
             });
96
             });
89
 
97
 
90
             conference.on(JitsiConferenceEvents.LOBBY_USER_LEFT, id => {
98
             conference.on(JitsiConferenceEvents.LOBBY_USER_LEFT, id => {
98
                 })
106
                 })
99
             );
107
             );
100
         }
108
         }
101
-    });
109
+    }
110
+);
102
 
111
 
103
 /**
112
 /**
104
  * Function to handle the conference failed event and navigate the user to the lobby screen
113
  * Function to handle the conference failed event and navigate the user to the lobby screen
135
     dispatch(hideLobbyScreen());
144
     dispatch(hideLobbyScreen());
136
 
145
 
137
     if (error.name === JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED) {
146
     if (error.name === JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED) {
138
-        dispatch(showNotification({
139
-            appearance: NOTIFICATION_TYPE.ERROR,
140
-            hideErrorSupportLink: true,
141
-            titleKey: 'lobby.joinRejectedMessage'
142
-        }));
147
+        dispatch(
148
+            showNotification({
149
+                appearance: NOTIFICATION_TYPE.ERROR,
150
+                hideErrorSupportLink: true,
151
+                titleKey: 'lobby.joinRejectedMessage'
152
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG)
153
+        );
143
     }
154
     }
144
 
155
 
145
     return next(action);
156
     return next(action);
174
     if (!disableThirdPartyRequests && updatedParticipant && !updatedParticipant.loadableAvatarUrl) {
185
     if (!disableThirdPartyRequests && updatedParticipant && !updatedParticipant.loadableAvatarUrl) {
175
         getFirstLoadableAvatarUrl(updatedParticipant, store).then(loadableAvatarUrl => {
186
         getFirstLoadableAvatarUrl(updatedParticipant, store).then(loadableAvatarUrl => {
176
             if (loadableAvatarUrl) {
187
             if (loadableAvatarUrl) {
177
-                dispatch(participantIsKnockingOrUpdated({
178
-                    loadableAvatarUrl,
179
-                    id
180
-                }));
188
+                dispatch(
189
+                    participantIsKnockingOrUpdated({
190
+                        loadableAvatarUrl,
191
+                        id
192
+                    })
193
+                );
181
             }
194
             }
182
         });
195
         });
183
     }
196
     }
217
         break;
230
         break;
218
     }
231
     }
219
 
232
 
220
-    dispatch(showNotification(notificationProps, isTestModeEnabled(getState()) ? undefined : 5000));
233
+    dispatch(
234
+        showNotification(
235
+            notificationProps,
236
+            isTestModeEnabled(getState()) ? NOTIFICATION_TIMEOUT_TYPE.STICKY : NOTIFICATION_TIMEOUT_TYPE.MEDIUM
237
+        )
238
+    );
221
 }
239
 }

+ 3
- 2
react/features/local-recording/middleware.js Просмотреть файл

8
 import { SET_AUDIO_MUTED } from '../base/media/actionTypes';
8
 import { SET_AUDIO_MUTED } from '../base/media/actionTypes';
9
 import { MiddlewareRegistry } from '../base/redux';
9
 import { MiddlewareRegistry } from '../base/redux';
10
 import { SETTINGS_UPDATED } from '../base/settings/actionTypes';
10
 import { SETTINGS_UPDATED } from '../base/settings/actionTypes';
11
+import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications';
11
 import { showNotification } from '../notifications/actions';
12
 import { showNotification } from '../notifications/actions';
12
 
13
 
13
 import { localRecordingEngaged, localRecordingUnengaged } from './actions';
14
 import { localRecordingEngaged, localRecordingUnengaged } from './actions';
48
             dispatch(showNotification({
49
             dispatch(showNotification({
49
                 titleKey: 'localRecording.localRecording',
50
                 titleKey: 'localRecording.localRecording',
50
                 description: i18next.t(messageKey, messageParams)
51
                 description: i18next.t(messageKey, messageParams)
51
-            }, 10000));
52
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
52
         };
53
         };
53
 
54
 
54
         recordingController.onNotify = (messageKey, messageParams) => {
55
         recordingController.onNotify = (messageKey, messageParams) => {
55
             dispatch(showNotification({
56
             dispatch(showNotification({
56
                 titleKey: 'localRecording.localRecording',
57
                 titleKey: 'localRecording.localRecording',
57
                 description: i18next.t(messageKey, messageParams)
58
                 description: i18next.t(messageKey, messageParams)
58
-            }, 10000));
59
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
59
         };
60
         };
60
 
61
 
61
         typeof APP === 'object' && typeof APP.keyboardshortcut === 'object'
62
         typeof APP === 'object' && typeof APP.keyboardshortcut === 'object'

+ 2
- 2
react/features/no-audio-signal/middleware.js Просмотреть файл

12
 import { MiddlewareRegistry } from '../base/redux';
12
 import { MiddlewareRegistry } from '../base/redux';
13
 import { updateSettings } from '../base/settings';
13
 import { updateSettings } from '../base/settings';
14
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
14
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
15
-import { hideNotification, showNotification } from '../notifications';
15
+import { NOTIFICATION_TIMEOUT_TYPE, hideNotification, showNotification } from '../notifications';
16
 
16
 
17
 import { setNoAudioSignalNotificationUid } from './actions';
17
 import { setNoAudioSignalNotificationUid } from './actions';
18
 import DialInLink from './components/DialInLink';
18
 import DialInLink from './components/DialInLink';
114
             descriptionKey,
114
             descriptionKey,
115
             customActionNameKey,
115
             customActionNameKey,
116
             customActionHandler
116
             customActionHandler
117
-        }));
117
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
118
 
118
 
119
         dispatch(playSound(NO_AUDIO_SIGNAL_SOUND_ID));
119
         dispatch(playSound(NO_AUDIO_SIGNAL_SOUND_ID));
120
 
120
 

+ 2
- 2
react/features/noise-detection/middleware.js Просмотреть файл

5
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
5
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
6
 import { MiddlewareRegistry } from '../base/redux';
6
 import { MiddlewareRegistry } from '../base/redux';
7
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
7
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
8
-import { hideNotification, showNotification } from '../notifications';
8
+import { NOTIFICATION_TIMEOUT_TYPE, hideNotification, showNotification } from '../notifications';
9
 
9
 
10
 import { setNoisyAudioInputNotificationUid } from './actions';
10
 import { setNoisyAudioInputNotificationUid } from './actions';
11
 import { NOISY_AUDIO_INPUT_SOUND_ID } from './constants';
11
 import { NOISY_AUDIO_INPUT_SOUND_ID } from './constants';
41
                 const notification = await dispatch(showNotification({
41
                 const notification = await dispatch(showNotification({
42
                     titleKey: 'toolbar.noisyAudioInputTitle',
42
                     titleKey: 'toolbar.noisyAudioInputTitle',
43
                     descriptionKey: 'toolbar.noisyAudioInputDesc'
43
                     descriptionKey: 'toolbar.noisyAudioInputDesc'
44
-                }));
44
+                }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
45
 
45
 
46
                 dispatch(playSound(NOISY_AUDIO_INPUT_SOUND_ID));
46
                 dispatch(playSound(NOISY_AUDIO_INPUT_SOUND_ID));
47
 
47
 

+ 32
- 12
react/features/notifications/actions.js Просмотреть файл

14
     SHOW_NOTIFICATION
14
     SHOW_NOTIFICATION
15
 } from './actionTypes';
15
 } from './actionTypes';
16
 import {
16
 import {
17
+    NOTIFICATION_TIMEOUT_TYPE,
17
     NOTIFICATION_TIMEOUT,
18
     NOTIFICATION_TIMEOUT,
18
     NOTIFICATION_TYPE,
19
     NOTIFICATION_TYPE,
19
     SILENT_JOIN_THRESHOLD
20
     SILENT_JOIN_THRESHOLD
20
 } from './constants';
21
 } from './constants';
21
 
22
 
23
+/**
24
+ * Function that returns notification timeout value based on notification timeout type.
25
+ *
26
+ * @param {string} type - Notification type.
27
+ * @param {Object} notificationTimeouts - Config notification timeouts.
28
+ * @returns {number}
29
+ */
30
+function getNotificationTimeout(type: ?string, notificationTimeouts: ?Object) {
31
+    if (type === NOTIFICATION_TIMEOUT_TYPE.SHORT) {
32
+        return notificationTimeouts?.short ?? NOTIFICATION_TIMEOUT.SHORT;
33
+    } else if (type === NOTIFICATION_TIMEOUT_TYPE.MEDIUM) {
34
+        return notificationTimeouts?.medium ?? NOTIFICATION_TIMEOUT.MEDIUM;
35
+    } else if (type === NOTIFICATION_TIMEOUT_TYPE.LONG) {
36
+        return notificationTimeouts?.long ?? NOTIFICATION_TIMEOUT.LONG;
37
+    }
38
+
39
+    return NOTIFICATION_TIMEOUT.STICKY;
40
+}
41
+
22
 /**
42
 /**
23
  * Clears (removes) all the notifications.
43
  * Clears (removes) all the notifications.
24
  *
44
  *
82
  * Queues an error notification for display.
102
  * Queues an error notification for display.
83
  *
103
  *
84
  * @param {Object} props - The props needed to show the notification component.
104
  * @param {Object} props - The props needed to show the notification component.
105
+ * @param {string} type - Notification type.
85
  * @returns {Object}
106
  * @returns {Object}
86
  */
107
  */
87
-export function showErrorNotification(props: Object) {
108
+export function showErrorNotification(props: Object, type: ?string) {
88
     return showNotification({
109
     return showNotification({
89
         ...props,
110
         ...props,
90
         appearance: NOTIFICATION_TYPE.ERROR
111
         appearance: NOTIFICATION_TYPE.ERROR
91
-    });
112
+    }, type);
92
 }
113
 }
93
 
114
 
94
 /**
115
 /**
95
  * Queues a notification for display.
116
  * Queues a notification for display.
96
  *
117
  *
97
  * @param {Object} props - The props needed to show the notification component.
118
  * @param {Object} props - The props needed to show the notification component.
98
- * @param {number} timeout - How long the notification should display before
99
- * automatically being hidden.
119
+ * @param {string} type - Notification type.
100
  * @returns {Function}
120
  * @returns {Function}
101
  */
121
  */
102
-export function showNotification(props: Object = {}, timeout: ?number) {
122
+export function showNotification(props: Object = {}, type: ?string) {
103
     return function(dispatch: Function, getState: Function) {
123
     return function(dispatch: Function, getState: Function) {
104
-        const { notifications } = getState()['features/base/config'];
124
+        const { notifications, notificationTimeouts } = getState()['features/base/config'];
105
         const enabledFlag = getFeatureFlag(getState(), NOTIFICATIONS_ENABLED, true);
125
         const enabledFlag = getFeatureFlag(getState(), NOTIFICATIONS_ENABLED, true);
106
 
126
 
107
         const shouldDisplay = enabledFlag
127
         const shouldDisplay = enabledFlag
113
             return dispatch({
133
             return dispatch({
114
                 type: SHOW_NOTIFICATION,
134
                 type: SHOW_NOTIFICATION,
115
                 props,
135
                 props,
116
-                timeout,
136
+                timeout: getNotificationTimeout(type, notificationTimeouts),
117
                 uid: props.uid || window.Date.now().toString()
137
                 uid: props.uid || window.Date.now().toString()
118
             });
138
             });
119
         }
139
         }
124
  * Queues a warning notification for display.
144
  * Queues a warning notification for display.
125
  *
145
  *
126
  * @param {Object} props - The props needed to show the notification component.
146
  * @param {Object} props - The props needed to show the notification component.
127
- * @param {number} timeout - How long the notification should display before
128
- * automatically being hidden.
147
+ * @param {string} type - Notification type.
129
  * @returns {Object}
148
  * @returns {Object}
130
  */
149
  */
131
-export function showWarningNotification(props: Object, timeout: ?number) {
150
+export function showWarningNotification(props: Object, type: ?string) {
151
+
132
     return showNotification({
152
     return showNotification({
133
         ...props,
153
         ...props,
134
         appearance: NOTIFICATION_TYPE.WARNING
154
         appearance: NOTIFICATION_TYPE.WARNING
135
-    }, timeout);
155
+    }, type);
136
 }
156
 }
137
 
157
 
138
 /**
158
 /**
192
 
212
 
193
     if (notificationProps) {
213
     if (notificationProps) {
194
         dispatch(
214
         dispatch(
195
-            showNotification(notificationProps, NOTIFICATION_TIMEOUT));
215
+            showNotification(notificationProps, NOTIFICATION_TIMEOUT_TYPE.SHORT));
196
     }
216
     }
197
 
217
 
198
     joinedParticipantsNames = [];
218
     joinedParticipantsNames = [];

+ 4
- 13
react/features/notifications/components/web/NotificationsContainer.js Просмотреть файл

13
 
13
 
14
 import Notification from './Notification';
14
 import Notification from './Notification';
15
 
15
 
16
-declare var interfaceConfig: Object;
17
-
18
 type Props = {
16
 type Props = {
19
 
17
 
20
     /**
18
     /**
33
      */
31
      */
34
     _notifications: Array<Object>,
32
     _notifications: Array<Object>,
35
 
33
 
36
-    /**
37
-     * The length, in milliseconds, to use as a default timeout for all
38
-     * dismissible timeouts that do not have a timeout specified.
39
-     */
40
-    autoDismissTimeout: number,
41
-
42
     /**
34
     /**
43
      * JSS classes object.
35
      * JSS classes object.
44
      */
36
      */
260
      * @returns {void}
252
      * @returns {void}
261
      */
253
      */
262
     _updateTimeouts() {
254
     _updateTimeouts() {
263
-        const { _notifications, autoDismissTimeout } = this.props;
255
+        const { _notifications } = this.props;
264
 
256
 
265
         for (const notification of _notifications) {
257
         for (const notification of _notifications) {
266
-            if ((notification.timeout || typeof autoDismissTimeout === 'number')
258
+            if (notification.timeout
267
                     && notification.props.isDismissAllowed !== false
259
                     && notification.props.isDismissAllowed !== false
268
                     && !this._timeouts.has(notification.uid)) {
260
                     && !this._timeouts.has(notification.uid)) {
269
                 const {
261
                 const {
270
-                    timeout = autoDismissTimeout,
262
+                    timeout,
271
                     uid
263
                     uid
272
                 } = notification;
264
                 } = notification;
273
                 const timerID = setTimeout(() => {
265
                 const timerID = setTimeout(() => {
296
     return {
288
     return {
297
         _iAmSipGateway: Boolean(iAmSipGateway),
289
         _iAmSipGateway: Boolean(iAmSipGateway),
298
         _isChatOpen: isChatOpen,
290
         _isChatOpen: isChatOpen,
299
-        _notifications: _visible ? notifications : [],
300
-        autoDismissTimeout: interfaceConfig.ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT
291
+        _notifications: _visible ? notifications : []
301
     };
292
     };
302
 }
293
 }
303
 
294
 

+ 16
- 1
react/features/notifications/constants.js Просмотреть файл

3
 /**
3
 /**
4
  * The standard time when auto-disappearing notifications should disappear.
4
  * The standard time when auto-disappearing notifications should disappear.
5
  */
5
  */
6
-export const NOTIFICATION_TIMEOUT = 2500;
6
+export const NOTIFICATION_TIMEOUT = {
7
+    SHORT: 2500,
8
+    MEDIUM: 5000,
9
+    LONG: 10000,
10
+    STICKY: false
11
+};
12
+
13
+/**
14
+ * Notification timeout type.
15
+ */
16
+export const NOTIFICATION_TIMEOUT_TYPE = {
17
+    SHORT: 'short',
18
+    MEDIUM: 'medium',
19
+    LONG: 'long',
20
+    STICKY: 'sticky'
21
+};
7
 
22
 
8
 /**
23
 /**
9
  * The set of possible notification types.
24
  * The set of possible notification types.

+ 4
- 7
react/features/notifications/middleware.js Просмотреть файл

19
     showNotification,
19
     showNotification,
20
     showParticipantJoinedNotification
20
     showParticipantJoinedNotification
21
 } from './actions';
21
 } from './actions';
22
-import { NOTIFICATION_TIMEOUT } from './constants';
22
+import { NOTIFICATION_TIMEOUT_TYPE } from './constants';
23
 import { joinLeaveNotificationsDisabled } from './functions';
23
 import { joinLeaveNotificationsDisabled } from './functions';
24
 
24
 
25
 declare var interfaceConfig: Object;
25
 declare var interfaceConfig: Object;
54
                 action.participant.id
54
                 action.participant.id
55
             );
55
             );
56
 
56
 
57
-            if (typeof interfaceConfig === 'object'
58
-                && participant
59
-                && !participant.local
60
-                && !action.participant.isReplaced) {
57
+            if (participant && !participant.local && !action.participant.isReplaced) {
61
                 store.dispatch(showNotification({
58
                 store.dispatch(showNotification({
62
                     descriptionKey: 'notify.disconnected',
59
                     descriptionKey: 'notify.disconnected',
63
                     titleKey: 'notify.somebody',
60
                     titleKey: 'notify.somebody',
64
                     title: participant.name
61
                     title: participant.name
65
-                }, NOTIFICATION_TIMEOUT));
62
+                }, NOTIFICATION_TIMEOUT_TYPE.SHORT));
66
             }
63
             }
67
         }
64
         }
68
 
65
 
91
             store.dispatch(showNotification({
88
             store.dispatch(showNotification({
92
                 titleKey: 'notify.moderator'
89
                 titleKey: 'notify.moderator'
93
             },
90
             },
94
-            NOTIFICATION_TIMEOUT));
91
+            NOTIFICATION_TIMEOUT_TYPE.SHORT));
95
         }
92
         }
96
 
93
 
97
         return next(action);
94
         return next(action);

+ 2
- 2
react/features/old-client-notification/middleware.js Просмотреть файл

4
 
4
 
5
 import { APP_WILL_MOUNT } from '../base/app';
5
 import { APP_WILL_MOUNT } from '../base/app';
6
 import { MiddlewareRegistry } from '../base/redux';
6
 import { MiddlewareRegistry } from '../base/redux';
7
-import { showErrorNotification } from '../notifications';
7
+import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification } from '../notifications';
8
 
8
 
9
 import { OldElectronAPPNotificationDescription } from './components';
9
 import { OldElectronAPPNotificationDescription } from './components';
10
 import { isOldJitsiMeetElectronApp } from './functions';
10
 import { isOldJitsiMeetElectronApp } from './functions';
36
         dispatch(showErrorNotification({
36
         dispatch(showErrorNotification({
37
             titleKey: 'notify.OldElectronAPPTitle',
37
             titleKey: 'notify.OldElectronAPPTitle',
38
             description: <OldElectronAPPNotificationDescription />
38
             description: <OldElectronAPPNotificationDescription />
39
-        }));
39
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
40
     }
40
     }
41
 
41
 
42
     return next(action);
42
     return next(action);

+ 2
- 2
react/features/polls/subscriber.js Просмотреть файл

4
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
4
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
5
 import { StateListenerRegistry } from '../base/redux';
5
 import { StateListenerRegistry } from '../base/redux';
6
 import {
6
 import {
7
-    NOTIFICATION_TIMEOUT,
7
+    NOTIFICATION_TIMEOUT_TYPE,
8
     NOTIFICATION_TYPE,
8
     NOTIFICATION_TYPE,
9
     showNotification
9
     showNotification
10
 } from '../notifications';
10
 } from '../notifications';
83
                         appearance: NOTIFICATION_TYPE.NORMAL,
83
                         appearance: NOTIFICATION_TYPE.NORMAL,
84
                         titleKey: 'polls.notification.title',
84
                         titleKey: 'polls.notification.title',
85
                         descriptionKey: 'polls.notification.description'
85
                         descriptionKey: 'polls.notification.description'
86
-                    }, NOTIFICATION_TIMEOUT));
86
+                    }, NOTIFICATION_TIMEOUT_TYPE.SHORT));
87
                     break;
87
                     break;
88
 
88
 
89
                 }
89
                 }

+ 5
- 5
react/features/prejoin/actions.js Просмотреть файл

19
 } from '../base/tracks';
19
 } from '../base/tracks';
20
 import { openURLInBrowser } from '../base/util';
20
 import { openURLInBrowser } from '../base/util';
21
 import { executeDialOutRequest, executeDialOutStatusRequest, getDialInfoPageURL } from '../invite/functions';
21
 import { executeDialOutRequest, executeDialOutStatusRequest, getDialInfoPageURL } from '../invite/functions';
22
-import { showErrorNotification } from '../notifications';
22
+import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification } from '../notifications';
23
 
23
 
24
 import {
24
 import {
25
     PREJOIN_JOINING_IN_PROGRESS,
25
     PREJOIN_JOINING_IN_PROGRESS,
114
             case DIAL_OUT_STATUS.DISCONNECTED: {
114
             case DIAL_OUT_STATUS.DISCONNECTED: {
115
                 dispatch(showErrorNotification({
115
                 dispatch(showErrorNotification({
116
                     titleKey: 'prejoin.errorDialOutDisconnected'
116
                     titleKey: 'prejoin.errorDialOutDisconnected'
117
-                }));
117
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
118
 
118
 
119
                 return onFail();
119
                 return onFail();
120
             }
120
             }
122
             case DIAL_OUT_STATUS.FAILED: {
122
             case DIAL_OUT_STATUS.FAILED: {
123
                 dispatch(showErrorNotification({
123
                 dispatch(showErrorNotification({
124
                     titleKey: 'prejoin.errorDialOutFailed'
124
                     titleKey: 'prejoin.errorDialOutFailed'
125
-                }));
125
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
126
 
126
 
127
                 return onFail();
127
                 return onFail();
128
             }
128
             }
130
         } catch (err) {
130
         } catch (err) {
131
             dispatch(showErrorNotification({
131
             dispatch(showErrorNotification({
132
                 titleKey: 'prejoin.errorDialOutStatus'
132
                 titleKey: 'prejoin.errorDialOutStatus'
133
-            }));
133
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
134
             logger.error('Error getting dial out status', err);
134
             logger.error('Error getting dial out status', err);
135
             onFail();
135
             onFail();
136
         }
136
         }
183
                 }
183
                 }
184
             }
184
             }
185
 
185
 
186
-            dispatch(showErrorNotification(notification));
186
+            dispatch(showErrorNotification(notification, NOTIFICATION_TIMEOUT_TYPE.LONG));
187
             logger.error('Error dialing out', err);
187
             logger.error('Error dialing out', err);
188
             onFail();
188
             onFail();
189
         }
189
         }

+ 2
- 2
react/features/reactions/middleware.js Просмотреть файл

9
 import { SETTINGS_UPDATED, updateSettings } from '../base/settings';
9
 import { SETTINGS_UPDATED, updateSettings } from '../base/settings';
10
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
10
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
11
 import { getDisabledSounds } from '../base/sounds/functions.any';
11
 import { getDisabledSounds } from '../base/sounds/functions.any';
12
-import { NOTIFICATION_TIMEOUT, showNotification } from '../notifications';
12
+import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
13
 
13
 
14
 import {
14
 import {
15
     ADD_REACTION_BUFFER,
15
     ADD_REACTION_BUFFER,
169
             customActionHandler: () => dispatch(updateSettings({
169
             customActionHandler: () => dispatch(updateSettings({
170
                 soundsReactions: false
170
                 soundsReactions: false
171
             }))
171
             }))
172
-        }, NOTIFICATION_TIMEOUT));
172
+        }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
173
         break;
173
         break;
174
     }
174
     }
175
     }
175
     }

+ 6
- 6
react/features/recording/actions.any.js Просмотреть файл

6
 import { copyText } from '../base/util/helpers';
6
 import { copyText } from '../base/util/helpers';
7
 import { getVpaasTenant, isVpaasMeeting } from '../jaas/functions';
7
 import { getVpaasTenant, isVpaasMeeting } from '../jaas/functions';
8
 import {
8
 import {
9
-    NOTIFICATION_TIMEOUT,
9
+    NOTIFICATION_TIMEOUT_TYPE,
10
     hideNotification,
10
     hideNotification,
11
     showErrorNotification,
11
     showErrorNotification,
12
     showNotification,
12
     showNotification,
98
         const notification = await dispatch(showNotification({
98
         const notification = await dispatch(showNotification({
99
             isDismissAllowed: false,
99
             isDismissAllowed: false,
100
             ...dialogProps
100
             ...dialogProps
101
-        }));
101
+        }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
102
 
102
 
103
         if (notification) {
103
         if (notification) {
104
             dispatch(_setPendingRecordingNotificationUid(notification.uid, streamType));
104
             dispatch(_setPendingRecordingNotificationUid(notification.uid, streamType));
113
  * @returns {showErrorNotification}
113
  * @returns {showErrorNotification}
114
  */
114
  */
115
 export function showRecordingError(props: Object) {
115
 export function showRecordingError(props: Object) {
116
-    return showErrorNotification(props);
116
+    return showErrorNotification(props, NOTIFICATION_TIMEOUT_TYPE.LONG);
117
 }
117
 }
118
 
118
 
119
 /**
119
 /**
149
         titleKey: 'dialog.recording'
149
         titleKey: 'dialog.recording'
150
     };
150
     };
151
 
151
 
152
-    return showNotification(dialogProps, NOTIFICATION_TIMEOUT);
152
+    return showNotification(dialogProps, NOTIFICATION_TIMEOUT_TYPE.SHORT);
153
 }
153
 }
154
 
154
 
155
 /**
155
 /**
214
                 } catch (err) {
214
                 } catch (err) {
215
                     dispatch(showErrorNotification({
215
                     dispatch(showErrorNotification({
216
                         titleKey: 'recording.errorFetchingLink'
216
                         titleKey: 'recording.errorFetchingLink'
217
-                    }));
217
+                    }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
218
 
218
 
219
                     return logger.error('Could not fetch recording link', err);
219
                     return logger.error('Could not fetch recording link', err);
220
                 }
220
                 }
221
             }
221
             }
222
         }
222
         }
223
 
223
 
224
-        dispatch(showNotification(dialogProps, NOTIFICATION_TIMEOUT));
224
+        dispatch(showNotification(dialogProps, NOTIFICATION_TIMEOUT_TYPE.SHORT));
225
     };
225
     };
226
 }
226
 }
227
 
227
 

+ 2
- 2
react/features/recording/actions.native.js Просмотреть файл

1
 // @flow
1
 // @flow
2
 
2
 
3
 import JitsiMeetJS from '../base/lib-jitsi-meet';
3
 import JitsiMeetJS from '../base/lib-jitsi-meet';
4
-import { showNotification } from '../notifications';
4
+import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
5
 
5
 
6
 export * from './actions.any';
6
 export * from './actions.any';
7
 
7
 
37
             descriptionKey,
37
             descriptionKey,
38
             titleKey,
38
             titleKey,
39
             maxLines: 2
39
             maxLines: 2
40
-        }, 10000));
40
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
41
     };
41
     };
42
 }
42
 }

+ 2
- 2
react/features/recording/actions.web.js Просмотреть файл

3
 import React from 'react';
3
 import React from 'react';
4
 
4
 
5
 import JitsiMeetJS from '../base/lib-jitsi-meet';
5
 import JitsiMeetJS from '../base/lib-jitsi-meet';
6
-import { showNotification } from '../notifications';
6
+import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
7
 
7
 
8
 import { RecordingLimitNotificationDescription } from './components';
8
 import { RecordingLimitNotificationDescription } from './components';
9
 
9
 
23
     return showNotification({
23
     return showNotification({
24
         description: <RecordingLimitNotificationDescription isLiveStreaming = { isLiveStreaming } />,
24
         description: <RecordingLimitNotificationDescription isLiveStreaming = { isLiveStreaming } />,
25
         titleKey: isLiveStreaming ? 'dialog.liveStreaming' : 'dialog.recording'
25
         titleKey: isLiveStreaming ? 'dialog.liveStreaming' : 'dialog.recording'
26
-    }, 10000);
26
+    }, NOTIFICATION_TIMEOUT_TYPE.LONG);
27
 }
27
 }

+ 2
- 2
react/features/recording/components/Recording/AbstractStartRecordingDialog.js Просмотреть файл

13
     getNewAccessToken,
13
     getNewAccessToken,
14
     updateDropboxToken
14
     updateDropboxToken
15
 } from '../../../dropbox';
15
 } from '../../../dropbox';
16
-import { showErrorNotification } from '../../../notifications';
16
+import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification } from '../../../notifications';
17
 import { toggleRequestingSubtitles } from '../../../subtitles';
17
 import { toggleRequestingSubtitles } from '../../../subtitles';
18
 import { setSelectedRecordingService } from '../../actions';
18
 import { setSelectedRecordingService } from '../../actions';
19
 import { RECORDING_TYPES } from '../../constants';
19
 import { RECORDING_TYPES } from '../../constants';
298
             } else {
298
             } else {
299
                 dispatch(showErrorNotification({
299
                 dispatch(showErrorNotification({
300
                     titleKey: 'dialog.noDropboxToken'
300
                     titleKey: 'dialog.noDropboxToken'
301
-                }));
301
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
302
 
302
 
303
                 return;
303
                 return;
304
             }
304
             }

+ 5
- 5
react/features/remote-control/actions.js Просмотреть файл

4
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
4
 import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
5
 import { getParticipantDisplayName, getPinnedParticipant, pinParticipant } from '../base/participants';
5
 import { getParticipantDisplayName, getPinnedParticipant, pinParticipant } from '../base/participants';
6
 import { getLocalVideoTrack } from '../base/tracks';
6
 import { getLocalVideoTrack } from '../base/tracks';
7
-import { showNotification } from '../notifications';
7
+import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
8
 
8
 
9
 import {
9
 import {
10
     CAPTURE_EVENTS,
10
     CAPTURE_EVENTS,
190
                 descriptionArguments: { user: getParticipantDisplayName(state, participantId) },
190
                 descriptionArguments: { user: getParticipantDisplayName(state, participantId) },
191
                 descriptionKey,
191
                 descriptionKey,
192
                 titleKey: 'dialog.remoteControlTitle'
192
                 titleKey: 'dialog.remoteControlTitle'
193
-            }));
193
+            }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
194
 
194
 
195
             if (permissionGranted) {
195
             if (permissionGranted) {
196
                 // the remote control permissions has been granted
196
                 // the remote control permissions has been granted
269
         dispatch(showNotification({
269
         dispatch(showNotification({
270
             descriptionKey: 'dialog.remoteControlStopMessage',
270
             descriptionKey: 'dialog.remoteControlStopMessage',
271
             titleKey: 'dialog.remoteControlTitle'
271
             titleKey: 'dialog.remoteControlTitle'
272
-        }));
272
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
273
     };
273
     };
274
 }
274
 }
275
 
275
 
425
             dispatch(showNotification({
425
             dispatch(showNotification({
426
                 descriptionKey: 'dialog.remoteControlStopMessage',
426
                 descriptionKey: 'dialog.remoteControlStopMessage',
427
                 titleKey: 'dialog.remoteControlTitle'
427
                 titleKey: 'dialog.remoteControlTitle'
428
-            }));
428
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
429
         }
429
         }
430
     };
430
     };
431
 }
431
 }
564
                 dispatch(showNotification({
564
                 dispatch(showNotification({
565
                     descriptionKey: 'dialog.startRemoteControlErrorMessage',
565
                     descriptionKey: 'dialog.startRemoteControlErrorMessage',
566
                     titleKey: 'dialog.remoteControlTitle'
566
                     titleKey: 'dialog.remoteControlTitle'
567
-                }));
567
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
568
 
568
 
569
                 dispatch(stopReceiver(true));
569
                 dispatch(stopReceiver(true));
570
             });
570
             });

+ 3
- 3
react/features/room-lock/middleware.js Просмотреть файл

11
 import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
11
 import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
12
 import { MiddlewareRegistry } from '../base/redux';
12
 import { MiddlewareRegistry } from '../base/redux';
13
 import {
13
 import {
14
-    NOTIFICATION_TIMEOUT,
14
+    NOTIFICATION_TIMEOUT_TYPE,
15
     showNotification
15
     showNotification
16
 } from '../notifications';
16
 } from '../notifications';
17
 
17
 
54
             store.dispatch(
54
             store.dispatch(
55
                 showNotification({
55
                 showNotification({
56
                     titleKey: 'notify.passwordSetRemotely'
56
                     titleKey: 'notify.passwordSetRemotely'
57
-                }, NOTIFICATION_TIMEOUT));
57
+                }, NOTIFICATION_TIMEOUT_TYPE.SHORT));
58
         } else if (previousLockedState === LOCKED_REMOTELY && !currentLockedState) {
58
         } else if (previousLockedState === LOCKED_REMOTELY && !currentLockedState) {
59
             store.dispatch(
59
             store.dispatch(
60
                 showNotification({
60
                 showNotification({
61
                     titleKey: 'notify.passwordRemovedRemotely'
61
                     titleKey: 'notify.passwordRemovedRemotely'
62
-                }, NOTIFICATION_TIMEOUT));
62
+                }, NOTIFICATION_TIMEOUT_TYPE.SHORT));
63
         }
63
         }
64
 
64
 
65
         return result;
65
         return result;

+ 2
- 1
react/features/shared-video/components/web/AbstractVideoManager.js Просмотреть файл

9
 import { MEDIA_TYPE } from '../../../base/media';
9
 import { MEDIA_TYPE } from '../../../base/media';
10
 import { getLocalParticipant } from '../../../base/participants';
10
 import { getLocalParticipant } from '../../../base/participants';
11
 import { isLocalTrackMuted } from '../../../base/tracks';
11
 import { isLocalTrackMuted } from '../../../base/tracks';
12
+import { NOTIFICATION_TIMEOUT_TYPE } from '../../../notifications';
12
 import { showWarningNotification } from '../../../notifications/actions';
13
 import { showWarningNotification } from '../../../notifications/actions';
13
 import { dockToolbox } from '../../../toolbox/actions.web';
14
 import { dockToolbox } from '../../../toolbox/actions.web';
14
 import { muteLocal } from '../../../video-menu/actions.any';
15
 import { muteLocal } from '../../../video-menu/actions.any';
424
         _displayWarning: () => {
425
         _displayWarning: () => {
425
             dispatch(showWarningNotification({
426
             dispatch(showWarningNotification({
426
                 titleKey: 'dialog.shareVideoLinkError'
427
                 titleKey: 'dialog.shareVideoLinkError'
427
-            }));
428
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG));
428
         },
429
         },
429
         _dockToolbox: value => {
430
         _dockToolbox: value => {
430
             dispatch(dockToolbox(value));
431
             dispatch(dockToolbox(value));

+ 3
- 2
react/features/stream-effects/virtual-background/index.js Просмотреть файл

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications';
3
 import { showWarningNotification } from '../../notifications/actions';
4
 import { showWarningNotification } from '../../notifications/actions';
4
 import { timeout } from '../../virtual-background/functions';
5
 import { timeout } from '../../virtual-background/functions';
5
 import logger from '../../virtual-background/logger';
6
 import logger from '../../virtual-background/logger';
62
                 logger.error('Failed to download tflite model!');
63
                 logger.error('Failed to download tflite model!');
63
                 dispatch(showWarningNotification({
64
                 dispatch(showWarningNotification({
64
                     titleKey: 'virtualBackground.backgroundEffectError'
65
                     titleKey: 'virtualBackground.backgroundEffectError'
65
-                }));
66
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
66
             } else {
67
             } else {
67
                 logger.error('Looks like WebAssembly is disabled or not supported on this browser');
68
                 logger.error('Looks like WebAssembly is disabled or not supported on this browser');
68
                 dispatch(showWarningNotification({
69
                 dispatch(showWarningNotification({
69
                     titleKey: 'virtualBackground.webAssemblyWarning',
70
                     titleKey: 'virtualBackground.webAssemblyWarning',
70
                     description: 'WebAssembly disabled or not supported by this browser'
71
                     description: 'WebAssembly disabled or not supported by this browser'
71
-                }));
72
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
72
             }
73
             }
73
 
74
 
74
             return;
75
             return;

+ 2
- 1
react/features/talk-while-muted/middleware.js Просмотреть файл

8
 import { MiddlewareRegistry } from '../base/redux';
8
 import { MiddlewareRegistry } from '../base/redux';
9
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
9
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
10
 import {
10
 import {
11
+    NOTIFICATION_TIMEOUT_TYPE,
11
     hideNotification,
12
     hideNotification,
12
     showNotification
13
     showNotification
13
 } from '../notifications';
14
 } from '../notifications';
50
                     titleKey: 'toolbar.talkWhileMutedPopup',
51
                     titleKey: 'toolbar.talkWhileMutedPopup',
51
                     customActionNameKey: forceMuted ? 'notify.raiseHandAction' : 'notify.unmute',
52
                     customActionNameKey: forceMuted ? 'notify.raiseHandAction' : 'notify.unmute',
52
                     customActionHandler: () => dispatch(forceMuted ? raiseHand(true) : setAudioMuted(false))
53
                     customActionHandler: () => dispatch(forceMuted ? raiseHand(true) : setAudioMuted(false))
53
-                }));
54
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
54
 
55
 
55
                 const { soundsTalkWhileMuted } = getState()['features/base/settings'];
56
                 const { soundsTalkWhileMuted } = getState()['features/base/settings'];
56
 
57
 

+ 4
- 4
react/features/transcribing/actions.js Просмотреть файл

1
 // @flow
1
 // @flow
2
 
2
 
3
 import {
3
 import {
4
-    NOTIFICATION_TIMEOUT,
4
+    NOTIFICATION_TIMEOUT_TYPE,
5
     hideNotification,
5
     hideNotification,
6
     showErrorNotification,
6
     showErrorNotification,
7
     showNotification
7
     showNotification
74
             descriptionKey: 'transcribing.pending',
74
             descriptionKey: 'transcribing.pending',
75
             isDismissAllowed: false,
75
             isDismissAllowed: false,
76
             titleKey: 'dialog.transcribing'
76
             titleKey: 'dialog.transcribing'
77
-        }));
77
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG));
78
 
78
 
79
         if (notification) {
79
         if (notification) {
80
             dispatch(setPendingTranscribingNotificationUid(notification.uid));
80
             dispatch(setPendingTranscribingNotificationUid(notification.uid));
127
     return showNotification({
127
     return showNotification({
128
         descriptionKey: 'transcribing.off',
128
         descriptionKey: 'transcribing.off',
129
         titleKey: 'dialog.transcribing'
129
         titleKey: 'dialog.transcribing'
130
-    }, NOTIFICATION_TIMEOUT);
130
+    }, NOTIFICATION_TIMEOUT_TYPE.SHORT);
131
 }
131
 }
132
 
132
 
133
 
133
 
140
     return showErrorNotification({
140
     return showErrorNotification({
141
         descriptionKey: 'transcribing.error',
141
         descriptionKey: 'transcribing.error',
142
         titleKey: 'transcribing.failedToStart'
142
         titleKey: 'transcribing.failedToStart'
143
-    });
143
+    }, NOTIFICATION_TIMEOUT_TYPE.LONG);
144
 }
144
 }

+ 6
- 5
react/features/videosipgw/middleware.js Просмотреть файл

7
 } from '../base/lib-jitsi-meet';
7
 } from '../base/lib-jitsi-meet';
8
 import { MiddlewareRegistry } from '../base/redux';
8
 import { MiddlewareRegistry } from '../base/redux';
9
 import {
9
 import {
10
+    NOTIFICATION_TIMEOUT_TYPE,
10
     showErrorNotification,
11
     showErrorNotification,
11
     showNotification,
12
     showNotification,
12
     showWarningNotification
13
     showWarningNotification
103
                     dispatch(showErrorNotification({
104
                     dispatch(showErrorNotification({
104
                         descriptionKey: 'videoSIPGW.errorInvite',
105
                         descriptionKey: 'videoSIPGW.errorInvite',
105
                         titleKey: 'videoSIPGW.errorInviteTitle'
106
                         titleKey: 'videoSIPGW.errorInviteTitle'
106
-                    }));
107
+                    }, NOTIFICATION_TIMEOUT_TYPE.LONG));
107
 
108
 
108
                     return;
109
                     return;
109
                 }
110
                 }
111
                     dispatch(showWarningNotification({
112
                     dispatch(showWarningNotification({
112
                         titleKey: 'videoSIPGW.errorAlreadyInvited',
113
                         titleKey: 'videoSIPGW.errorAlreadyInvited',
113
                         titleArguments: { displayName }
114
                         titleArguments: { displayName }
114
-                    }));
115
+                    }, NOTIFICATION_TIMEOUT_TYPE.LONG));
115
 
116
 
116
                     return;
117
                     return;
117
                 }
118
                 }
148
             titleArguments: {
149
             titleArguments: {
149
                 displayName: event.displayName
150
                 displayName: event.displayName
150
             }
151
             }
151
-        }, 2000);
152
+        }, NOTIFICATION_TIMEOUT_TYPE.SHORT);
152
     }
153
     }
153
     case JitsiSIPVideoGWStatus.STATE_FAILED: {
154
     case JitsiSIPVideoGWStatus.STATE_FAILED: {
154
         return showErrorNotification({
155
         return showErrorNotification({
157
                 displayName: event.displayName
158
                 displayName: event.displayName
158
             },
159
             },
159
             descriptionKey: 'videoSIPGW.errorInviteFailed'
160
             descriptionKey: 'videoSIPGW.errorInviteFailed'
160
-        });
161
+        }, NOTIFICATION_TIMEOUT_TYPE.LONG);
161
     }
162
     }
162
     case JitsiSIPVideoGWStatus.STATE_OFF: {
163
     case JitsiSIPVideoGWStatus.STATE_OFF: {
163
         if (event.failureReason === JitsiSIPVideoGWStatus.STATUS_BUSY) {
164
         if (event.failureReason === JitsiSIPVideoGWStatus.STATUS_BUSY) {
164
             return showErrorNotification({
165
             return showErrorNotification({
165
                 descriptionKey: 'videoSIPGW.busy',
166
                 descriptionKey: 'videoSIPGW.busy',
166
                 titleKey: 'videoSIPGW.busyTitle'
167
                 titleKey: 'videoSIPGW.busyTitle'
167
-            });
168
+            }, NOTIFICATION_TIMEOUT_TYPE.LONG);
168
         } else if (event.failureReason) {
169
         } else if (event.failureReason) {
169
             logger.error(`Unknown sip videogw error ${event.newState} ${
170
             logger.error(`Unknown sip videogw error ${event.newState} ${
170
                 event.failureReason}`);
171
                 event.failureReason}`);

+ 2
- 2
react/features/virtual-background/components/VirtualBackgroundDialog.js Просмотреть файл

16
 import { updateSettings } from '../../base/settings';
16
 import { updateSettings } from '../../base/settings';
17
 import { Tooltip } from '../../base/tooltip';
17
 import { Tooltip } from '../../base/tooltip';
18
 import { getLocalVideoTrack } from '../../base/tracks';
18
 import { getLocalVideoTrack } from '../../base/tracks';
19
-import { showErrorNotification } from '../../notifications';
19
+import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification } from '../../notifications';
20
 import { toggleBackgroundEffect, virtualBackgroundTrackChanged } from '../actions';
20
 import { toggleBackgroundEffect, virtualBackgroundTrackChanged } from '../actions';
21
 import { IMAGES, BACKGROUNDS_LIMIT, VIRTUAL_BACKGROUND_TYPE, type Image } from '../constants';
21
 import { IMAGES, BACKGROUNDS_LIMIT, VIRTUAL_BACKGROUND_TYPE, type Image } from '../constants';
22
 import { toDataURL } from '../functions';
22
 import { toDataURL } from '../functions';
219
             if (!isCancelled) {
219
             if (!isCancelled) {
220
                 dispatch(showErrorNotification({
220
                 dispatch(showErrorNotification({
221
                     titleKey: 'virtualBackground.desktopShareError'
221
                     titleKey: 'virtualBackground.desktopShareError'
222
-                }));
222
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG));
223
                 logger.error('Could not create desktop share as a virtual background!');
223
                 logger.error('Could not create desktop share as a virtual background!');
224
             }
224
             }
225
 
225
 

+ 2
- 1
react/features/virtual-background/components/VirtualBackgroundPreview.js Просмотреть файл

10
 import { connect, equals } from '../../base/redux';
10
 import { connect, equals } from '../../base/redux';
11
 import { getCurrentCameraDeviceId } from '../../base/settings';
11
 import { getCurrentCameraDeviceId } from '../../base/settings';
12
 import { createLocalTracksF } from '../../base/tracks/functions';
12
 import { createLocalTracksF } from '../../base/tracks/functions';
13
+import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications';
13
 import { showWarningNotification } from '../../notifications/actions';
14
 import { showWarningNotification } from '../../notifications/actions';
14
 import { toggleBackgroundEffect } from '../actions';
15
 import { toggleBackgroundEffect } from '../actions';
15
 import { VIRTUAL_BACKGROUND_TYPE } from '../constants';
16
 import { VIRTUAL_BACKGROUND_TYPE } from '../constants';
140
                 showWarningNotification({
141
                 showWarningNotification({
141
                     titleKey: 'virtualBackground.backgroundEffectError',
142
                     titleKey: 'virtualBackground.backgroundEffectError',
142
                     description: 'Failed to access camera device.'
143
                     description: 'Failed to access camera device.'
143
-                })
144
+                }, NOTIFICATION_TIMEOUT_TYPE.LONG)
144
             );
145
             );
145
             logger.error('Failed to access camera device. Error on apply background effect.');
146
             logger.error('Failed to access camera device. Error on apply background effect.');
146
 
147
 

Загрузка…
Отмена
Сохранить