From 865130c55aeeacc77373368eb2ee01db43458a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sun, 10 Nov 2024 23:10:54 +0100 Subject: [PATCH] pl-fe: remove some immutable usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- packages/pl-fe/src/features/aliases/index.tsx | 2 +- .../auth-login/components/captcha.tsx | 12 +- .../components/registration-form.tsx | 7 +- .../crypto-donate/utils/manifest-map.ts | 10 +- .../federation-restrictions/index.tsx | 4 +- .../src/features/notifications/index.tsx | 15 +-- .../components/placeholder-media-gallery.tsx | 21 ++- .../pl-fe/src/features/preferences/index.tsx | 3 +- .../modals/list-editor-modal/index.tsx | 2 +- packages/pl-fe/src/reducers/aliases.ts | 61 +++++---- packages/pl-fe/src/reducers/list-adder.ts | 64 +++++---- packages/pl-fe/src/reducers/list-editor.ts | 122 +++++++++++------- packages/pl-fe/src/selectors/index.ts | 18 +-- packages/pl-fe/src/utils/auth.ts | 10 +- packages/pl-fe/src/utils/badges.ts | 15 +-- 15 files changed, 197 insertions(+), 169 deletions(-) diff --git a/packages/pl-fe/src/features/aliases/index.tsx b/packages/pl-fe/src/features/aliases/index.tsx index d786abfc6..98a95687c 100644 --- a/packages/pl-fe/src/features/aliases/index.tsx +++ b/packages/pl-fe/src/features/aliases/index.tsx @@ -59,7 +59,7 @@ const Aliases = () => { { - loaded && searchAccountIds.size === 0 ? ( + loaded && searchAccountIds.length === 0 ? (
diff --git a/packages/pl-fe/src/features/auth-login/components/captcha.tsx b/packages/pl-fe/src/features/auth-login/components/captcha.tsx index add7cb36a..56c465596 100644 --- a/packages/pl-fe/src/features/auth-login/components/captcha.tsx +++ b/packages/pl-fe/src/features/auth-login/components/captcha.tsx @@ -1,4 +1,3 @@ -import { Map as ImmutableMap } from 'immutable'; import React, { useState, useEffect } from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; @@ -19,7 +18,7 @@ interface ICaptchaField { name?: string; value: string; onChange?: React.ChangeEventHandler; - onFetch?: (captcha: ImmutableMap) => void; + onFetch?: (captcha: Record) => void; onFetchFail?: (error: Error) => void; onClick?: React.MouseEventHandler; refreshInterval?: number; @@ -38,12 +37,11 @@ const CaptchaField: React.FC = ({ }) => { const dispatch = useAppDispatch(); - const [captcha, setCaptcha] = useState(ImmutableMap()); + const [captcha, setCaptcha] = useState>({}); const [refresh, setRefresh] = useState(undefined); const getCaptcha = () => { - dispatch(fetchCaptcha()).then((response) => { - const captcha = ImmutableMap(response); + dispatch(fetchCaptcha()).then((captcha) => { setCaptcha(captcha); onFetch(captcha); }).catch((error: Error) => { @@ -98,7 +96,7 @@ const CaptchaField: React.FC = ({ }; interface INativeCaptchaField { - captcha: ImmutableMap; + captcha: Record; onChange: React.ChangeEventHandler; onClick: React.MouseEventHandler; name?: string; @@ -111,7 +109,7 @@ const NativeCaptchaField: React.FC = ({ captcha, onChange, return (
- {intl.formatMessage(messages.captcha)} + {intl.formatMessage(messages.captcha)}
= ({ inviteToken }) => { refreshCaptcha(); }; - const onFetchCaptcha = (captcha: ImmutableMap) => { + const onFetchCaptcha = (captcha: Record) => { setCaptchaLoading(false); setParams(params => ({ ...params, - captcha_token: captcha.get('token'), - captcha_answer_data: captcha.get('answer_data'), + captcha_token: captcha.token, + captcha_answer_data: captcha.answer_data, })); }; diff --git a/packages/pl-fe/src/features/crypto-donate/utils/manifest-map.ts b/packages/pl-fe/src/features/crypto-donate/utils/manifest-map.ts index 239e373f2..ff767d412 100644 --- a/packages/pl-fe/src/features/crypto-donate/utils/manifest-map.ts +++ b/packages/pl-fe/src/features/crypto-donate/utils/manifest-map.ts @@ -2,12 +2,10 @@ // See: https://github.com/spothq/cryptocurrency-icons/blob/master/manifest.json import manifest from 'cryptocurrency-icons/manifest.json'; -import { List as ImmutableList, Map as ImmutableMap, fromJS } from 'immutable'; -const manifestMap = (fromJS(manifest) as ImmutableList>).reduce( - (acc: ImmutableMap>, entry: ImmutableMap) => - acc.set(entry.get('symbol')!.toLowerCase(), entry), - ImmutableMap(), -).toJS(); +const manifestMap = manifest.reduce((acc: Record, entry) => { + acc[entry.symbol.toLowerCase()] = entry; + return acc; +}, {}); export { manifestMap as default }; diff --git a/packages/pl-fe/src/features/federation-restrictions/index.tsx b/packages/pl-fe/src/features/federation-restrictions/index.tsx index 4fa825e32..45d72076b 100644 --- a/packages/pl-fe/src/features/federation-restrictions/index.tsx +++ b/packages/pl-fe/src/features/federation-restrictions/index.tsx @@ -11,8 +11,6 @@ import { federationRestrictionsDisclosed } from 'pl-fe/utils/state'; import RestrictedInstance from './components/restricted-instance'; -import type { OrderedSet as ImmutableOrderedSet } from 'immutable'; - const messages = defineMessages({ heading: { id: 'column.federation_restrictions', defaultMessage: 'Federation Restrictions' }, boxTitle: { id: 'federation_restrictions.explanation_box.title', defaultMessage: 'Instance-specific policies' }, @@ -27,7 +25,7 @@ const FederationRestrictions = () => { const getHosts = useCallback(makeGetHosts(), []); - const hosts = useAppSelector((state) => getHosts(state)) as ImmutableOrderedSet; + const hosts = useAppSelector((state) => getHosts(state)); const disclosed = useAppSelector((state) => federationRestrictionsDisclosed(state)); const [explanationBoxExpanded, setExplanationBoxExpanded] = useState(true); diff --git a/packages/pl-fe/src/features/notifications/index.tsx b/packages/pl-fe/src/features/notifications/index.tsx index 4b682d0b8..dcb5ef7fa 100644 --- a/packages/pl-fe/src/features/notifications/index.tsx +++ b/packages/pl-fe/src/features/notifications/index.tsx @@ -1,5 +1,4 @@ import clsx from 'clsx'; -import { List as ImmutableList } from 'immutable'; import debounce from 'lodash/debounce'; import React, { useCallback, useEffect, useRef } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -31,8 +30,8 @@ const messages = defineMessages({ }); const getNotifications = createSelector([ - (state: RootState) => state.notifications.items.toList(), -], (notifications) => notifications.filter(item => item !== null)); + (state: RootState) => state.notifications.items.toArray(), +], (notifications) => notifications.map(([_, notification]) => notification).filter(item => item !== null)); const Notifications = () => { const dispatch = useAppDispatch(); @@ -47,7 +46,7 @@ const Notifications = () => { const hasMore = useAppSelector(state => state.notifications.hasMore); const totalQueuedNotificationsCount = useAppSelector(state => state.notifications.totalQueuedNotificationsCount || 0); - const scrollableContentRef = useRef | null>(null); + const scrollableContentRef = useRef | null>(null); // const handleLoadGap = (maxId) => { // dispatch(expandNotifications({ maxId })); @@ -105,7 +104,7 @@ const Notifications = () => { ? : ; - let scrollableContent: ImmutableList | null = null; + let scrollableContent: Array | null = null; const filterBarContainer = showFilterBar ? () @@ -113,7 +112,7 @@ const Notifications = () => { if (isLoading && scrollableContentRef.current) { scrollableContent = scrollableContentRef.current; - } else if (notifications.size > 0 || hasMore) { + } else if (notifications.length > 0 || hasMore) { scrollableContent = notifications.map((item) => ( { const scrollContainer = ( { onLoadMore={handleLoadOlder} onScroll={handleScroll} listClassName={clsx('divide-y divide-solid divide-gray-200 black:divide-gray-800 dark:divide-primary-800', { - 'animate-pulse': notifications.size === 0, + 'animate-pulse': notifications.length === 0, })} > {scrollableContent!} diff --git a/packages/pl-fe/src/features/placeholder/components/placeholder-media-gallery.tsx b/packages/pl-fe/src/features/placeholder/components/placeholder-media-gallery.tsx index b221b3697..e720ce80c 100644 --- a/packages/pl-fe/src/features/placeholder/components/placeholder-media-gallery.tsx +++ b/packages/pl-fe/src/features/placeholder/components/placeholder-media-gallery.tsx @@ -1,4 +1,3 @@ -import { Record as ImmutableRecord } from 'immutable'; import { MediaAttachment } from 'pl-api'; import React, { useState } from 'react'; @@ -7,12 +6,12 @@ interface IPlaceholderMediaGallery { defaultWidth?: number; } -const SizeData = ImmutableRecord({ - style: {} as React.CSSProperties, - itemsDimensions: [] as Record[], - size: 1 as number, - width: 0 as number, -}); +interface SizeData { + style: React.CSSProperties; + itemsDimensions: Record[]; + size: number; + width: number; +} const PlaceholderMediaGallery: React.FC = ({ media, defaultWidth }) => { const [width, setWidth] = useState(defaultWidth); @@ -23,7 +22,7 @@ const PlaceholderMediaGallery: React.FC = ({ media, de } }; - const getSizeData = (size: number) => { + const getSizeData = (size: number): SizeData => { const style: React.CSSProperties = {}; let itemsDimensions: Record[] = []; @@ -59,12 +58,12 @@ const PlaceholderMediaGallery: React.FC = ({ media, de ]; } - return SizeData({ + return { style, itemsDimensions, size, - width, - }); + width: width || 0, + }; }; const renderItem = (dimensions: Record, i: number) => { diff --git a/packages/pl-fe/src/features/preferences/index.tsx b/packages/pl-fe/src/features/preferences/index.tsx index 1d63cff63..7fdb36aaa 100644 --- a/packages/pl-fe/src/features/preferences/index.tsx +++ b/packages/pl-fe/src/features/preferences/index.tsx @@ -1,4 +1,3 @@ -import { Set as ImmutableSet } from 'immutable'; import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -106,7 +105,7 @@ const Preferences = () => { }; const onSelectMultiple = (selectedList: string[], path: string[]) => { - dispatch(changeSetting(path, ImmutableSet(selectedList.sort((a, b) => a.localeCompare(b))), { showAlert: true })); + dispatch(changeSetting(path, selectedList.toSorted((a, b) => a.localeCompare(b)), { showAlert: true })); }; const onToggleChange = (key: string[], checked: boolean) => { diff --git a/packages/pl-fe/src/features/ui/components/modals/list-editor-modal/index.tsx b/packages/pl-fe/src/features/ui/components/modals/list-editor-modal/index.tsx index 1e79a4a4b..15bac48cf 100644 --- a/packages/pl-fe/src/features/ui/components/modals/list-editor-modal/index.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/list-editor-modal/index.tsx @@ -54,7 +54,7 @@ const ListEditorModal: React.FC = ({ list
- {accountIds.size > 0 && ( + {accountIds.length > 0 && (
diff --git a/packages/pl-fe/src/reducers/aliases.ts b/packages/pl-fe/src/reducers/aliases.ts index 1b2051320..b1395aaa9 100644 --- a/packages/pl-fe/src/reducers/aliases.ts +++ b/packages/pl-fe/src/reducers/aliases.ts @@ -1,4 +1,4 @@ -import { List as ImmutableList, Record as ImmutableRecord } from 'immutable'; +import { create } from 'mutative'; import { ALIASES_SUGGESTIONS_READY, @@ -8,37 +8,52 @@ import { AliasesAction, } from '../actions/aliases'; -const ReducerRecord = ImmutableRecord({ - aliases: ImmutableRecord({ - items: ImmutableList(), +interface State { + aliases: { + items: Array; + loaded: boolean; + }; + suggestions: { + items: Array; + value: string; + loaded: boolean; + }; +} + +const initialState: State = { + aliases: { + items: [], loaded: false, - })(), - suggestions: ImmutableRecord({ - items: ImmutableList(), + }, + suggestions: { + items: [], value: '', loaded: false, - })(), -}); + }, +}; -const aliasesReducer = (state = ReducerRecord(), action: AliasesAction) => { +const aliasesReducer = (state = initialState, action: AliasesAction): State => { switch (action.type) { case ALIASES_FETCH_SUCCESS: - return state - .setIn(['aliases', 'items'], action.value); + return create(state, (draft) => { + draft.aliases.items = action.value; + }); case ALIASES_SUGGESTIONS_CHANGE: - return state - .setIn(['suggestions', 'value'], action.value) - .setIn(['suggestions', 'loaded'], false); + return create(state, (draft) => { + draft.suggestions.value = action.value; + draft.suggestions.loaded = false; + }); case ALIASES_SUGGESTIONS_READY: - return state - .setIn(['suggestions', 'items'], ImmutableList(action.accounts.map((item) => item.id))) - .setIn(['suggestions', 'loaded'], true); + return create(state, (draft) => { + draft.suggestions.items = action.accounts.map((item) => item.id); + draft.suggestions.loaded = true; + }); case ALIASES_SUGGESTIONS_CLEAR: - return state.update('suggestions', suggestions => suggestions.withMutations(map => { - map.set('items', ImmutableList()); - map.set('value', ''); - map.set('loaded', false); - })); + return create(state, (draft) => { + draft.suggestions.items = []; + draft.suggestions.value = ''; + draft.suggestions.loaded = false; + }); default: return state; } diff --git a/packages/pl-fe/src/reducers/list-adder.ts b/packages/pl-fe/src/reducers/list-adder.ts index 7716f4db0..e69b87baf 100644 --- a/packages/pl-fe/src/reducers/list-adder.ts +++ b/packages/pl-fe/src/reducers/list-adder.ts @@ -1,4 +1,4 @@ -import { List as ImmutableList, Record as ImmutableRecord } from 'immutable'; +import { create } from 'mutative'; import { LIST_ADDER_RESET, @@ -12,42 +12,54 @@ import { import type { AnyAction } from 'redux'; -const ListsRecord = ImmutableRecord({ - items: ImmutableList(), - loaded: false, - isLoading: false, -}); +interface State { + accountId: string | null; + lists: { + items: Array; + loaded: boolean; + isLoading: boolean; + }; +} -const ReducerRecord = ImmutableRecord({ - accountId: null as string | null, +const initialState: State = { + accountId: null, + lists: { + items: [], + loaded: false, + isLoading: false, + }, +}; - lists: ListsRecord(), -}); - -type State = ReturnType; - -const listAdderReducer = (state: State = ReducerRecord(), action: AnyAction) => { +const listAdderReducer = (state: State = initialState, action: AnyAction): State => { switch (action.type) { case LIST_ADDER_RESET: - return ReducerRecord(); + return initialState; case LIST_ADDER_SETUP: - return state.withMutations(map => { - map.set('accountId', action.account.id); + return create(state, (draft) => { + draft.accountId = action.account.id; }); case LIST_ADDER_LISTS_FETCH_REQUEST: - return state.setIn(['lists', 'isLoading'], true); + return create(state, (draft) => { + draft.lists.isLoading = true; + }); case LIST_ADDER_LISTS_FETCH_FAIL: - return state.setIn(['lists', 'isLoading'], false); + return create(state, (draft) => { + draft.lists.isLoading = false; + }); case LIST_ADDER_LISTS_FETCH_SUCCESS: - return state.update('lists', lists => lists.withMutations(map => { - map.set('isLoading', false); - map.set('loaded', true); - map.set('items', ImmutableList(action.lists.map((item: { id: string }) => item.id))); - })); + return create(state, (draft) => { + draft.lists.isLoading = false; + draft.lists.loaded = true; + draft.lists.items = action.lists.map((item: { id: string }) => item.id); + }); case LIST_EDITOR_ADD_SUCCESS: - return state.updateIn(['lists', 'items'], list => (list as ImmutableList).unshift(action.listId)); + return create(state, (draft) => { + draft.lists.items = [action.listId, ...draft.lists.items]; + }); case LIST_EDITOR_REMOVE_SUCCESS: - return state.updateIn(['lists', 'items'], list => (list as ImmutableList).filterNot(item => item === action.listId)); + return create(state, (draft) => { + draft.lists.items = draft.lists.items.filter(id => id !== action.listId); + }); default: return state; } diff --git a/packages/pl-fe/src/reducers/list-editor.ts b/packages/pl-fe/src/reducers/list-editor.ts index a8f1ac6de..8a9a21997 100644 --- a/packages/pl-fe/src/reducers/list-editor.ts +++ b/packages/pl-fe/src/reducers/list-editor.ts @@ -1,4 +1,4 @@ -import { List as ImmutableList, Record as ImmutableRecord } from 'immutable'; +import { create } from 'mutative'; import { LIST_CREATE_REQUEST, @@ -22,83 +22,109 @@ import { import type { AnyAction } from 'redux'; -const AccountsRecord = ImmutableRecord({ - items: ImmutableList(), - loaded: false, - isLoading: false, -}); +interface State { + listId: string | null; + isSubmitting: boolean; + isChanged: boolean; + title: string; -const SuggestionsRecord = ImmutableRecord({ - value: '', - items: ImmutableList(), -}); + accounts: { + items: Array; + loaded: boolean; + isLoading: boolean; + }; -const ReducerRecord = ImmutableRecord({ - listId: null as string | null, + suggestions: { + value: string; + items: Array; + }; +} + +const initialState: State = { + listId: null, isSubmitting: false, isChanged: false, title: '', - accounts: AccountsRecord(), + accounts: { + items: [], + loaded: false, + isLoading: false, + }, - suggestions: SuggestionsRecord(), -}); + suggestions: { + value: '', + items: [], + }, +}; -type State = ReturnType; - -const listEditorReducer = (state: State = ReducerRecord(), action: AnyAction) => { +const listEditorReducer = (state: State = initialState, action: AnyAction): State => { switch (action.type) { case LIST_EDITOR_RESET: - return ReducerRecord(); + return initialState; case LIST_EDITOR_SETUP: - return state.withMutations(map => { - map.set('listId', action.list.id); - map.set('title', action.list.title); - map.set('isSubmitting', false); + return create(state, (draft) => { + draft.listId = action.list.id; + draft.title = action.list.title; + draft.isSubmitting = false; }); case LIST_EDITOR_TITLE_CHANGE: - return state.withMutations(map => { - map.set('title', action.value); - map.set('isChanged', true); + return create(state, (draft) => { + draft.title = action.value; + draft.isChanged = true; }); case LIST_CREATE_REQUEST: case LIST_UPDATE_REQUEST: - return state.withMutations(map => { - map.set('isSubmitting', true); - map.set('isChanged', false); + return create(state, (draft) => { + draft.isSubmitting = true; + draft.isChanged = false; }); case LIST_CREATE_FAIL: case LIST_UPDATE_FAIL: - return state.set('isSubmitting', false); + return create(state, (draft) => { + draft.isSubmitting = false; + }); case LIST_CREATE_SUCCESS: case LIST_UPDATE_SUCCESS: - return state.withMutations(map => { - map.set('isSubmitting', false); - map.set('listId', action.list.id); + return create(state, (draft) => { + draft.isSubmitting = false; + draft.listId = action.list.id; }); case LIST_ACCOUNTS_FETCH_REQUEST: - return state.setIn(['accounts', 'isLoading'], true); + return create(state, (draft) => { + draft.accounts.isLoading = true; + }); case LIST_ACCOUNTS_FETCH_FAIL: - return state.setIn(['accounts', 'isLoading'], false); + return create(state, (draft) => { + draft.accounts.isLoading = false; + }); case LIST_ACCOUNTS_FETCH_SUCCESS: - return state.update('accounts', accounts => accounts.withMutations(map => { - map.set('isLoading', false); - map.set('loaded', true); - map.set('items', ImmutableList(action.accounts.map((item: { id: string }) => item.id))); - })); + return create(state, (draft) => { + draft.accounts.isLoading = false; + draft.accounts.loaded = true; + draft.accounts.items = action.accounts.map((item: { id: string }) => item.id); + }); case LIST_EDITOR_SUGGESTIONS_CHANGE: - return state.setIn(['suggestions', 'value'], action.value); + return create(state, (draft) => { + draft.suggestions.value = action.value; + }); case LIST_EDITOR_SUGGESTIONS_READY: - return state.setIn(['suggestions', 'items'], ImmutableList(action.accounts.map((item: { id: string }) => item.id))); + return create(state, (draft) => { + draft.suggestions.items = action.accounts.map((item: { id: string }) => item.id); + }); case LIST_EDITOR_SUGGESTIONS_CLEAR: - return state.update('suggestions', suggestions => suggestions.withMutations(map => { - map.set('items', ImmutableList()); - map.set('value', ''); - })); + return create(state, (draft) => { + draft.suggestions.items = []; + draft.suggestions.value = ''; + }); case LIST_EDITOR_ADD_SUCCESS: - return state.updateIn(['accounts', 'items'], list => (list as ImmutableList).unshift(action.accountId)); + return create(state, (draft) => { + draft.accounts.items = [action.accountId, ...draft.accounts.items]; + }); case LIST_EDITOR_REMOVE_SUCCESS: - return state.updateIn(['accounts', 'items'], list => (list as ImmutableList).filterNot((item) => item === action.accountId)); + return create(state, (draft) => { + draft.accounts.items = draft.accounts.items.filter(id => id !== action.accoundId); + }); default: return state; } diff --git a/packages/pl-fe/src/selectors/index.ts b/packages/pl-fe/src/selectors/index.ts index 40f3d5da5..67ce403e8 100644 --- a/packages/pl-fe/src/selectors/index.ts +++ b/packages/pl-fe/src/selectors/index.ts @@ -1,4 +1,3 @@ -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; import { createSelector } from 'reselect'; // import { getLocale } from 'pl-fe/actions/settings'; @@ -262,14 +261,11 @@ const makeGetReport = () => { const getAuthUserIds = createSelector( [(state: RootState) => state.auth.users], - authUsers => authUsers.reduce((userIds: ImmutableOrderedSet, authUser) => { - try { - const userId = authUser.id; - return validId(userId) ? userIds.add(userId) : userIds; - } catch { - return userIds; - } - }, ImmutableOrderedSet())); + authUsers => authUsers.reduce((userIds: Array, authUser) => { + const userId = authUser?.id; + if (validId(userId)) userIds.push(userId); + return userIds; + }, [])); const makeGetOtherAccounts = () => createSelector([ (state: RootState) => state.entities[Entities.ACCOUNTS]?.store as EntityStore, @@ -314,9 +310,7 @@ const makeGetHosts = () => createSelector([getSimplePolicy], (simplePolicy) => { const { accept, reject_deletes, report_removal, ...rest } = simplePolicy; - return Object.values(rest) - .reduce((acc, hosts) => acc.union(hosts), ImmutableOrderedSet()) - .sort(); + return [...new Set(Object.values(rest).reduce((acc, hosts) => (acc.push(...hosts), acc), []))].toSorted(); }); interface RemoteInstance { diff --git a/packages/pl-fe/src/utils/auth.ts b/packages/pl-fe/src/utils/auth.ts index d2de057b2..d5b3d68f0 100644 --- a/packages/pl-fe/src/utils/auth.ts +++ b/packages/pl-fe/src/utils/auth.ts @@ -1,5 +1,3 @@ -import { List as ImmutableList } from 'immutable'; - import { selectAccount, selectOwnAccount } from 'pl-fe/selectors'; import type { RootState } from 'pl-fe/store'; @@ -43,19 +41,19 @@ const getAccessToken = (state: RootState) => { const getAuthUserId = (state: RootState) => { const me = state.auth.me; - return ImmutableList([ + return [ state.auth.users.get(me!)?.id, me, - ].filter(id => id)).find(validId); + ].filter(id => id).find(validId); }; const getAuthUserUrl = (state: RootState) => { const me = state.auth.me; - return ImmutableList([ + return [ state.auth.users.get(me!)?.url, me, - ].filter(url => url)).find(isURL); + ].filter(url => url).find(isURL); }; /** Get the VAPID public key. */ diff --git a/packages/pl-fe/src/utils/badges.ts b/packages/pl-fe/src/utils/badges.ts index 5b512ed0b..f1bcd8312 100644 --- a/packages/pl-fe/src/utils/badges.ts +++ b/packages/pl-fe/src/utils/badges.ts @@ -1,5 +1,3 @@ -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; - import type { Account } from 'pl-fe/normalizers/account'; /** Convert a plain tag into a badge. */ @@ -17,15 +15,10 @@ interface TagDiff { } /** Returns the differences between two sets of tags. */ -const getTagDiff = (oldTags: string[], newTags: string[]): TagDiff => { - const o = ImmutableOrderedSet(oldTags); - const n = ImmutableOrderedSet(newTags); - - return { - added: n.subtract(o).toArray(), - removed: o.subtract(n).toArray(), - }; -}; +const getTagDiff = (oldTags: string[], newTags: string[]): TagDiff => ({ + added: newTags.filter(tag => !oldTags.includes(tag)), + removed: oldTags.filter(tag => !newTags.includes(tag)), +}); /** Returns only tags which are badges. */ const filterBadges = (tags: string[]): string[] => tags.filter(tag => tag.startsWith('badge:'));