Remove legacy accounts reducer

environments/review-develop-3zknud/deployments/3653
Alex Gleason 2023-07-20 15:03:23 -05:00
rodzic 7944de8305
commit 90664dd5c6
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
25 zmienionych plików z 143 dodań i 138 usunięć

Wyświetl plik

@ -1,5 +1,6 @@
import { importEntities } from 'soapbox/entity-store/actions';
import { Entities } from 'soapbox/entity-store/entities';
import { selectAccount } from 'soapbox/selectors';
import { isLoggedIn } from 'soapbox/utils/auth';
import { getFeatures, parseVersion, PLEROMA } from 'soapbox/utils/features';
@ -141,9 +142,9 @@ const fetchAccount = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch(fetchRelationships([id]));
const account = getState().accounts.get(id);
const account = selectAccount(getState(), id);
if (account && !account.get('should_refetch')) {
if (account) {
return null;
}

Wyświetl plik

@ -2,6 +2,7 @@ import { defineMessages } from 'react-intl';
import { fetchRelationships } from 'soapbox/actions/accounts';
import { importFetchedAccount, importFetchedAccounts, importFetchedStatuses } from 'soapbox/actions/importer';
import { selectAccount } from 'soapbox/selectors';
import toast from 'soapbox/toast';
import { filterBadges, getTagDiff } from 'soapbox/utils/badges';
import { getFeatures } from 'soapbox/utils/features';
@ -121,7 +122,7 @@ const messages = defineMessages({
announcementUpdateSuccess: { id: 'admin.edit_announcement.updated', defaultMessage: 'Announcement edited' },
});
const nicknamesFromIds = (getState: () => RootState, ids: string[]) => ids.map(id => getState().accounts.get(id)!.acct);
const nicknamesFromIds = (getState: () => RootState, ids: string[]) => ids.map((id) => selectAccount(getState(), id)!.acct);
const fetchConfig = () =>
(dispatch: AppDispatch, getState: () => RootState) => {

Wyświetl plik

@ -16,6 +16,7 @@ import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth';
import { startOnboarding } from 'soapbox/actions/onboarding';
import { custom } from 'soapbox/custom';
import { queryClient } from 'soapbox/queries/client';
import { selectAccount } from 'soapbox/selectors';
import KVStore from 'soapbox/storage/kv-store';
import toast from 'soapbox/toast';
import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth';
@ -227,7 +228,7 @@ export const logOut = () =>
export const switchAccount = (accountId: string, background = false) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const account = getState().accounts.get(accountId);
const account = selectAccount(getState(), accountId);
// Clear all stored cache from React Query
queryClient.invalidateQueries();
queryClient.clear();
@ -239,7 +240,7 @@ export const fetchOwnAccounts = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
return state.auth.users.forEach((user) => {
const account = state.accounts.get(user.id);
const account = selectAccount(state, user.id);
if (!account) {
dispatch(verifyCredentials(user.access_token, user.url))
.catch(() => console.warn(`Failed to load account: ${user.url}`));

Wyświetl plik

@ -6,6 +6,7 @@ import { defineMessages, IntlShape } from 'react-intl';
import api from 'soapbox/api';
import { isNativeEmoji } from 'soapbox/features/emoji';
import emojiSearch from 'soapbox/features/emoji/search';
import { selectAccount, selectOwnAccount } from 'soapbox/selectors';
import { tagHistory } from 'soapbox/settings';
import toast from 'soapbox/toast';
import { isLoggedIn } from 'soapbox/utils/auth';
@ -151,12 +152,14 @@ const replyCompose = (status: Status) =>
const state = getState();
const instance = state.instance;
const { explicitAddressing } = getFeatures(instance);
const account = selectOwnAccount(state);
if (!account) return;
const action: ComposeReplyAction = {
type: COMPOSE_REPLY,
id: 'compose-modal',
status: status,
account: state.accounts.get(state.me)!,
account,
explicitAddressing,
};
@ -187,7 +190,7 @@ const quoteCompose = (status: Status) =>
type: COMPOSE_QUOTE,
id: 'compose-modal',
status: status,
account: state.accounts.get(state.me),
account: selectOwnAccount(state),
explicitAddressing,
};
@ -251,7 +254,7 @@ const directCompose = (account: Account) =>
const directComposeById = (accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const account = getState().accounts.get(accountId);
const account = selectAccount(getState(), accountId);
if (!account) return;
const action: ComposeDirectAction = {
@ -651,11 +654,13 @@ const selectComposeSuggestion = (composeId: string, position: number, token: str
} else if (typeof suggestion === 'string' && suggestion[0] === '#') {
completion = suggestion;
startPosition = position - 1;
} else {
completion = getState().accounts.get(suggestion)!.acct;
} else if (typeof suggestion === 'string') {
completion = selectAccount(getState(), suggestion)!.acct;
startPosition = position;
}
if (!startPosition || !completion) return;
const action: ComposeSuggestionSelectAction = {
type: COMPOSE_SUGGESTION_SELECT,
id: composeId,
@ -798,12 +803,13 @@ interface ComposeAddToMentionsAction {
const addToMentions = (composeId: string, accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const acct = state.accounts.get(accountId)!.acct;
const account = selectAccount(state, accountId);
if (!account) return;
const action: ComposeAddToMentionsAction = {
type: COMPOSE_ADD_TO_MENTIONS,
id: composeId,
account: acct,
account: account.acct,
};
return dispatch(action);
@ -818,12 +824,13 @@ interface ComposeRemoveFromMentionsAction {
const removeFromMentions = (composeId: string, accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const acct = state.accounts.get(accountId)!.acct;
const account = selectAccount(state, accountId);
if (!account) return;
const action: ComposeRemoveFromMentionsAction = {
type: COMPOSE_REMOVE_FROM_MENTIONS,
id: composeId,
account: acct,
account: account.acct,
};
return dispatch(action);
@ -847,7 +854,7 @@ const eventDiscussionCompose = (composeId: string, status: Status) =>
type: COMPOSE_EVENT_REPLY,
id: composeId,
status: status,
account: state.accounts.get(state.me),
account: selectOwnAccount(state),
explicitAddressing,
});
};

Wyświetl plik

@ -1,8 +1,11 @@
import { Entities } from 'soapbox/entity-store/entities';
import { isLoggedIn } from 'soapbox/utils/auth';
import api, { getLinks } from '../api';
import type { AxiosError } from 'axios';
import type { EntityStore } from 'soapbox/entity-store/types';
import type { Account } from 'soapbox/schemas';
import type { AppDispatch, RootState } from 'soapbox/store';
const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST';
@ -28,11 +31,8 @@ const blockDomain = (domain: string) =>
dispatch(blockDomainRequest(domain));
api(getState).post('/api/v1/domain_blocks', { domain }).then(() => {
const at_domain = '@' + domain;
const accounts = getState().accounts
.filter(item => item.acct.endsWith(at_domain))
.map(item => item.id);
const accounts = selectAccountsByDomain(getState(), domain);
if (!accounts) return;
dispatch(blockDomainSuccess(domain, accounts));
}).catch(err => {
dispatch(blockDomainFail(domain, err));
@ -69,8 +69,8 @@ const unblockDomain = (domain: string) =>
};
api(getState).delete('/api/v1/domain_blocks', params).then(() => {
const at_domain = '@' + domain;
const accounts = getState().accounts.filter(item => item.acct.endsWith(at_domain)).map(item => item.id);
const accounts = selectAccountsByDomain(getState(), domain);
if (!accounts) return;
dispatch(unblockDomainSuccess(domain, accounts));
}).catch(err => {
dispatch(unblockDomainFail(domain, err));
@ -143,6 +143,15 @@ const expandDomainBlocks = () =>
});
};
function selectAccountsByDomain(state: RootState, domain: string): string[] {
const store = state.entities[Entities.ACCOUNTS]?.store as EntityStore<Account> | undefined;
const entries = store ? Object.entries(store) : undefined;
const accounts = entries
?.filter(([_, item]) => item && item.acct.endsWith(`@${domain}`))
.map(([_, item]) => item!.id);
return accounts || [];
}
const expandDomainBlocksRequest = () => ({
type: DOMAIN_BLOCKS_EXPAND_REQUEST,
});

Wyświetl plik

@ -3,16 +3,11 @@ import get from 'lodash/get';
import KVStore from 'soapbox/storage/kv-store';
import { RootState } from 'soapbox/store';
import { getAuthUserUrl } from 'soapbox/utils/auth';
import { getAuthUserUrl, getMeUrl } from 'soapbox/utils/auth';
import { parseVersion } from 'soapbox/utils/features';
import api from '../api';
const getMeUrl = (state: RootState) => {
const me = state.me;
return state.accounts.get(me)?.url;
};
/** Figure out the appropriate instance to fetch depending on the state */
export const getHost = (state: RootState) => {
const accountUrl = getMeUrl(state) || getAuthUserUrl(state) as string;

Wyświetl plik

@ -1,3 +1,4 @@
import { selectAccount } from 'soapbox/selectors';
import toast from 'soapbox/toast';
import { isLoggedIn } from 'soapbox/utils/auth';
@ -356,7 +357,7 @@ const resetListAdder = () => ({
const setupListAdder = (accountId: string) => (dispatch: AppDispatch, getState: () => RootState) => {
dispatch({
type: LIST_ADDER_SETUP,
account: getState().accounts.get(accountId),
account: selectAccount(getState(), accountId),
});
dispatch(fetchLists());
dispatch(fetchAccountLists(accountId));

Wyświetl plik

@ -1,3 +1,4 @@
import { selectAccount } from 'soapbox/selectors';
import KVStore from 'soapbox/storage/kv-store';
import { getAuthUserId, getAuthUserUrl } from 'soapbox/utils/auth';
@ -25,7 +26,9 @@ const getMeId = (state: RootState) => state.me || getAuthUserId(state);
const getMeUrl = (state: RootState) => {
const accountId = getMeId(state);
return state.accounts.get(accountId)?.url || getAuthUserUrl(state);
if (accountId) {
return selectAccount(state, accountId)?.url || getAuthUserUrl(state);
}
};
const getMeToken = (state: RootState) => {

Wyświetl plik

@ -7,6 +7,7 @@ import { openModal } from 'soapbox/actions/modals';
import OutlineBox from 'soapbox/components/outline-box';
import { Stack, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account-container';
import { selectAccount } from 'soapbox/selectors';
import toast from 'soapbox/toast';
import { isLocal } from 'soapbox/utils/accounts';
@ -42,8 +43,8 @@ const messages = defineMessages({
const deactivateUserModal = (intl: IntlShape, accountId: string, afterConfirm = () => {}) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const acct = state.accounts.get(accountId)!.acct;
const name = state.accounts.get(accountId)!.username;
const acct = selectAccount(state, accountId)!.acct;
const name = selectAccount(state, accountId)!.username;
const message = (
<Stack space={4}>
@ -75,7 +76,7 @@ const deactivateUserModal = (intl: IntlShape, accountId: string, afterConfirm =
const deleteUserModal = (intl: IntlShape, accountId: string, afterConfirm = () => {}) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const account = state.accounts.get(accountId)!;
const account = selectAccount(state, accountId)!;
const acct = account.acct;
const name = account.username;
const local = isLocal(account);
@ -115,8 +116,8 @@ const deleteUserModal = (intl: IntlShape, accountId: string, afterConfirm = () =
const toggleStatusSensitivityModal = (intl: IntlShape, statusId: string, sensitive: boolean, afterConfirm = () => {}) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const accountId = state.statuses.get(statusId)!.account;
const acct = state.accounts.get(accountId)!.acct;
const accountId = state.statuses.get(statusId)!.account.id;
const acct = selectAccount(state, accountId)!.acct;
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/alert-triangle.svg'),
@ -136,8 +137,8 @@ const toggleStatusSensitivityModal = (intl: IntlShape, statusId: string, sensiti
const deleteStatusModal = (intl: IntlShape, statusId: string, afterConfirm = () => {}) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const accountId = state.statuses.get(statusId)!.account;
const acct = state.accounts.get(accountId)!.acct;
const accountId = state.statuses.get(statusId)!.account.id;
const acct = selectAccount(state, accountId)!.acct;
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/trash.svg'),

Wyświetl plik

@ -10,6 +10,7 @@ import LinkHeader from 'http-link-header';
import { createSelector } from 'reselect';
import * as BuildConfig from 'soapbox/build-config';
import { selectAccount } from 'soapbox/selectors';
import { RootState } from 'soapbox/store';
import { getAccessToken, getAppToken, isURL, parseBaseURL } from 'soapbox/utils/auth';
@ -46,7 +47,7 @@ const maybeParseJSON = (data: string) => {
};
const getAuthBaseURL = createSelector([
(state: RootState, me: string | false | null) => state.accounts.getIn([me, 'url']),
(state: RootState, me: string | false | null) => me ? selectAccount(state, me)?.url : undefined,
(state: RootState, _me: string | false | null) => state.auth.me,
], (accountUrl, authUserUrl) => {
const baseURL = parseBaseURL(accountUrl) || parseBaseURL(authUserUrl);

Wyświetl plik

@ -7,6 +7,7 @@ import { fetchUsers } from 'soapbox/actions/admin';
import { Widget } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account-container';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { selectAccount } from 'soapbox/selectors';
import { compareId } from 'soapbox/utils/comparators';
const messages = defineMessages({
@ -24,7 +25,7 @@ const LatestAccountsPanel: React.FC<ILatestAccountsPanel> = ({ limit = 5 }) => {
const dispatch = useAppDispatch();
const accountIds = useAppSelector<ImmutableOrderedSet<string>>((state) => state.admin.get('latestUsers').take(limit));
const hasDates = useAppSelector((state) => accountIds.every(id => !!state.accounts.getIn([id, 'created_at'])));
const hasDates = useAppSelector((state) => accountIds.every(id => !!selectAccount(state, id)?.created_at));
const [total, setTotal] = useState(accountIds.size);

Wyświetl plik

@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
import { FormattedList, FormattedMessage } from 'react-intl';
import { openModal } from 'soapbox/actions/modals';
import { useAppDispatch, useAppSelector, useCompose, useFeatures } from 'soapbox/hooks';
import { useAppDispatch, useAppSelector, useCompose, useFeatures, useOwnAccount } from 'soapbox/hooks';
import { statusToMentionsAccountIdsArray } from 'soapbox/reducers/compose';
import { makeGetStatus } from 'soapbox/selectors';
import { isPubkey } from 'soapbox/utils/nostr';
@ -21,7 +21,7 @@ const ReplyMentions: React.FC<IReplyMentions> = ({ composeId }) => {
const getStatus = useCallback(makeGetStatus(), []);
const status = useAppSelector<StatusEntity | null>(state => getStatus(state, { id: compose.in_reply_to! }));
const to = compose.to;
const account = useAppSelector((state) => state.accounts.get(state.me));
const { account } = useOwnAccount();
if (!features.explicitAddressing || !status || !to) {
return null;

Wyświetl plik

@ -4,6 +4,7 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { expandSearch, setFilter, setSearchAccount } from 'soapbox/actions/search';
import { fetchTrendingStatuses } from 'soapbox/actions/trending-statuses';
import { useAccount } from 'soapbox/api/hooks';
import Hashtag from 'soapbox/components/hashtag';
import IconButton from 'soapbox/components/icon-button';
import ScrollableList from 'soapbox/components/scrollable-list';
@ -38,8 +39,8 @@ const SearchResults = () => {
const trends = useAppSelector((state) => state.trends.items);
const submitted = useAppSelector((state) => state.search.submitted);
const selectedFilter = useAppSelector((state) => state.search.filter);
const filterByAccount = useAppSelector((state) => state.search.accountId);
const account = useAppSelector((state) => state.accounts.get(filterByAccount)?.acct);
const filterByAccount = useAppSelector((state) => state.search.accountId || undefined);
const { account } = useAccount(filterByAccount);
const handleLoadMore = () => dispatch(expandSearch(selectedFilter));
@ -205,7 +206,7 @@ const SearchResults = () => {
<FormattedMessage
id='search_results.filter_message'
defaultMessage='You are searching for posts from @{acct}.'
values={{ acct: <strong className='break-words'>{account}</strong> }}
values={{ acct: <strong className='break-words'>{account?.acct}</strong> }}
/>
</Text>
</HStack>

Wyświetl plik

@ -3,10 +3,11 @@ import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { useAppSelector, useCompose } from 'soapbox/hooks';
import { selectOwnAccount } from 'soapbox/selectors';
import Warning from '../components/warning';
const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\w*[a-zA-Z·]\w*)/i;
const APPROX_HASHTAG_RE = /(?:^|[^/)\w])#(\w*[a-zA-Z·]\w*)/i;
interface IWarningWrapper {
composeId: string
@ -15,25 +16,50 @@ interface IWarningWrapper {
const WarningWrapper: React.FC<IWarningWrapper> = ({ composeId }) => {
const compose = useCompose(composeId);
const me = useAppSelector((state) => state.me);
const needsLockWarning = useAppSelector((state) => compose.privacy === 'private' && !state.accounts.get(me)!.locked);
const needsLockWarning = useAppSelector((state) => compose.privacy === 'private' && !selectOwnAccount(state)!.locked);
const hashtagWarning = (compose.privacy !== 'public' && compose.privacy !== 'group') && APPROX_HASHTAG_RE.test(compose.text);
const directMessageWarning = compose.privacy === 'direct';
if (needsLockWarning) {
return <Warning message={<FormattedMessage id='compose_form.lock_disclaimer' defaultMessage='Your account is not {locked}. Anyone can follow you to view your follower-only posts.' values={{ locked: <Link to='/settings/profile'><FormattedMessage id='compose_form.lock_disclaimer.lock' defaultMessage='locked' /></Link> }} />} />;
return (
<Warning
message={(
<FormattedMessage
id='compose_form.lock_disclaimer'
defaultMessage='Your account is not {locked}. Anyone can follow you to view your follower-only posts.'
values={{
locked: (
<Link to='/settings/profile'>
<FormattedMessage id='compose_form.lock_disclaimer.lock' defaultMessage='locked' />
</Link>
),
}}
/>
)}
/>
);
}
if (hashtagWarning) {
return <Warning message={<FormattedMessage id='compose_form.hashtag_warning' defaultMessage="This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag." />} />;
return (
<Warning
message={(
<FormattedMessage
id='compose_form.hashtag_warning'
defaultMessage="This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag."
/>
)}
/>
);
}
if (directMessageWarning) {
const message = (
<span>
<FormattedMessage id='compose_form.direct_message_warning' defaultMessage='This post will only be sent to the mentioned users.' />
{/* <a href='/about/tos' target='_blank'><FormattedMessage id='compose_form.direct_message_warning_learn_more' defaultMessage='Learn more' /></a> */}
<FormattedMessage
id='compose_form.direct_message_warning'
defaultMessage='This post will only be sent to the mentioned users.'
/>
</span>
);

Wyświetl plik

@ -4,6 +4,7 @@ import { useHistory } from 'react-router-dom';
import { markConversationRead } from 'soapbox/actions/conversations';
import StatusContainer from 'soapbox/containers/status-container';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { selectAccount } from 'soapbox/selectors';
interface IConversation {
conversationId: string
@ -19,7 +20,7 @@ const Conversation: React.FC<IConversation> = ({ conversationId, onMoveUp, onMov
const conversation = state.conversations.items.find(x => x.id === conversationId)!;
return {
accounts: conversation.accounts.map((accountId: string) => state.accounts.get(accountId)!),
accounts: conversation.accounts.map((accountId: string) => selectAccount(state, accountId)!),
unread: conversation.unread,
lastStatusId: conversation.last_status || null,
};

Wyświetl plik

@ -7,6 +7,7 @@ import MissingIndicator from 'soapbox/components/missing-indicator';
import StatusList from 'soapbox/components/status-list';
import { Column } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { selectOwnAccount } from 'soapbox/selectors';
const messages = defineMessages({
heading: { id: 'column.pins', defaultMessage: 'Pinned posts' },
@ -17,7 +18,7 @@ const PinnedStatuses = () => {
const dispatch = useAppDispatch();
const { username } = useParams<{ username: string }>();
const meUsername = useAppSelector((state) => state.accounts.get(state.me)?.username || '');
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);

Wyświetl plik

@ -110,14 +110,8 @@ const MediaModal: React.FC<IMediaModal> = (props) => {
const handleStatusClick: React.MouseEventHandler = e => {
if (status && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
dispatch((_, getState) => {
const account = typeof status.account === 'string' ? getState().accounts.get(status.account) : status.account;
if (!account) return;
history.push(`/@${account.acct}/posts/${status?.id}`);
onClose();
});
history.push(`/@${status.account.acct}/posts/${status?.id}`);
onClose();
}
};

Wyświetl plik

@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import { Modal } from 'soapbox/components/ui';
import { useAppSelector, useCompose } from 'soapbox/hooks';
import { useAppSelector, useCompose, useOwnAccount } from 'soapbox/hooks';
import { statusToMentionsAccountIdsArray } from 'soapbox/reducers/compose';
import { makeGetStatus } from 'soapbox/selectors';
@ -20,7 +20,7 @@ const ReplyMentionsModal: React.FC<IReplyMentionsModal> = ({ composeId, onClose
const getStatus = useCallback(makeGetStatus(), []);
const status = useAppSelector<StatusEntity | null>(state => getStatus(state, { id: compose.in_reply_to! }));
const account = useAppSelector((state) => state.accounts.get(state.me));
const { account } = useOwnAccount();
const mentions = statusToMentionsAccountIdsArray(status!, account!);
const author = (status?.account as AccountEntity).id;

Wyświetl plik

@ -5,6 +5,7 @@ import { useHistory } from 'react-router-dom';
import { remoteInteraction } from 'soapbox/actions/interactions';
import { Button, Form, Input, Modal, Stack, Text } from 'soapbox/components/ui';
import { useAppSelector, useAppDispatch, useFeatures, useInstance, useRegistrationStatus } from 'soapbox/hooks';
import { selectAccount } from 'soapbox/selectors';
import toast from 'soapbox/toast';
const messages = defineMessages({
@ -32,7 +33,7 @@ const UnauthorizedModal: React.FC<IUnauthorizedModal> = ({ action, onClose, acco
const instance = useInstance();
const { isOpen } = useRegistrationStatus();
const username = useAppSelector(state => state.accounts.get(accountId)?.display_name);
const username = useAppSelector(state => selectAccount(state, accountId!)?.display_name);
const features = useFeatures();
const [account, setAccount] = useState('');

Wyświetl plik

@ -1,29 +0,0 @@
import { Map as ImmutableMap, Record as ImmutableRecord } from 'immutable';
import { ACCOUNT_IMPORT } from 'soapbox/actions/importer';
import reducer from '../accounts';
describe('accounts reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {} as any)).toEqual(ImmutableMap());
});
describe('ACCOUNT_IMPORT', () => {
it('parses the account as a Record', () => {
const account = require('soapbox/__fixtures__/pleroma-account.json');
const action = { type: ACCOUNT_IMPORT, account };
const result = reducer(undefined, action).get('9v5bmRalQvjOy0ECcC');
expect(ImmutableRecord.isRecord(result)).toBe(true);
});
it('minifies a moved account', () => {
const account = require('soapbox/__fixtures__/account-moved.json');
const action = { type: ACCOUNT_IMPORT, account };
const result = reducer(undefined, action).get('106801667066418367');
expect(result?.moved).toBe('107945464165013501');
});
});
});

Wyświetl plik

@ -6,7 +6,6 @@ describe('root reducer', () => {
it('should return the initial state', () => {
const result = reducer(undefined, {} as any);
expect(ImmutableRecord.isRecord(result)).toBe(true);
expect(result.accounts.get('')).toBe(undefined);
expect(result.instance.version).toEqual('0.0.0');
});
});

Wyświetl plik

@ -1,12 +1,9 @@
import { Record as ImmutableRecord } from 'immutable';
import { combineReducers } from 'redux-immutable';
import { createSelector } from 'reselect';
import { AUTH_LOGGED_OUT } from 'soapbox/actions/auth';
import * as BuildConfig from 'soapbox/build-config';
import { Entities } from 'soapbox/entity-store/entities';
import entities from 'soapbox/entity-store/reducer';
import { immutableizeStore, type LegacyStore } from 'soapbox/utils/legacy';
import account_notes from './account-notes';
import accounts_meta from './accounts-meta';
@ -70,12 +67,7 @@ import trends from './trends';
import user_lists from './user-lists';
import verification from './verification';
import type { AnyAction, Reducer } from 'redux';
import type { EntityStore } from 'soapbox/entity-store/types';
import type { Account } from 'soapbox/schemas';
const reducers = {
accounts: ((state: any = {}) => state) as (state: any) => EntityStore<Account> & LegacyStore<Account>,
account_notes,
accounts_meta,
admin,
@ -175,19 +167,4 @@ const rootReducer: typeof appReducer = (state, action) => {
}
};
type InferState<R> = R extends Reducer<infer S> ? S : never;
const accountsSelector = createSelector(
(state: InferState<typeof appReducer>) => state.entities[Entities.ACCOUNTS]?.store as EntityStore<Account> || {},
(accounts) => immutableizeStore<Account, EntityStore<Account>>(accounts),
);
const extendedRootReducer = (
state: InferState<typeof appReducer>,
action: AnyAction,
): ReturnType<typeof rootReducer> => {
const extendedState = rootReducer(state, action);
return extendedState.set('accounts', accountsSelector(extendedState));
};
export default extendedRootReducer as Reducer<ReturnType<typeof extendedRootReducer>>;
export default rootReducer;

Wyświetl plik

@ -14,13 +14,25 @@ import ConfigDB from 'soapbox/utils/config-db';
import { getFeatures } from 'soapbox/utils/features';
import { shouldFilter } from 'soapbox/utils/timelines';
import type { EntityStore } from 'soapbox/entity-store/types';
import type { ContextType } from 'soapbox/normalizers/filter';
import type { ReducerChat } from 'soapbox/reducers/chats';
import type { Account as AccountSchema } from 'soapbox/schemas';
import type { RootState } from 'soapbox/store';
import type { Account, Filter as FilterEntity, Notification, Status } from 'soapbox/types/entities';
const normalizeId = (id: any): string => typeof id === 'string' ? id : '';
export function selectAccount(state: RootState, accountId: string) {
return state.entities[Entities.ACCOUNTS]?.store[accountId] as AccountSchema | undefined;
}
export function selectOwnAccount(state: RootState) {
if (state.me) {
return selectAccount(state, state.me);
}
}
const getAccountBase = (state: RootState, id: string) => state.entities[Entities.ACCOUNTS]?.store[id] as Account | undefined;
const getAccountRelationship = (state: RootState, id: string) => state.relationships.get(id);
@ -144,8 +156,8 @@ export const makeGetStatus = () => {
export const makeGetNotification = () => {
return createSelector([
(_state: RootState, notification: Notification) => notification,
(state: RootState, notification: Notification) => state.accounts.get(normalizeId(notification.account)),
(state: RootState, notification: Notification) => state.accounts.get(normalizeId(notification.target)),
(state: RootState, notification: Notification) => selectAccount(state, normalizeId(notification.account)),
(state: RootState, notification: Notification) => selectAccount(state, normalizeId(notification.target)),
(state: RootState, notification: Notification) => state.statuses.get(normalizeId(notification.status)),
], (notification, account, target, status) => {
return notification.merge({
@ -193,7 +205,7 @@ export const makeGetChat = () => {
return createSelector(
[
(state: RootState, { id }: APIChat) => state.chats.items.get(id) as ReducerChat,
(state: RootState, { id }: APIChat) => state.accounts.get(state.chats.items.getIn([id, 'account'])),
(state: RootState, { id }: APIChat) => selectAccount(state, state.chats.items.getIn([id, 'account']) as string),
(state: RootState, { last_message }: APIChat) => state.chat_messages.get(last_message),
],
@ -216,10 +228,8 @@ export const makeGetReport = () => {
return createSelector(
[
(state: RootState, id: string) => state.admin.reports.get(id),
(state: RootState, id: string) => state.accounts.get(state.admin.reports.get(id)?.account || ''),
(state: RootState, id: string) => state.accounts.get(state.admin.reports.get(id)?.target_account || ''),
// (state: RootState, id: string) => state.accounts.get(state.admin.reports.get(id)?.action_taken_by_account || ''),
// (state: RootState, id: string) => state.accounts.get(state.admin.reports.get(id)?.assigned_account || ''),
(state: RootState, id: string) => selectAccount(state, state.admin.reports.get(id)?.account || ''),
(state: RootState, id: string) => selectAccount(state, state.admin.reports.get(id)?.target_account || ''),
(state: RootState, id: string) => ImmutableList(fromJS(state.admin.reports.get(id)?.statuses)).map(
statusId => state.statuses.get(normalizeId(statusId)))
.filter((s: any) => s)
@ -255,7 +265,7 @@ const getAuthUserIds = createSelector([
export const makeGetOtherAccounts = () => {
return createSelector([
(state: RootState) => state.accounts,
(state: RootState) => state.entities[Entities.ACCOUNTS]?.store as EntityStore<AccountSchema>,
getAuthUserIds,
(state: RootState) => state.me,
],
@ -263,7 +273,7 @@ export const makeGetOtherAccounts = () => {
return authUserIds
.reduce((list: ImmutableList<any>, id: string) => {
if (id === me) return list;
const account = accounts.get(id);
const account = accounts[id];
return account ? list.push(account) : list;
}, ImmutableList());
});
@ -276,10 +286,11 @@ const getSimplePolicy = createSelector([
return instancePolicy.merge(ConfigDB.toSimplePolicy(configs));
});
const getRemoteInstanceFavicon = (state: RootState, host: string) => (
(state.accounts.find(account => getDomain(account) === host) || ImmutableMap())
.getIn(['pleroma', 'favicon'])
);
const getRemoteInstanceFavicon = (state: RootState, host: string) => {
const accounts = state.entities[Entities.ACCOUNTS]?.store as EntityStore<AccountSchema>;
const account = Object.entries(accounts).find(([_, account]) => account && getDomain(account) === host)?.[1];
return account?.pleroma?.favicon;
};
const getRemoteInstanceFederation = (state: RootState, host: string) => (
getSimplePolicy(state)

Wyświetl plik

@ -1,5 +1,7 @@
import { List as ImmutableList } from 'immutable';
import { selectAccount, selectOwnAccount } from 'soapbox/selectors';
import type { RootState } from 'soapbox/store';
export const validId = (id: any) => typeof id === 'string' && id !== 'null' && id !== 'undefined';
@ -22,10 +24,7 @@ export const parseBaseURL = (url: any) => {
}
};
export const getLoggedInAccount = (state: RootState) => {
const me = state.me;
return state.accounts.get(me);
};
export const getLoggedInAccount = (state: RootState) => selectOwnAccount(state);
export const isLoggedIn = (getState: () => RootState) => {
return validId(getState().me);
@ -35,7 +34,7 @@ export const getAppToken = (state: RootState) => state.auth.app.access_token as
export const getUserToken = (state: RootState, accountId?: string | false | null) => {
if (!accountId) return;
const accountUrl = state.accounts[accountId]?.url;
const accountUrl = selectAccount(state, accountId)?.url;
if (!accountUrl) return;
return state.auth.users.get(accountUrl)?.access_token;
};
@ -66,3 +65,5 @@ export const getAuthUserUrl = (state: RootState) => {
/** Get the VAPID public key. */
export const getVapidKey = (state: RootState) =>
(state.auth.app.vapid_key || state.instance.pleroma.get('vapid_public_key')) as string;
export const getMeUrl = (state: RootState) => selectOwnAccount(state)?.url;

Wyświetl plik

@ -6,6 +6,7 @@
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
import * as BuildConfig from 'soapbox/build-config';
import { isPrerendered } from 'soapbox/precheck';
import { selectOwnAccount } from 'soapbox/selectors';
import { isURL } from 'soapbox/utils/auth';
import type { RootState } from 'soapbox/store';
@ -39,6 +40,6 @@ const getHost = (url: any): string => {
/** Get the baseURL of the instance. */
export const getBaseURL = (state: RootState): string => {
const account = state.accounts.get(state.me);
const account = selectOwnAccount(state);
return isURL(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : getHost(account?.url);
};