pl-fe: migrate status lists to mutative

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-11-10 12:11:09 +01:00
parent fad9714475
commit b2d5bbf537
16 changed files with 142 additions and 146 deletions

View file

@ -17,7 +17,7 @@ const noOp = () => new Promise(f => f(undefined));
const fetchBookmarkedStatuses = (folderId?: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (getState().status_lists.get(folderId ? `bookmarks:${folderId}` : 'bookmarks')?.isLoading) {
if (getState().status_lists[folderId ? `bookmarks:${folderId}` : 'bookmarks']?.isLoading) {
return dispatch(noOp);
}
@ -52,9 +52,9 @@ const fetchBookmarkedStatusesFail = (error: unknown, folderId?: string) => ({
const expandBookmarkedStatuses = (folderId?: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const list = folderId ? `bookmarks:${folderId}` : 'bookmarks';
const next = getState().status_lists.get(list)?.next || null;
const next = getState().status_lists[list]?.next || null;
if (next === null || getState().status_lists.get(list)?.isLoading) {
if (next === null || getState().status_lists[list]?.isLoading) {
return dispatch(noOp);
}

View file

@ -448,7 +448,7 @@ const initEventEdit = (statusId: string) => (dispatch: AppDispatch, getState: ()
const fetchRecentEvents = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (getState().status_lists.get('recent_events')?.isLoading) {
if (getState().status_lists.recent_events?.isLoading) {
return;
}
@ -470,7 +470,7 @@ const fetchRecentEvents = () =>
const fetchJoinedEvents = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (getState().status_lists.get('joined_events')?.isLoading) {
if (getState().status_lists.joined_events?.isLoading) {
return;
}

View file

@ -27,7 +27,7 @@ const fetchFavouritedStatuses = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
if (getState().status_lists.get('favourites')?.isLoading) {
if (getState().status_lists.favourites?.isLoading) {
return;
}
@ -60,9 +60,9 @@ const expandFavouritedStatuses = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
const next = getState().status_lists.get('favourites')?.next || null;
const next = getState().status_lists.favourites?.next || null;
if (next === null || getState().status_lists.get('favourites')?.isLoading) {
if (next === null || getState().status_lists.favourites?.isLoading) {
return;
}
@ -95,7 +95,7 @@ const fetchAccountFavouritedStatuses = (accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
if (getState().status_lists.get(`favourites:${accountId}`)?.isLoading) {
if (getState().status_lists[`favourites:${accountId}`]?.isLoading) {
return;
}
@ -131,9 +131,9 @@ const expandAccountFavouritedStatuses = (accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
const next = getState().status_lists.get(`favourites:${accountId}`)?.next || null;
const next = getState().status_lists[`favourites:${accountId}`]?.next || null;
if (next === null || getState().status_lists.get(`favourites:${accountId}`)?.isLoading) {
if (next === null || getState().status_lists[`favourites:${accountId}`]?.isLoading) {
return;
}

View file

@ -19,7 +19,7 @@ const fetchScheduledStatuses = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
if (state.status_lists.get('scheduled_statuses')?.isLoading) {
if (state.status_lists.scheduled_statuses?.isLoading) {
return;
}
@ -63,9 +63,9 @@ const fetchScheduledStatusesFail = (error: unknown) => ({
const expandScheduledStatuses = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
const next = getState().status_lists.get('scheduled_statuses')?.next as any as () => Promise<PaginatedResponse<ScheduledStatus>> || null;
const next = getState().status_lists.scheduled_statuses?.next as any as () => Promise<PaginatedResponse<ScheduledStatus>> || null;
if (next === null || getState().status_lists.get('scheduled_statuses')?.isLoading) {
if (next === null || getState().status_lists.scheduled_statuses?.isLoading) {
return;
}

View file

@ -35,7 +35,7 @@ interface FetchStatusQuotesFailAction {
const fetchStatusQuotes = (statusId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (getState().status_lists.getIn([`quotes:${statusId}`, 'isLoading'])) {
if (getState().status_lists[`quotes:${statusId}`]?.isLoading) {
return dispatch(noOp);
}
@ -78,9 +78,9 @@ interface ExpandStatusQuotesFailAction {
const expandStatusQuotes = (statusId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const next = getState().status_lists.get(`quotes:${statusId}`)?.next || null;
const next = getState().status_lists[`quotes:${statusId}`]?.next || null;
if (next === null || getState().status_lists.getIn([`quotes:${statusId}`, 'isLoading'])) {
if (next === null || getState().status_lists[`quotes:${statusId}`]?.isLoading) {
return dispatch(noOp);
}

View file

@ -1,5 +1,4 @@
import clsx from 'clsx';
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
import debounce from 'lodash/debounce';
import React, { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
@ -18,11 +17,11 @@ interface IStatusList extends Omit<IScrollableListWithContainer, 'onLoadMore' |
/** Unique key to preserve the scroll position when navigating back. */
scrollKey: string;
/** List of status IDs to display. */
statusIds: ImmutableOrderedSet<string>;
statusIds: Array<string>;
/** Last _unfiltered_ status ID (maxId) for pagination. */
lastStatusId?: string;
/** Pinned statuses to show at the top of the feed. */
featuredStatusIds?: ImmutableOrderedSet<string>;
featuredStatusIds?: Array<string>;
/** Pagination callback when the end of the list is reached. */
onLoadMore?: (lastStatusId: string) => void;
/** Whether the data is currently being fetched. */
@ -57,13 +56,13 @@ const StatusList: React.FC<IStatusList> = ({
}) => {
const plFeConfig = usePlFeConfig();
const getFeaturedStatusCount = () => featuredStatusIds?.size || 0;
const getFeaturedStatusCount = () => featuredStatusIds?.length || 0;
const getCurrentStatusIndex = (id: string, featured: boolean): number => {
if (featured) {
return featuredStatusIds?.keySeq().findIndex(key => key === id) || 0;
return featuredStatusIds?.findIndex(key => key === id) || 0;
} else {
return statusIds.keySeq().findIndex(key => key === id) + getFeaturedStatusCount();
return statusIds.findIndex(key => key === id) + getFeaturedStatusCount();
}
};
@ -78,11 +77,11 @@ const StatusList: React.FC<IStatusList> = ({
};
const handleLoadOlder = useCallback(debounce(() => {
const maxId = lastStatusId || statusIds.last();
const maxId = lastStatusId || statusIds.at(-1);
if (onLoadMore && maxId) {
onLoadMore(maxId.replace('末suggestions-', ''));
}
}, 300, { leading: true }), [onLoadMore, lastStatusId, statusIds.last()]);
}, 300, { leading: true }), [onLoadMore, lastStatusId, statusIds.at(-1)]);
const selectChild = (index: number) => {
const selector = `#status-list [data-index="${index}"] .focusable`;
@ -92,9 +91,9 @@ const StatusList: React.FC<IStatusList> = ({
};
const renderLoadGap = (index: number) => {
const ids = statusIds.toList();
const nextId = ids.get(index + 1);
const prevId = ids.get(index - 1);
const ids = statusIds;
const nextId = ids[index + 1];
const prevId = ids[index - 1];
if (index < 1 || !nextId || !prevId || !onLoadMore) return null;
@ -136,7 +135,7 @@ const StatusList: React.FC<IStatusList> = ({
const renderFeaturedStatuses = (): React.ReactNode[] => {
if (!featuredStatusIds) return [];
return featuredStatusIds.toArray().map(statusId => (
return featuredStatusIds.map(statusId => (
<StatusContainer
key={`f-${statusId}`}
id={statusId}
@ -160,8 +159,8 @@ const StatusList: React.FC<IStatusList> = ({
);
const renderStatuses = (): React.ReactNode[] => {
if (isLoading || statusIds.size > 0) {
return statusIds.toList().reduce((acc, statusId, index) => {
if (isLoading || statusIds.length > 0) {
return statusIds.reduce((acc, statusId, index) => {
if (statusId === null) {
const gap = renderLoadGap(index);
if (gap) {
@ -214,7 +213,7 @@ const StatusList: React.FC<IStatusList> = ({
id='status-list'
key='scrollable-list'
isLoading={isLoading}
showLoading={isLoading && statusIds.size === 0}
showLoading={isLoading && statusIds.length === 0}
onLoadMore={handleLoadOlder}
placeholderComponent={() => <PlaceholderStatus variant={divideType === 'border' ? 'slim' : 'rounded'} />}
placeholderCount={20}

View file

@ -1,4 +1,3 @@
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
import debounce from 'lodash/debounce';
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
@ -54,9 +53,9 @@ const Bookmarks: React.FC<IBookmarks> = ({ params }) => {
const bookmarksKey = folderId ? `bookmarks:${folderId}` : 'bookmarks';
const statusIds = useAppSelector((state) => state.status_lists.get(bookmarksKey)?.items || ImmutableOrderedSet<string>());
const isLoading = useAppSelector((state) => state.status_lists.get(bookmarksKey)?.isLoading === true);
const hasMore = useAppSelector((state) => !!state.status_lists.get(bookmarksKey)?.next);
const statusIds = useAppSelector((state) => state.status_lists[bookmarksKey]?.items || []);
const isLoading = useAppSelector((state) => state.status_lists[bookmarksKey]?.isLoading === true);
const hasMore = useAppSelector((state) => !!state.status_lists[bookmarksKey]?.next);
React.useEffect(() => {
dispatch(fetchBookmarkedStatuses(folderId));

View file

@ -10,8 +10,6 @@ import { makeGetStatus } from 'pl-fe/selectors';
import PlaceholderEventPreview from '../../placeholder/components/placeholder-event-preview';
import type { OrderedSet as ImmutableOrderedSet } from 'immutable';
const Event = ({ id }: { id: string }) => {
const getStatus = useCallback(makeGetStatus(), []);
const status = useAppSelector(state => getStatus(state, { id }));
@ -29,7 +27,7 @@ const Event = ({ id }: { id: string }) => {
};
interface IEventCarousel {
statusIds: ImmutableOrderedSet<string>;
statusIds: Array<string>;
isLoading?: boolean | null;
emptyMessage: React.ReactNode;
}
@ -38,10 +36,10 @@ const EventCarousel: React.FC<IEventCarousel> = ({ statusIds, isLoading, emptyMe
const [index, setIndex] = useState(0);
const handleChangeIndex = (index: number) => {
setIndex(index % statusIds.size);
setIndex(index % statusIds.length);
};
if (statusIds.size === 0) {
if (statusIds.length === 0) {
if (isLoading) {
return <PlaceholderEventPreview />;
}
@ -67,7 +65,7 @@ const EventCarousel: React.FC<IEventCarousel> = ({ statusIds, isLoading, emptyMe
<ReactSwipeableViews animateHeight index={index} onChangeIndex={handleChangeIndex}>
{statusIds.map(statusId => <Event key={statusId} id={statusId} />)}
</ReactSwipeableViews>
{index !== statusIds.size - 1 && (
{index !== statusIds.length - 1 && (
<div className='absolute right-3 top-1/2 z-10 -mt-4'>
<button
onClick={() => handleChangeIndex(index + 1)}

View file

@ -20,10 +20,10 @@ const Events = () => {
const dispatch = useAppDispatch();
const recentEvents = useAppSelector((state) => state.status_lists.get('recent_events')!.items);
const recentEventsLoading = useAppSelector((state) => state.status_lists.get('recent_events')!.isLoading);
const joinedEvents = useAppSelector((state) => state.status_lists.get('joined_events')!.items);
const joinedEventsLoading = useAppSelector((state) => state.status_lists.get('joined_events')!.isLoading);
const recentEvents = useAppSelector((state) => state.status_lists.recent_events!.items);
const recentEventsLoading = useAppSelector((state) => state.status_lists.recent_events!.isLoading);
const joinedEvents = useAppSelector((state) => state.status_lists.joined_events!.items);
const joinedEventsLoading = useAppSelector((state) => state.status_lists.joined_events!.isLoading);
useEffect(() => {
dispatch(fetchRecentEvents());

View file

@ -1,4 +1,3 @@
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
import debounce from 'lodash/debounce';
import React, { useCallback, useEffect } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
@ -34,9 +33,9 @@ const Favourites: React.FC<IFavourites> = ({ params }) => {
const isOwnAccount = username.toLowerCase() === ownAccount?.acct?.toLowerCase();
const timelineKey = isOwnAccount ? 'favourites' : `favourites:${account?.id}`;
const statusIds = useAppSelector(state => state.status_lists.get(timelineKey)?.items || ImmutableOrderedSet<string>());
const isLoading = useAppSelector(state => state.status_lists.get(timelineKey)?.isLoading === true);
const hasMore = useAppSelector(state => !!state.status_lists.get(timelineKey)?.next);
const statusIds = useAppSelector(state => state.status_lists[timelineKey]?.items || []);
const isLoading = useAppSelector(state => state.status_lists[timelineKey]?.isLoading === true);
const hasMore = useAppSelector(state => !!state.status_lists[timelineKey]?.next);
const handleLoadMore = useCallback(debounce(() => {
if (isOwnAccount) {

View file

@ -20,9 +20,9 @@ const PinnedStatuses = () => {
const { username } = useParams<{ username: string }>();
const meUsername = useAppSelector((state) => selectOwnAccount(state)?.username || '');
const statusIds = useAppSelector((state) => state.status_lists.get('pins')!.items);
const isLoading = useAppSelector((state) => !!state.status_lists.get('pins')!.isLoading);
const hasMore = useAppSelector((state) => !!state.status_lists.get('pins')!.next);
const statusIds = useAppSelector((state) => state.status_lists.pins!.items);
const isLoading = useAppSelector((state) => !!state.status_lists.pins!.isLoading);
const hasMore = useAppSelector((state) => !!state.status_lists.pins!.next);
const isMyAccount = username.toLowerCase() === meUsername.toLowerCase();

View file

@ -1,4 +1,3 @@
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
import debounce from 'lodash/debounce';
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
@ -26,9 +25,9 @@ const Quotes: React.FC = () => {
const theme = useTheme();
const isMobile = useIsMobile();
const statusIds = useAppSelector((state) => state.status_lists.getIn([`quotes:${statusId}`, 'items'], ImmutableOrderedSet<string>()));
const isLoading = useAppSelector((state) => state.status_lists.getIn([`quotes:${statusId}`, 'isLoading'], true));
const hasMore = useAppSelector((state) => !!state.status_lists.getIn([`quotes:${statusId}`, 'next']));
const statusIds = useAppSelector((state) => state.status_lists[`quotes:${statusId}`]?.items || []);
const isLoading = useAppSelector((state) => state.status_lists[`quotes:${statusId}`]?.isLoading !== false);
const hasMore = useAppSelector((state) => !!state.status_lists[`quotes:${statusId}`]?.next);
React.useEffect(() => {
dispatch(fetchStatusQuotes(statusId));
@ -41,7 +40,7 @@ const Quotes: React.FC = () => {
<StatusList
className='black:p-0 black:sm:p-4 black:sm:pt-0'
loadMoreClassName='black:sm:mx-4'
statusIds={statusIds as ImmutableOrderedSet<string>}
statusIds={statusIds}
scrollKey={`quotes:${statusId}`}
hasMore={hasMore}
isLoading={typeof isLoading === 'boolean' ? isLoading : true}

View file

@ -22,9 +22,9 @@ const ScheduledStatuses = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
const statusIds = useAppSelector((state) => state.status_lists.get('scheduled_statuses')!.items);
const isLoading = useAppSelector((state) => state.status_lists.get('scheduled_statuses')!.isLoading);
const hasMore = useAppSelector((state) => !!state.status_lists.get('scheduled_statuses')!.next);
const statusIds = useAppSelector((state) => state.status_lists.scheduled_statuses!.items);
const isLoading = useAppSelector((state) => state.status_lists.scheduled_statuses!.isLoading);
const hasMore = useAppSelector((state) => !!state.status_lists.scheduled_statuses!.next);
useEffect(() => {
dispatch(fetchScheduledStatuses());

View file

@ -34,7 +34,7 @@ const Timeline: React.FC<ITimeline> = ({
const getStatusIds = useCallback(makeGetStatusIds(), []);
const statusIds = useAppSelector(state => getStatusIds(state, { type: timelineId, prefix }));
const lastStatusId = statusIds.last();
const lastStatusId = statusIds.at(-1);
const isLoading = useAppSelector(state => (state.timelines.get(timelineId) || { isLoading: true }).isLoading === true);
const isPartial = useAppSelector(state => (state.timelines.get(timelineId)?.isPartial || false) === true);
const hasMore = useAppSelector(state => state.timelines.get(timelineId)?.hasMore === true);

View file

@ -1,8 +1,4 @@
import {
Map as ImmutableMap,
OrderedSet as ImmutableOrderedSet,
Record as ImmutableRecord,
} from 'immutable';
import { create } from 'mutative';
import {
STATUS_QUOTES_EXPAND_FAIL,
@ -72,62 +68,71 @@ import {
import type { PaginatedResponse, ScheduledStatus, Status } from 'pl-api';
import type { AnyAction } from 'redux';
const StatusListRecord = ImmutableRecord({
next: null as (() => Promise<PaginatedResponse<Status>>) | null,
interface StatusList {
next: (() => Promise<PaginatedResponse<Status>>) | null;
loaded: boolean;
isLoading: boolean | null;
items: Array<string>;
}
const newStatusList = (): StatusList => ({
next: null,
loaded: false,
isLoading: null as boolean | null,
items: ImmutableOrderedSet<string>(),
isLoading: null,
items: [],
});
type State = ImmutableMap<string, StatusList>;
type StatusList = ReturnType<typeof StatusListRecord>;
type State = Record<string, StatusList>;
const initialState: State = ImmutableMap({
favourites: StatusListRecord(),
bookmarks: StatusListRecord(),
pins: StatusListRecord(),
scheduled_statuses: StatusListRecord(),
recent_events: StatusListRecord(),
joined_events: StatusListRecord(),
});
const initialState: State = {
favourites: newStatusList(),
bookmarks: newStatusList(),
pins: newStatusList(),
scheduled_statuses: newStatusList(),
recent_events: newStatusList(),
joined_events: newStatusList(),
};
const getStatusId = (status: string | Pick<Status, 'id'>) => typeof status === 'string' ? status : status.id;
const getStatusIds = (statuses: Array<string | Pick<Status, 'id'>> = []) => (
ImmutableOrderedSet(statuses.map(getStatusId))
);
const getStatusIds = (statuses: Array<string | Pick<Status, 'id'>> = []) => statuses.map(getStatusId);
const setLoading = (state: State, listType: string, loading: boolean) =>
state.update(listType, StatusListRecord(), listMap => listMap.set('isLoading', loading));
const setLoading = (state: State, listType: string, loading: boolean) => {
const list = state[listType] = state[listType] || newStatusList();
list.isLoading = loading;
};
const normalizeList = (state: State, listType: string, statuses: Array<string | Pick<Status, 'id'>>, next: (() => Promise<PaginatedResponse<Status>>) | null) =>
state.update(listType, StatusListRecord(), listMap => listMap.withMutations(map => {
map.set('next', next);
map.set('loaded', true);
map.set('isLoading', false);
map.set('items', getStatusIds(statuses));
}));
const normalizeList = (state: State, listType: string, statuses: Array<string | Pick<Status, 'id'>>, next: (() => Promise<PaginatedResponse<Status>>) | null) => {
const list = state[listType] = state[listType] || newStatusList();
list.next = next;
list.loaded = true;
list.isLoading = false;
list.items = getStatusIds(statuses);
};
const appendToList = (state: State, listType: string, statuses: Array<string | Pick<Status, 'id'>>, next: (() => Promise<PaginatedResponse<Status>>) | null) => {
const newIds = getStatusIds(statuses);
return state.update(listType, StatusListRecord(), listMap => listMap.withMutations(map => {
map.set('next', next);
map.set('isLoading', false);
map.update('items', items => items.union(newIds));
}));
const list = state[listType] = state[listType] || newStatusList();
list.next = next;
list.isLoading = false;
list.items = [...new Set([...list.items, ...newIds])];
};
const prependOneToList = (state: State, listType: string, status: string | Pick<Status, 'id'>) => {
const statusId = getStatusId(status);
return state.update(listType, StatusListRecord(), listMap => listMap.update('items', items =>
ImmutableOrderedSet([statusId]).union(items as ImmutableOrderedSet<string>),
));
const list = state[listType] = state[listType] || newStatusList();
list.items = [...new Set([statusId, ...list.items])];
};
const removeOneFromList = (state: State, listType: string, status: string | Pick<Status, 'id'>) => {
const statusId = getStatusId(status);
return state.update(listType, StatusListRecord(), listMap => listMap.update('items', items => items.delete(statusId)));
const list = state[listType] = state[listType] || newStatusList();
list.items = list.items.filter(id => id !== statusId);
};
const maybeAppendScheduledStatus = (state: State, status: Pick<ScheduledStatus | Status, 'id' | 'scheduled_at'>) => {
@ -136,112 +141,109 @@ const maybeAppendScheduledStatus = (state: State, status: Pick<ScheduledStatus |
};
const addBookmarkToLists = (state: State, status: Pick<Status, 'id' | 'bookmark_folder'>) => {
state = prependOneToList(state, 'bookmarks', status);
prependOneToList(state, 'bookmarks', status);
const folderId = status.bookmark_folder;
if (folderId) {
return prependOneToList(state, `bookmarks:${folderId}`, status);
prependOneToList(state, `bookmarks:${folderId}`, status);
}
return state;
};
const removeBookmarkFromLists = (state: State, status: Pick<Status, 'id' | 'bookmark_folder'>) => {
state = removeOneFromList(state, 'bookmarks', status);
removeOneFromList(state, 'bookmarks', status);
const folderId = status.bookmark_folder;
if (folderId) {
return removeOneFromList(state, `bookmarks:${folderId}`, status);
removeOneFromList(state, `bookmarks:${folderId}`, status);
}
return state;
};
const statusLists = (state = initialState, action: AnyAction | BookmarksAction | EventsAction | FavouritesAction | InteractionsAction | PinStatusesAction | StatusQuotesAction) => {
const statusLists = (state = initialState, action: AnyAction | BookmarksAction | EventsAction | FavouritesAction | InteractionsAction | PinStatusesAction | StatusQuotesAction): State => {
switch (action.type) {
case FAVOURITED_STATUSES_FETCH_REQUEST:
case FAVOURITED_STATUSES_EXPAND_REQUEST:
return setLoading(state, 'favourites', true);
return create(state, draft => setLoading(draft, 'favourites', true));
case FAVOURITED_STATUSES_FETCH_FAIL:
case FAVOURITED_STATUSES_EXPAND_FAIL:
return setLoading(state, 'favourites', false);
return create(state, draft => setLoading(draft, 'favourites', false));
case FAVOURITED_STATUSES_FETCH_SUCCESS:
return normalizeList(state, 'favourites', action.statuses, action.next);
return create(state, draft => normalizeList(draft, 'favourites', action.statuses, action.next));
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
return appendToList(state, 'favourites', action.statuses, action.next);
return create(state, draft => appendToList(draft, 'favourites', action.statuses, action.next));
case ACCOUNT_FAVOURITED_STATUSES_FETCH_REQUEST:
case ACCOUNT_FAVOURITED_STATUSES_EXPAND_REQUEST:
return setLoading(state, `favourites:${action.accountId}`, true);
return create(state, draft => setLoading(draft, `favourites:${action.accountId}`, true));
case ACCOUNT_FAVOURITED_STATUSES_FETCH_FAIL:
case ACCOUNT_FAVOURITED_STATUSES_EXPAND_FAIL:
return setLoading(state, `favourites:${action.accountId}`, false);
return create(state, draft => setLoading(draft, `favourites:${action.accountId}`, false));
case ACCOUNT_FAVOURITED_STATUSES_FETCH_SUCCESS:
return normalizeList(state, `favourites:${action.accountId}`, action.statuses, action.next);
return create(state, draft => normalizeList(draft, `favourites:${action.accountId}`, action.statuses, action.next));
case ACCOUNT_FAVOURITED_STATUSES_EXPAND_SUCCESS:
return appendToList(state, `favourites:${action.accountId}`, action.statuses, action.next);
return create(state, draft => appendToList(draft, `favourites:${action.accountId}`, action.statuses, action.next));
case BOOKMARKED_STATUSES_FETCH_REQUEST:
case BOOKMARKED_STATUSES_EXPAND_REQUEST:
return setLoading(state, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', true);
return create(state, draft => setLoading(draft, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', true));
case BOOKMARKED_STATUSES_FETCH_FAIL:
case BOOKMARKED_STATUSES_EXPAND_FAIL:
return setLoading(state, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', false);
return create(state, draft => setLoading(draft, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', false));
case BOOKMARKED_STATUSES_FETCH_SUCCESS:
return normalizeList(state, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', action.statuses, action.next);
return create(state, draft => normalizeList(draft, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', action.statuses, action.next));
case BOOKMARKED_STATUSES_EXPAND_SUCCESS:
return appendToList(state, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', action.statuses, action.next);
return create(state, draft => appendToList(draft, action.folderId ? `bookmarks:${action.folderId}` : 'bookmarks', action.statuses, action.next));
case FAVOURITE_SUCCESS:
return prependOneToList(state, 'favourites', action.status);
return create(state, draft => prependOneToList(draft, 'favourites', action.status));
case UNFAVOURITE_SUCCESS:
return removeOneFromList(state, 'favourites', action.status);
return create(state, draft => removeOneFromList(draft, 'favourites', action.status));
case BOOKMARK_SUCCESS:
return addBookmarkToLists(state, action.status);
return create(state, draft => addBookmarkToLists(draft, action.status));
case UNBOOKMARK_SUCCESS:
return removeBookmarkFromLists(state, action.status);
return create(state, draft => removeBookmarkFromLists(draft, action.status));
case PINNED_STATUSES_FETCH_SUCCESS:
return normalizeList(state, 'pins', action.statuses, action.next);
return create(state, draft => normalizeList(draft, 'pins', action.statuses, action.next));
case PIN_SUCCESS:
return prependOneToList(state, 'pins', action.status);
return create(state, draft => prependOneToList(draft, 'pins', action.status));
case UNPIN_SUCCESS:
return removeOneFromList(state, 'pins', action.status);
return create(state, draft => removeOneFromList(draft, 'pins', action.status));
case SCHEDULED_STATUSES_FETCH_REQUEST:
case SCHEDULED_STATUSES_EXPAND_REQUEST:
return setLoading(state, 'scheduled_statuses', true);
return create(state, draft => setLoading(draft, 'scheduled_statuses', true));
case SCHEDULED_STATUSES_FETCH_FAIL:
case SCHEDULED_STATUSES_EXPAND_FAIL:
return setLoading(state, 'scheduled_statuses', false);
return create(state, draft => setLoading(draft, 'scheduled_statuses', false));
case SCHEDULED_STATUSES_FETCH_SUCCESS:
return normalizeList(state, 'scheduled_statuses', action.statuses, action.next);
return create(state, draft => normalizeList(draft, 'scheduled_statuses', action.statuses, action.next));
case SCHEDULED_STATUSES_EXPAND_SUCCESS:
return appendToList(state, 'scheduled_statuses', action.statuses, action.next);
return create(state, draft => appendToList(draft, 'scheduled_statuses', action.statuses, action.next));
case SCHEDULED_STATUS_CANCEL_REQUEST:
case SCHEDULED_STATUS_CANCEL_SUCCESS:
return removeOneFromList(state, 'scheduled_statuses', action.statusId);
return create(state, draft => removeOneFromList(draft, 'scheduled_statuses', action.statusId));
case STATUS_QUOTES_FETCH_REQUEST:
case STATUS_QUOTES_EXPAND_REQUEST:
return setLoading(state, `quotes:${action.statusId}`, true);
return create(state, draft => setLoading(draft, `quotes:${action.statusId}`, true));
case STATUS_QUOTES_FETCH_FAIL:
case STATUS_QUOTES_EXPAND_FAIL:
return setLoading(state, `quotes:${action.statusId}`, false);
return create(state, draft => setLoading(draft, `quotes:${action.statusId}`, false));
case STATUS_QUOTES_FETCH_SUCCESS:
return normalizeList(state, `quotes:${action.statusId}`, action.statuses, action.next);
return create(state, draft => normalizeList(draft, `quotes:${action.statusId}`, action.statuses, action.next));
case STATUS_QUOTES_EXPAND_SUCCESS:
return appendToList(state, `quotes:${action.statusId}`, action.statuses, action.next);
return create(state, draft => appendToList(draft, `quotes:${action.statusId}`, action.statuses, action.next));
case RECENT_EVENTS_FETCH_REQUEST:
return setLoading(state, 'recent_events', true);
return create(state, draft => setLoading(draft, 'recent_events', true));
case RECENT_EVENTS_FETCH_FAIL:
return setLoading(state, 'recent_events', false);
return create(state, draft => setLoading(draft, 'recent_events', false));
case RECENT_EVENTS_FETCH_SUCCESS:
return normalizeList(state, 'recent_events', action.statuses, action.next);
return create(state, draft => normalizeList(draft, 'recent_events', action.statuses, action.next));
case JOINED_EVENTS_FETCH_REQUEST:
return setLoading(state, 'joined_events', true);
return create(state, draft => setLoading(draft, 'joined_events', true));
case JOINED_EVENTS_FETCH_FAIL:
return setLoading(state, 'joined_events', false);
return create(state, draft => setLoading(draft, 'joined_events', false));
case JOINED_EVENTS_FETCH_SUCCESS:
return normalizeList(state, 'joined_events', action.statuses, action.next);
return create(state, draft => normalizeList(draft, 'joined_events', action.statuses, action.next));
case STATUS_CREATE_SUCCESS:
return maybeAppendScheduledStatus(state, action.status);
return create(state, draft => maybeAppendScheduledStatus(draft, action.status));
default:
return state;
}
};
export {
StatusListRecord,
statusLists as default,
};

View file

@ -347,7 +347,7 @@ const makeGetStatusIds = () => createSelector([
const status = statuses[id];
if (!status) return true;
return !shouldFilter(status, columnSettings);
}),
}).toArray(),
);
export {