闭社主体 forked from https://github.com/tootsuite/mastodon
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.

119 lines
3.3 KiB

  1. import {
  2. NOTIFICATIONS_UPDATE,
  3. NOTIFICATIONS_REFRESH_SUCCESS,
  4. NOTIFICATIONS_EXPAND_SUCCESS,
  5. NOTIFICATIONS_REFRESH_REQUEST,
  6. NOTIFICATIONS_EXPAND_REQUEST,
  7. NOTIFICATIONS_REFRESH_FAIL,
  8. NOTIFICATIONS_EXPAND_FAIL,
  9. NOTIFICATIONS_CLEAR,
  10. NOTIFICATIONS_SCROLL_TOP,
  11. } from '../actions/notifications';
  12. import { ACCOUNT_BLOCK_SUCCESS } from '../actions/accounts';
  13. import { TIMELINE_DELETE } from '../actions/timelines';
  14. import Immutable from 'immutable';
  15. const initialState = Immutable.Map({
  16. items: Immutable.List(),
  17. next: null,
  18. top: true,
  19. unread: 0,
  20. loaded: false,
  21. isLoading: true,
  22. });
  23. const notificationToMap = notification => Immutable.Map({
  24. id: notification.id,
  25. type: notification.type,
  26. account: notification.account.id,
  27. status: notification.status ? notification.status.id : null,
  28. });
  29. const normalizeNotification = (state, notification) => {
  30. const top = state.get('top');
  31. if (!top) {
  32. state = state.update('unread', unread => unread + 1);
  33. }
  34. return state.update('items', list => {
  35. if (top && list.size > 40) {
  36. list = list.take(20);
  37. }
  38. return list.unshift(notificationToMap(notification));
  39. });
  40. };
  41. const normalizeNotifications = (state, notifications, next) => {
  42. let items = Immutable.List();
  43. const loaded = state.get('loaded');
  44. notifications.forEach((n, i) => {
  45. items = items.set(i, notificationToMap(n));
  46. });
  47. if (state.get('next') === null) {
  48. state = state.set('next', next);
  49. }
  50. return state
  51. .update('items', list => loaded ? items.concat(list) : list.concat(items))
  52. .set('loaded', true)
  53. .set('isLoading', false);
  54. };
  55. const appendNormalizedNotifications = (state, notifications, next) => {
  56. let items = Immutable.List();
  57. notifications.forEach((n, i) => {
  58. items = items.set(i, notificationToMap(n));
  59. });
  60. return state
  61. .update('items', list => list.concat(items))
  62. .set('next', next)
  63. .set('isLoading', false);
  64. };
  65. const filterNotifications = (state, relationship) => {
  66. return state.update('items', list => list.filterNot(item => item.get('account') === relationship.id));
  67. };
  68. const updateTop = (state, top) => {
  69. if (top) {
  70. state = state.set('unread', 0);
  71. }
  72. return state.set('top', top);
  73. };
  74. const deleteByStatus = (state, statusId) => {
  75. return state.update('items', list => list.filterNot(item => item.get('status') === statusId));
  76. };
  77. export default function notifications(state = initialState, action) {
  78. switch(action.type) {
  79. case NOTIFICATIONS_REFRESH_REQUEST:
  80. case NOTIFICATIONS_EXPAND_REQUEST:
  81. case NOTIFICATIONS_REFRESH_FAIL:
  82. case NOTIFICATIONS_EXPAND_FAIL:
  83. return state.set('isLoading', true);
  84. case NOTIFICATIONS_SCROLL_TOP:
  85. return updateTop(state, action.top);
  86. case NOTIFICATIONS_UPDATE:
  87. return normalizeNotification(state, action.notification);
  88. case NOTIFICATIONS_REFRESH_SUCCESS:
  89. return normalizeNotifications(state, action.notifications, action.next);
  90. case NOTIFICATIONS_EXPAND_SUCCESS:
  91. return appendNormalizedNotifications(state, action.notifications, action.next);
  92. case ACCOUNT_BLOCK_SUCCESS:
  93. return filterNotifications(state, action.relationship);
  94. case NOTIFICATIONS_CLEAR:
  95. return state.set('items', Immutable.List()).set('next', null);
  96. case TIMELINE_DELETE:
  97. return deleteByStatus(state, action.id);
  98. default:
  99. return state;
  100. }
  101. };