You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

reducer.js 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // @flow
  2. import { ReducerRegistry } from '../base/redux';
  3. import {
  4. CLEAR_NOTIFICATIONS,
  5. HIDE_NOTIFICATION,
  6. HIDE_RAISE_HAND_NOTIFICATIONS,
  7. SET_NOTIFICATIONS_ENABLED,
  8. SHOW_NOTIFICATION
  9. } from './actionTypes';
  10. import { NOTIFICATION_TYPE_PRIORITIES } from './constants';
  11. /**
  12. * The initial state of the feature notifications.
  13. *
  14. * @type {array}
  15. */
  16. const DEFAULT_STATE = {
  17. enabled: true,
  18. notifications: []
  19. };
  20. /**
  21. * Reduces redux actions which affect the display of notifications.
  22. *
  23. * @param {Object} state - The current redux state.
  24. * @param {Object} action - The redux action to reduce.
  25. * @returns {Object} The next redux state which is the result of reducing the
  26. * specified {@code action}.
  27. */
  28. ReducerRegistry.register('features/notifications',
  29. (state = DEFAULT_STATE, action) => {
  30. switch (action.type) {
  31. case CLEAR_NOTIFICATIONS:
  32. return {
  33. ...state,
  34. notifications: []
  35. };
  36. case HIDE_NOTIFICATION:
  37. return {
  38. ...state,
  39. notifications: state.notifications.filter(
  40. notification => notification.uid !== action.uid)
  41. };
  42. case HIDE_RAISE_HAND_NOTIFICATIONS:
  43. return {
  44. ...state,
  45. notifications: state.notifications.filter(
  46. notification => !notification.props.raiseHandNotification
  47. )
  48. };
  49. case SET_NOTIFICATIONS_ENABLED:
  50. return {
  51. ...state,
  52. enabled: action.enabled
  53. };
  54. case SHOW_NOTIFICATION:
  55. return {
  56. ...state,
  57. notifications:
  58. _insertNotificationByPriority(state.notifications, {
  59. component: action.component,
  60. props: action.props,
  61. timeout: action.timeout,
  62. uid: action.uid
  63. })
  64. };
  65. }
  66. return state;
  67. });
  68. /**
  69. * Creates a new notification queue with the passed in notification placed at
  70. * the end of other notifications with higher or the same priority.
  71. *
  72. * @param {Object[]} notifications - The queue of notifications to be displayed.
  73. * @param {Object} notification - The new notification to add to the queue.
  74. * @private
  75. * @returns {Object[]} A new array with an updated order of the notification
  76. * queue.
  77. */
  78. function _insertNotificationByPriority(notifications, notification) {
  79. const newNotificationPriority
  80. = NOTIFICATION_TYPE_PRIORITIES[notification.props.appearance] || 0;
  81. // Default to putting the new notification at the end of the queue.
  82. let insertAtLocation = notifications.length;
  83. // Find where to insert the new notification based on priority. Do not
  84. // insert at the front of the queue so that the user can finish acting on
  85. // any notification currently being read.
  86. for (let i = 1; i < notifications.length; i++) {
  87. const queuedNotification = notifications[i];
  88. const queuedNotificationPriority
  89. = NOTIFICATION_TYPE_PRIORITIES[queuedNotification.props.appearance]
  90. || 0;
  91. if (queuedNotificationPriority < newNotificationPriority) {
  92. insertAtLocation = i;
  93. break;
  94. }
  95. }
  96. // Create a copy to avoid mutation and insert the notification.
  97. const copyOfNotifications = notifications.slice();
  98. copyOfNotifications.splice(insertAtLocation, 0, notification);
  99. return copyOfNotifications;
  100. }