From f183094f828b8135ea34cb21d485e9d60ea00a39 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 23 Sep 2020 18:57:10 -0500 Subject: [PATCH] Refactor notifications again, this time with OrderedMap, fixes #433 --- app/soapbox/actions/notifications.js | 6 +- app/soapbox/features/notifications/index.js | 6 +- .../reducers/__tests__/notifications-test.js | 178 +++++++++--------- app/soapbox/reducers/notifications.js | 51 +++-- 4 files changed, 119 insertions(+), 122 deletions(-) diff --git a/app/soapbox/actions/notifications.js b/app/soapbox/actions/notifications.js index 96bdd09dc..1a1175700 100644 --- a/app/soapbox/actions/notifications.js +++ b/app/soapbox/actions/notifications.js @@ -13,7 +13,7 @@ import { defineMessages } from 'react-intl'; import { List as ImmutableList, Map as ImmutableMap, - OrderedSet as ImmutableOrderedSet, + OrderedMap as ImmutableOrderedMap, } from 'immutable'; import { unescapeHTML } from '../utils/html'; import { getFilters, regexFromFilters } from '../selectors'; @@ -125,7 +125,7 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale, export function dequeueNotifications() { return (dispatch, getState) => { - const queuedNotifications = getState().getIn(['notifications', 'queuedNotifications'], ImmutableOrderedSet()); + const queuedNotifications = getState().getIn(['notifications', 'queuedNotifications'], ImmutableOrderedMap()); const totalQueuedNotificationsCount = getState().getIn(['notifications', 'totalQueuedNotificationsCount'], 0); if (totalQueuedNotificationsCount === 0) { @@ -259,7 +259,7 @@ export function markReadNotifications() { const state = getState(); if (!state.get('me')) return; - const topNotification = state.getIn(['notifications', 'items'], ImmutableOrderedSet()).first(ImmutableMap()).get('id'); + const topNotification = state.getIn(['notifications', 'items'], ImmutableOrderedMap()).first(ImmutableMap()).get('id'); const lastRead = state.getIn(['notifications', 'lastRead']); if (!(topNotification && topNotification > lastRead)) return; diff --git a/app/soapbox/features/notifications/index.js b/app/soapbox/features/notifications/index.js index 89ccea75a..a62eea8b4 100644 --- a/app/soapbox/features/notifications/index.js +++ b/app/soapbox/features/notifications/index.js @@ -30,7 +30,7 @@ const getNotifications = createSelector([ state => getSettings(state).getIn(['notifications', 'quickFilter', 'show']), state => getSettings(state).getIn(['notifications', 'quickFilter', 'active']), state => ImmutableList(getSettings(state).getIn(['notifications', 'shows']).filter(item => !item).keys()), - state => state.getIn(['notifications', 'items']), + state => state.getIn(['notifications', 'items']).toList(), ], (showFilterBar, allowedType, excludedTypes, notifications) => { if (!showFilterBar || allowedType === 'all') { // used if user changed the notification settings after loading the notifications from the server @@ -55,7 +55,7 @@ export default @connect(mapStateToProps) class Notifications extends React.PureComponent { static propTypes = { - notifications: ImmutablePropTypes.orderedSet.isRequired, + notifications: ImmutablePropTypes.list.isRequired, showFilterBar: PropTypes.bool.isRequired, dispatch: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -142,8 +142,6 @@ class Notifications extends React.PureComponent { } else if (notifications.size > 0 || hasMore) { scrollableContent = notifications.map((item, index) => item === null ? ( 0 ? notifications.getIn([index - 1, 'id']) : null} diff --git a/app/soapbox/reducers/__tests__/notifications-test.js b/app/soapbox/reducers/__tests__/notifications-test.js index a2bfd3a53..d2d434c3d 100644 --- a/app/soapbox/reducers/__tests__/notifications-test.js +++ b/app/soapbox/reducers/__tests__/notifications-test.js @@ -1,7 +1,7 @@ import * as actions from 'soapbox/actions/notifications'; import reducer from '../notifications'; import notifications from 'soapbox/__fixtures__/notifications.json'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; +import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap } from 'immutable'; import { take } from 'lodash'; import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'soapbox/actions/accounts'; import notification from 'soapbox/__fixtures__/notification.json'; @@ -12,12 +12,12 @@ import { TIMELINE_DELETE } from 'soapbox/actions/timelines'; describe('notifications reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ - items: ImmutableOrderedSet(), + items: ImmutableOrderedMap(), hasMore: true, top: false, unread: 0, isLoading: false, - queuedNotifications: ImmutableOrderedSet(), + queuedNotifications: ImmutableOrderedMap(), totalQueuedNotificationsCount: 0, lastRead: -1, })); @@ -32,8 +32,8 @@ describe('notifications reducer', () => { skipLoading: true, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ id: '10744', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -42,8 +42,8 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), - ImmutableMap({ + })], + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -52,8 +52,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -62,13 +62,13 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), hasMore: false, top: false, unread: 1, isLoading: false, - queuedNotifications: ImmutableOrderedSet(), + queuedNotifications: ImmutableOrderedMap(), totalQueuedNotificationsCount: 0, lastRead: -1, })); @@ -100,8 +100,8 @@ describe('notifications reducer', () => { it('should handle NOTIFICATIONS_FILTER_SET', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ id: '10744', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -110,8 +110,8 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), - ImmutableMap({ + })], + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -120,8 +120,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -130,13 +130,13 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), hasMore: false, top: false, unread: 1, isLoading: false, - queuedNotifications: ImmutableOrderedSet(), + queuedNotifications: ImmutableOrderedMap(), totalQueuedNotificationsCount: 0, lastRead: -1, }); @@ -144,12 +144,12 @@ describe('notifications reducer', () => { type: actions.NOTIFICATIONS_FILTER_SET, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet(), + items: ImmutableOrderedMap(), hasMore: true, top: false, unread: 1, isLoading: false, - queuedNotifications: ImmutableOrderedSet(), + queuedNotifications: ImmutableOrderedMap(), totalQueuedNotificationsCount: 0, lastRead: -1, })); @@ -185,7 +185,7 @@ describe('notifications reducer', () => { it('should handle NOTIFICATIONS_UPDATE, when top = false, increment unread', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet(), + items: ImmutableOrderedMap(), top: false, unread: 1, }); @@ -194,8 +194,8 @@ describe('notifications reducer', () => { notification: notification, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -204,7 +204,7 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), top: false, unread: 2, @@ -213,8 +213,8 @@ describe('notifications reducer', () => { it('should handle NOTIFICATIONS_UPDATE_QUEUE', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([]), - queuedNotifications: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), + queuedNotifications: ImmutableOrderedMap(), totalQueuedNotificationsCount: 0, }); const action = { @@ -224,19 +224,19 @@ describe('notifications reducer', () => { intlLocale: 'en', }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([]), - queuedNotifications: ImmutableOrderedSet([{ + items: ImmutableOrderedMap(), + queuedNotifications: ImmutableOrderedMap([[notification.id, { notification: notification, intlMessages: intlMessages, intlLocale: 'en', - }]), + }]]), totalQueuedNotificationsCount: 1, })); }); it('should handle NOTIFICATIONS_DEQUEUE', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), queuedNotifications: take(notifications, 1), totalQueuedNotificationsCount: 1, }); @@ -244,16 +244,16 @@ describe('notifications reducer', () => { type: actions.NOTIFICATIONS_DEQUEUE, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([]), - queuedNotifications: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), + queuedNotifications: ImmutableOrderedMap(), totalQueuedNotificationsCount: 0, })); }); it('should handle NOTIFICATIONS_EXPAND_SUCCESS with non-empty items and next set true', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10734', ImmutableMap({ id: '10734', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -262,7 +262,7 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), + })], ]), unread: 1, hasMore: true, @@ -274,8 +274,8 @@ describe('notifications reducer', () => { next: true, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ id: '10744', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -284,8 +284,8 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), - ImmutableMap({ + })], + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -294,8 +294,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -304,8 +304,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10734', ImmutableMap({ id: '10734', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -314,7 +314,7 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), + })], ]), unread: 1, hasMore: true, @@ -324,7 +324,7 @@ describe('notifications reducer', () => { it('should handle NOTIFICATIONS_EXPAND_SUCCESS with empty items and next set true', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), unread: 1, hasMore: true, isLoading: false, @@ -335,8 +335,8 @@ describe('notifications reducer', () => { next: true, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ id: '10744', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -345,8 +345,8 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), - ImmutableMap({ + })], + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -355,8 +355,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -365,7 +365,7 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), unread: 1, hasMore: true, @@ -375,8 +375,8 @@ describe('notifications reducer', () => { it('should handle ACCOUNT_BLOCK_SUCCESS', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ id: '10744', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -385,8 +385,8 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), - ImmutableMap({ + })], + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -395,8 +395,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -405,7 +405,7 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), }); const action = { @@ -413,8 +413,8 @@ describe('notifications reducer', () => { relationship: relationship, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -423,8 +423,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -433,15 +433,15 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), })); }); it('should handle ACCOUNT_MUTE_SUCCESS', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ id: '10744', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -450,8 +450,8 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), - ImmutableMap({ + })], + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -460,8 +460,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -470,7 +470,7 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), }); const action = { @@ -478,8 +478,8 @@ describe('notifications reducer', () => { relationship: relationship, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -488,8 +488,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -498,43 +498,43 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), })); }); it('should handle NOTIFICATIONS_CLEAR', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), hasMore: true, }); const action = { type: actions.NOTIFICATIONS_CLEAR, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), hasMore: false, })); }); it('should handle NOTIFICATIONS_MARK_READ_REQUEST', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), }); const action = { type: actions.NOTIFICATIONS_MARK_READ_REQUEST, lastRead: 35098814, }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), lastRead: 35098814, })); }); it('should handle TIMELINE_DELETE', () => { const state = ImmutableMap({ - items: ImmutableOrderedSet([ - ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ id: '10744', type: 'pleroma:emoji_reaction', account: '9vMAje101ngtjlMj7w', @@ -543,8 +543,8 @@ describe('notifications reducer', () => { emoji: '😢', chat_message: undefined, is_seen: false, - }), - ImmutableMap({ + })], + ['10743', ImmutableMap({ id: '10743', type: 'favourite', account: '9v5c6xSEgAi3Zu1Lv6', @@ -553,8 +553,8 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), - ImmutableMap({ + })], + ['10741', ImmutableMap({ id: '10741', type: 'favourite', account: '9v5cKMOPGqPcgfcWp6', @@ -563,7 +563,7 @@ describe('notifications reducer', () => { emoji: undefined, chat_message: undefined, is_seen: true, - }), + })], ]), }); const action = { @@ -571,7 +571,7 @@ describe('notifications reducer', () => { id: '9vvNxoo5EFbbnfdXQu', }; expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedSet([]), + items: ImmutableOrderedMap(), })); }); diff --git a/app/soapbox/reducers/notifications.js b/app/soapbox/reducers/notifications.js index c34edf210..7dbda2c64 100644 --- a/app/soapbox/reducers/notifications.js +++ b/app/soapbox/reducers/notifications.js @@ -16,16 +16,16 @@ import { ACCOUNT_MUTE_SUCCESS, } from '../actions/accounts'; import { TIMELINE_DELETE } from '../actions/timelines'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; +import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap } from 'immutable'; import { get } from 'lodash'; const initialState = ImmutableMap({ - items: ImmutableOrderedSet(), + items: ImmutableOrderedMap(), hasMore: true, top: false, unread: 0, isLoading: false, - queuedNotifications: ImmutableOrderedSet(), //max = MAX_QUEUED_NOTIFICATIONS + queuedNotifications: ImmutableOrderedMap(), //max = MAX_QUEUED_NOTIFICATIONS totalQueuedNotificationsCount: 0, //used for queuedItems overflow for MAX_QUEUED_NOTIFICATIONS+ lastRead: -1, }); @@ -56,26 +56,27 @@ const normalizeNotification = (state, notification) => { if (!top) state = state.update('unread', unread => unread + 1); - return state.update('items', list => { - if (top && list.size > 40) { - list = list.take(20); + return state.update('items', map => { + if (top && map.size > 40) { + map = map.take(20); } - return list.add(notificationToMap(notification)).sort(comparator); + return map.set(notification.id, notificationToMap(notification)).sort(comparator); }); }; const processRawNotifications = notifications => ( - ImmutableOrderedSet( + ImmutableOrderedMap( notifications .filter(isValid) - .map(notificationToMap))); + .map(n => [n.id, notificationToMap(n)]) + )); const expandNormalizedNotifications = (state, notifications, next) => { const items = processRawNotifications(notifications); return state.withMutations(mutable => { - mutable.update('items', list => list.union(items).sort(comparator)); + mutable.update('items', map => map.merge(items).sort(comparator)); if (!next) mutable.set('hasMore', false); mutable.set('isLoading', false); @@ -83,7 +84,7 @@ const expandNormalizedNotifications = (state, notifications, next) => { }; const filterNotifications = (state, relationship) => { - return state.update('items', list => list.filterNot(item => item !== null && item.get('account') === relationship.id)); + return state.update('items', map => map.filterNot(item => item !== null && item.get('account') === relationship.id)); }; const updateTop = (state, top) => { @@ -92,26 +93,22 @@ const updateTop = (state, top) => { }; const deleteByStatus = (state, statusId) => { - return state.update('items', list => list.filterNot(item => item !== null && item.get('status') === statusId)); + return state.update('items', map => map.filterNot(item => item !== null && item.get('status') === statusId)); }; const updateNotificationsQueue = (state, notification, intlMessages, intlLocale) => { - const queuedNotifications = state.getIn(['queuedNotifications'], ImmutableOrderedSet()); - const listedNotifications = state.getIn(['items'], ImmutableOrderedSet()); + const queuedNotifications = state.getIn(['queuedNotifications'], ImmutableOrderedMap()); + const listedNotifications = state.getIn(['items'], ImmutableOrderedMap()); const totalQueuedNotificationsCount = state.getIn(['totalQueuedNotificationsCount'], 0); - let alreadyExists = queuedNotifications.find(existingQueuedNotification => existingQueuedNotification.id === notification.id); - if (!alreadyExists) alreadyExists = listedNotifications.find(existingListedNotification => existingListedNotification.get('id') === notification.id); - - if (alreadyExists) { - return state; - } + const alreadyExists = queuedNotifications.has(notification.id) || listedNotifications.has(notification.id); + if (alreadyExists) return state; let newQueuedNotifications = queuedNotifications; return state.withMutations(mutable => { if (totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) { - mutable.set('queuedNotifications', newQueuedNotifications.add({ + mutable.set('queuedNotifications', newQueuedNotifications.set(notification.id, { notification, intlMessages, intlLocale, @@ -121,6 +118,9 @@ const updateNotificationsQueue = (state, notification, intlMessages, intlLocale) }); }; +const countUnseen = notifications => notifications.reduce((acc, cur) => + get(cur, ['pleroma', 'is_seen'], false) === false ? acc + 1 : acc, 0); + export default function notifications(state = initialState, action) { switch(action.type) { case NOTIFICATIONS_EXPAND_REQUEST: @@ -128,7 +128,7 @@ export default function notifications(state = initialState, action) { case NOTIFICATIONS_EXPAND_FAIL: return state.set('isLoading', false); case NOTIFICATIONS_FILTER_SET: - return state.set('items', ImmutableOrderedSet()).set('hasMore', true); + return state.set('items', ImmutableOrderedMap()).set('hasMore', true); case NOTIFICATIONS_SCROLL_TOP: return updateTop(state, action.top); case NOTIFICATIONS_UPDATE: @@ -137,12 +137,11 @@ export default function notifications(state = initialState, action) { return updateNotificationsQueue(state, action.notification, action.intlMessages, action.intlLocale); case NOTIFICATIONS_DEQUEUE: return state.withMutations(mutable => { - mutable.set('queuedNotifications', ImmutableOrderedSet()); + mutable.set('queuedNotifications', ImmutableOrderedMap()); mutable.set('totalQueuedNotificationsCount', 0); }); case NOTIFICATIONS_EXPAND_SUCCESS: - const legacyUnread = action.notifications.reduce((acc, cur) => - get(cur, ['pleroma', 'is_seen'], false) === false ? acc + 1 : acc, 0); + const legacyUnread = countUnseen(action.notifications); return expandNormalizedNotifications(state, action.notifications, action.next) .merge({ unread: Math.max(legacyUnread, state.get('unread')) }); case ACCOUNT_BLOCK_SUCCESS: @@ -150,7 +149,7 @@ export default function notifications(state = initialState, action) { case ACCOUNT_MUTE_SUCCESS: return action.relationship.muting_notifications ? filterNotifications(state, action.relationship) : state; case NOTIFICATIONS_CLEAR: - return state.set('items', ImmutableOrderedSet()).set('hasMore', false); + return state.set('items', ImmutableOrderedMap()).set('hasMore', false); case NOTIFICATIONS_MARK_READ_REQUEST: return state.set('lastRead', action.lastRead); case TIMELINE_DELETE: