闭社主体 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.

104 lines
2.9 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 Immutable from 'immutable';
  14. const initialState = Immutable.Map({
  15. items: Immutable.List(),
  16. next: null,
  17. top: true,
  18. unread: 0,
  19. loaded: false,
  20. isLoading: true
  21. });
  22. const notificationToMap = notification => Immutable.Map({
  23. id: notification.id,
  24. type: notification.type,
  25. account: notification.account.id,
  26. status: notification.status ? notification.status.id : null
  27. });
  28. const normalizeNotification = (state, notification) => {
  29. if (!state.get('top')) {
  30. state = state.update('unread', unread => unread + 1);
  31. }
  32. return state.update('items', list => list.unshift(notificationToMap(notification)));
  33. };
  34. const normalizeNotifications = (state, notifications, next) => {
  35. let items = Immutable.List();
  36. const loaded = state.get('loaded');
  37. notifications.forEach((n, i) => {
  38. items = items.set(i, notificationToMap(n));
  39. });
  40. if (state.get('next') === null) {
  41. state = state.set('next', next);
  42. }
  43. return state
  44. .update('items', list => loaded ? list.unshift(...items) : list.push(...items))
  45. .set('loaded', true)
  46. .set('isLoading', false);
  47. };
  48. const appendNormalizedNotifications = (state, notifications, next) => {
  49. let items = Immutable.List();
  50. notifications.forEach((n, i) => {
  51. items = items.set(i, notificationToMap(n));
  52. });
  53. return state
  54. .update('items', list => list.push(...items))
  55. .set('next', next)
  56. .set('isLoading', false);
  57. };
  58. const filterNotifications = (state, relationship) => {
  59. return state.update('items', list => list.filterNot(item => item.get('account') === relationship.id));
  60. };
  61. const updateTop = (state, top) => {
  62. if (top) {
  63. state = state.set('unread', 0);
  64. }
  65. return state.set('top', top);
  66. };
  67. export default function notifications(state = initialState, action) {
  68. switch(action.type) {
  69. case NOTIFICATIONS_REFRESH_REQUEST:
  70. case NOTIFICATIONS_EXPAND_REQUEST:
  71. case NOTIFICATIONS_REFRESH_FAIL:
  72. case NOTIFICATIONS_EXPAND_FAIL:
  73. return state.set('isLoading', true);
  74. case NOTIFICATIONS_SCROLL_TOP:
  75. return updateTop(state, action.top);
  76. case NOTIFICATIONS_UPDATE:
  77. return normalizeNotification(state, action.notification);
  78. case NOTIFICATIONS_REFRESH_SUCCESS:
  79. return normalizeNotifications(state, action.notifications, action.next);
  80. case NOTIFICATIONS_EXPAND_SUCCESS:
  81. return appendNormalizedNotifications(state, action.notifications, action.next);
  82. case ACCOUNT_BLOCK_SUCCESS:
  83. return filterNotifications(state, action.relationship);
  84. case NOTIFICATIONS_CLEAR:
  85. return state.set('items', Immutable.List()).set('next', null);
  86. default:
  87. return state;
  88. }
  89. };