From 628dc927755aa415c3e1d9c076540b02f2a3bea7 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 8 Jul 2021 16:12:04 -0500 Subject: [PATCH] StatusLists: big refactor with OrderedSet --- app/soapbox/features/bookmarks/index.js | 2 +- .../features/favourited_statuses/index.js | 2 +- app/soapbox/features/pinned_statuses/index.js | 2 +- .../features/scheduled_statuses/index.js | 2 +- app/soapbox/reducers/status_lists.js | 78 +++++++++---------- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/app/soapbox/features/bookmarks/index.js b/app/soapbox/features/bookmarks/index.js index 2d1054913..1d726adb9 100644 --- a/app/soapbox/features/bookmarks/index.js +++ b/app/soapbox/features/bookmarks/index.js @@ -30,7 +30,7 @@ class Bookmarks extends ImmutablePureComponent { static propTypes = { dispatch: PropTypes.func.isRequired, shouldUpdateScroll: PropTypes.func, - statusIds: ImmutablePropTypes.list.isRequired, + statusIds: ImmutablePropTypes.orderedSet.isRequired, intl: PropTypes.object.isRequired, columnId: PropTypes.string, multiColumn: PropTypes.bool, diff --git a/app/soapbox/features/favourited_statuses/index.js b/app/soapbox/features/favourited_statuses/index.js index 58506c357..233acf640 100644 --- a/app/soapbox/features/favourited_statuses/index.js +++ b/app/soapbox/features/favourited_statuses/index.js @@ -28,7 +28,7 @@ class Favourites extends ImmutablePureComponent { static propTypes = { dispatch: PropTypes.func.isRequired, - statusIds: ImmutablePropTypes.list.isRequired, + statusIds: ImmutablePropTypes.orderedSet.isRequired, intl: PropTypes.object.isRequired, hasMore: PropTypes.bool, isLoading: PropTypes.bool, diff --git a/app/soapbox/features/pinned_statuses/index.js b/app/soapbox/features/pinned_statuses/index.js index 27758840c..ba0b10bf9 100644 --- a/app/soapbox/features/pinned_statuses/index.js +++ b/app/soapbox/features/pinned_statuses/index.js @@ -26,7 +26,7 @@ class PinnedStatuses extends ImmutablePureComponent { static propTypes = { dispatch: PropTypes.func.isRequired, - statusIds: ImmutablePropTypes.list.isRequired, + statusIds: ImmutablePropTypes.orderedSet.isRequired, intl: PropTypes.object.isRequired, hasMore: PropTypes.bool.isRequired, isMyAccount: PropTypes.bool.isRequired, diff --git a/app/soapbox/features/scheduled_statuses/index.js b/app/soapbox/features/scheduled_statuses/index.js index ea6816057..34d0887ad 100644 --- a/app/soapbox/features/scheduled_statuses/index.js +++ b/app/soapbox/features/scheduled_statuses/index.js @@ -30,7 +30,7 @@ class ScheduledStatuses extends ImmutablePureComponent { static propTypes = { dispatch: PropTypes.func.isRequired, - statusIds: ImmutablePropTypes.list.isRequired, + statusIds: ImmutablePropTypes.orderedSet.isRequired, intl: PropTypes.object.isRequired, hasMore: PropTypes.bool, isLoading: PropTypes.bool, diff --git a/app/soapbox/reducers/status_lists.js b/app/soapbox/reducers/status_lists.js index a9e5079b2..aec4dfc8d 100644 --- a/app/soapbox/reducers/status_lists.js +++ b/app/soapbox/reducers/status_lists.js @@ -17,7 +17,7 @@ import { import { PINNED_STATUSES_FETCH_SUCCESS, } from '../actions/pin_statuses'; -import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; import { FAVOURITE_SUCCESS, UNFAVOURITE_SUCCESS, @@ -37,76 +37,76 @@ import { SCHEDULED_STATUS_CANCEL_SUCCESS, } from '../actions/scheduled_statuses'; -const initialState = ImmutableMap({ - favourites: ImmutableMap({ - next: null, - loaded: false, - items: ImmutableList(), - }), - bookmarks: ImmutableMap({ - next: null, - loaded: false, - items: ImmutableList(), - }), - pins: ImmutableMap({ - next: null, - loaded: false, - items: ImmutableList(), - }), - scheduled_statuses: ImmutableMap({ - next: null, - loaded: false, - items: ImmutableList(), - }), +const initialMap = ImmutableMap({ + next: null, + loaded: false, + items: ImmutableOrderedSet(), }); +const initialState = ImmutableMap({ + favourites: initialMap, + bookmarks: initialMap, + pins: initialMap, + scheduled_statuses: initialMap, +}); + +const getStatusId = status => typeof status === 'string' ? status : status.get('id'); + +const getStatusIds = (statuses = []) => ( + ImmutableOrderedSet(statuses.map(status => status.id)) +); + +const setLoading = (state, listType, loading) => state.setIn([listType, 'isLoading'], loading); + const normalizeList = (state, listType, statuses, next) => { - return state.update(listType, listMap => listMap.withMutations(map => { + return state.update(listType, initialMap, listMap => listMap.withMutations(map => { map.set('next', next); map.set('loaded', true); map.set('isLoading', false); - map.set('items', ImmutableList(statuses.map(item => item.id))); + map.set('items', getStatusIds(statuses)); })); }; const appendToList = (state, listType, statuses, next) => { - return state.update(listType, listMap => listMap.withMutations(map => { + const newIds = getStatusIds(statuses); + + return state.update(listType, initialMap, listMap => listMap.withMutations(map => { map.set('next', next); map.set('isLoading', false); - map.set('items', map.get('items').concat(statuses.map(item => item.id))); + map.update('items', ImmutableOrderedSet(), items => items.union(newIds)); })); }; const prependOneToList = (state, listType, status) => { - return state.update(listType, listMap => listMap.withMutations(map => { - map.set('items', map.get('items').unshift(status.get('id'))); - })); + const statusId = getStatusId(status); + return state.updateIn([listType, 'items'], ImmutableOrderedSet(), items => { + return ImmutableOrderedSet([statusId]).union(items); + }); }; -const removeOneFromList = (state, listType, statusId) => { - return state.update(listType, listMap => listMap.withMutations(map => { - map.set('items', map.get('items').filter(item => item !== statusId)); - })); +const removeOneFromList = (state, listType, status) => { + const statusId = getStatusId(status); + return state.updateIn([listType, 'items'], ImmutableOrderedSet(), items => items.delete(statusId)); }; export default function statusLists(state = initialState, action) { switch(action.type) { case FAVOURITED_STATUSES_FETCH_REQUEST: case FAVOURITED_STATUSES_EXPAND_REQUEST: - return state.setIn(['favourites', 'isLoading'], true); + return setLoading(state, 'favourites', true); case FAVOURITED_STATUSES_FETCH_FAIL: case FAVOURITED_STATUSES_EXPAND_FAIL: - return state.setIn(['favourites', 'isLoading'], false); + return setLoading(state, 'favourites', false); case FAVOURITED_STATUSES_FETCH_SUCCESS: return normalizeList(state, 'favourites', action.statuses, action.next); case FAVOURITED_STATUSES_EXPAND_SUCCESS: return appendToList(state, 'favourites', action.statuses, action.next); case BOOKMARKED_STATUSES_FETCH_REQUEST: case BOOKMARKED_STATUSES_EXPAND_REQUEST: - return state.setIn(['bookmarks', 'isLoading'], true); + return setLoading(state, 'bookmarks', true); case BOOKMARKED_STATUSES_FETCH_FAIL: case BOOKMARKED_STATUSES_EXPAND_FAIL: - return state.setIn(['bookmarks', 'isLoading'], false); + return setLoading(state, 'bookmarks', false); case BOOKMARKED_STATUSES_FETCH_SUCCESS: return normalizeList(state, 'bookmarks', action.statuses, action.next); case BOOKMARKED_STATUSES_EXPAND_SUCCESS: @@ -127,10 +127,10 @@ export default function statusLists(state = initialState, action) { return removeOneFromList(state, 'pins', action.status); case SCHEDULED_STATUSES_FETCH_REQUEST: case SCHEDULED_STATUSES_EXPAND_REQUEST: - return state.setIn(['scheduled_statuses', 'isLoading'], true); + return setLoading(state, 'scheduled_statuses', true); case SCHEDULED_STATUSES_FETCH_FAIL: case SCHEDULED_STATUSES_EXPAND_FAIL: - return state.setIn(['scheduled_statuses', 'isLoading'], false); + return setLoading(state, 'scheduled_statuses', false); case SCHEDULED_STATUSES_FETCH_SUCCESS: return normalizeList(state, 'scheduled_statuses', action.statuses, action.next); case SCHEDULED_STATUSES_EXPAND_SUCCESS: