Browse Source

fix(notifications): throttle and batch join notifications (#2182)

* fix(notifications): throttle and batch join notifications

Instead of directly calling to show a join notification,
go through a specific method. This method will queue
names for display while a throttled function pulls
the names and shows a notification.

* squash: remove unused translation key

* squash: use default display name

* squash: move into participant actions
master
virtuacoplenny 8 years ago
parent
commit
fe411398e3

+ 3
- 1
lang/main.json View File

@@ -214,7 +214,9 @@
214 214
     "notify": {
215 215
         "disconnected": "disconnected",
216 216
         "moderator": "Moderator rights granted!",
217
-        "connected": "connected",
217
+        "connectedOneMember": "__name__ connected",
218
+        "connectedTwoMembers": "__first__ and __second__ connected",
219
+        "connectedThreePlusMembers": "__name__ and __count__ others connected",
218 220
         "somebody": "Somebody",
219 221
         "me": "Me",
220 222
         "focus": "Conference focus",

+ 5
- 3
modules/UI/UI.js View File

@@ -25,7 +25,10 @@ import {
25 25
 } from '../../react/features/device-selection';
26 26
 import { updateDeviceList } from '../../react/features/base/devices';
27 27
 import { JitsiTrackErrors } from '../../react/features/base/lib-jitsi-meet';
28
-import { getLocalParticipant } from '../../react/features/base/participants';
28
+import {
29
+    getLocalParticipant,
30
+    showParticipantJoinedNotification
31
+} from '../../react/features/base/participants';
29 32
 import { openDisplayNamePrompt } from '../../react/features/display-name';
30 33
 import {
31 34
     maybeShowNotificationWithDoNotDisplay,
@@ -473,8 +476,7 @@ UI.addUser = function(user) {
473 476
     const id = user.getId();
474 477
     const displayName = user.getDisplayName();
475 478
 
476
-    messageHandler.participantNotification(
477
-        displayName, 'notify.somebody', 'connected', 'notify.connected');
479
+    APP.store.dispatch(showParticipantJoinedNotification(displayName));
478 480
 
479 481
     if (!config.startAudioMuted
480 482
         || config.startAudioMuted > APP.conference.membersCount) {

+ 2
- 2
modules/UI/util/MessageHandler.js View File

@@ -362,7 +362,7 @@ const messageHandler = {
362 362
         $titleString.attr('data-i18n', titleKey);
363 363
 
364 364
         return $('<div>').append($titleString)
365
-.html();
365
+            .html();
366 366
     },
367 367
 
368 368
     /**
@@ -479,7 +479,7 @@ const messageHandler = {
479 479
      * @param displayName the display name of the participant that is
480 480
      * associated with the notification.
481 481
      * @param displayNameKey the key from the language file for the display
482
-     * name. Only used if displayName i not provided.
482
+     * name. Only used if displayName is not provided.
483 483
      * @param cls css class for the notification
484 484
      * @param messageKey the key from the language file for the text of the
485 485
      * message.

+ 82
- 0
react/features/base/participants/actions.js View File

@@ -1,3 +1,9 @@
1
+/* global interfaceConfig */
2
+
3
+import throttle from 'lodash/throttle';
4
+
5
+import { Notification, showNotification } from '../../notifications';
6
+
1 7
 import {
2 8
     DOMINANT_SPEAKER_CHANGED,
3 9
     KICK_PARTICIPANT,
@@ -318,3 +324,79 @@ export function pinParticipant(id) {
318 324
         }
319 325
     };
320 326
 }
327
+
328
+/**
329
+ * An array of names of participants that have joined the conference. The array
330
+ * is replaced with an empty array as notifications are displayed.
331
+ *
332
+ * @private
333
+ * @type {string[]}
334
+ */
335
+let joinedParticipantsNames = [];
336
+
337
+/**
338
+ * A throttled internal function that takes the internal list of participant
339
+ * names, {@code joinedParticipantsNames}, and triggers the display of a
340
+ * notification informing of their joining.
341
+ *
342
+ * @private
343
+ * @type {Function}
344
+ */
345
+const _throttledNotifyParticipantConnected = throttle(dispatch => {
346
+    const joinedParticipantsCount = joinedParticipantsNames.length;
347
+
348
+    let notificationProps;
349
+
350
+    if (joinedParticipantsCount >= 3) {
351
+        notificationProps = {
352
+            titleArguments: {
353
+                name: joinedParticipantsNames[0],
354
+                count: joinedParticipantsCount - 1
355
+            },
356
+            titleKey: 'notify.connectedThreePlusMembers'
357
+        };
358
+    } else if (joinedParticipantsCount === 2) {
359
+        notificationProps = {
360
+            titleArguments: {
361
+                first: joinedParticipantsNames[0],
362
+                second: joinedParticipantsNames[1]
363
+            },
364
+            titleKey: 'notify.connectedTwoMembers'
365
+        };
366
+    } else if (joinedParticipantsCount) {
367
+        notificationProps = {
368
+            titleArguments: {
369
+                name: joinedParticipantsNames[0]
370
+            },
371
+            titleKey: 'notify.connectedOneMember'
372
+        };
373
+    }
374
+
375
+    if (notificationProps) {
376
+        dispatch(
377
+            showNotification(
378
+                Notification,
379
+                notificationProps,
380
+                2500));
381
+    }
382
+
383
+    joinedParticipantsNames = [];
384
+
385
+}, 500, { leading: false });
386
+
387
+/**
388
+ * Queues the display of a notification of a participant having connected to
389
+ * the meeting. The notifications are batched so that quick consecutive
390
+ * connection events are shown in one notification.
391
+ *
392
+ * @param {string} displayName - The name of the participant that connected.
393
+ * @returns {Function}
394
+ */
395
+export function showParticipantJoinedNotification(displayName) {
396
+    joinedParticipantsNames.push(
397
+        displayName || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME);
398
+
399
+    return dispatch => {
400
+        _throttledNotifyParticipantConnected(dispatch);
401
+    };
402
+}

+ 10
- 4
react/features/notifications/components/Notification.web.js View File

@@ -104,6 +104,11 @@ class Notification extends Component<*> {
104 104
          */
105 105
         title: PropTypes.string,
106 106
 
107
+        /**
108
+         * The translation arguments that may be necessary for the title.
109
+         */
110
+        titleArguments: PropTypes.object,
111
+
107 112
         /**
108 113
          * The translation key to display as the title of the notification if
109 114
          * no title is provided.
@@ -138,16 +143,17 @@ class Notification extends Component<*> {
138 143
      */
139 144
     render() {
140 145
         const {
141
-            hideErrorSupportLink,
142 146
             appearance,
143
-            titleKey,
147
+            description,
144 148
             descriptionArguments,
145 149
             descriptionKey,
146
-            description,
150
+            hideErrorSupportLink,
147 151
             isDismissAllowed,
148 152
             onDismissed,
149 153
             t,
150 154
             title,
155
+            titleArguments,
156
+            titleKey,
151 157
             uid
152 158
         } = this.props;
153 159
 
@@ -161,7 +167,7 @@ class Notification extends Component<*> {
161 167
                 id = { uid }
162 168
                 isDismissAllowed = { isDismissAllowed }
163 169
                 onDismissed = { onDismissed }
164
-                title = { title || t(titleKey) } />
170
+                title = { title || t(titleKey, titleArguments) } />
165 171
         );
166 172
     }
167 173
 

Loading…
Cancel
Save