Add useAccountLookup hook, fix useRelationships
This commit is contained in:
parent
9f53a81fa1
commit
ec8177d578
16 changed files with 61 additions and 32 deletions
|
@ -22,9 +22,9 @@ import { createStatus } from './statuses';
|
|||
|
||||
import type { AutoSuggestion } from 'soapbox/components/autosuggest-input';
|
||||
import type { Emoji } from 'soapbox/features/emoji';
|
||||
import type { Group } from 'soapbox/schemas';
|
||||
import type { Account, Group } from 'soapbox/schemas';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { Account, APIEntity, Status, Tag } from 'soapbox/types/entities';
|
||||
import type { APIEntity, Status, Tag } from 'soapbox/types/entities';
|
||||
import type { History } from 'soapbox/types/history';
|
||||
|
||||
const { CancelToken, isCancel } = axios;
|
||||
|
|
|
@ -8,8 +8,9 @@ import { importFetchedAccounts } from './importer';
|
|||
import { openModal } from './modals';
|
||||
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { Account as AccountEntity } from 'soapbox/schemas';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { APIEntity, Account as AccountEntity } from 'soapbox/types/entities';
|
||||
import type { APIEntity } from 'soapbox/types/entities';
|
||||
|
||||
const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST';
|
||||
const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS';
|
||||
|
|
|
@ -9,10 +9,11 @@ function useAccount(accountId?: string) {
|
|||
const api = useApi();
|
||||
|
||||
const { entity: account, ...result } = useEntity<Account>(
|
||||
[Entities.ACCOUNTS, accountId || ''],
|
||||
[Entities.ACCOUNTS, accountId!],
|
||||
() => api.get(`/api/v1/accounts/${accountId}`),
|
||||
{ schema: accountSchema, enabled: !!accountId },
|
||||
);
|
||||
|
||||
const {
|
||||
relationships,
|
||||
isLoading: isRelationshipLoading,
|
||||
|
|
31
app/soapbox/api/hooks/accounts/useAccountLookup.ts
Normal file
31
app/soapbox/api/hooks/accounts/useAccountLookup.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { Entities } from 'soapbox/entity-store/entities';
|
||||
import { useEntityLookup } from 'soapbox/entity-store/hooks';
|
||||
import { useApi } from 'soapbox/hooks/useApi';
|
||||
import { type Account, accountSchema } from 'soapbox/schemas';
|
||||
|
||||
import { useRelationships } from './useRelationships';
|
||||
|
||||
function useAccountLookup(acct?: string) {
|
||||
const api = useApi();
|
||||
|
||||
const { entity: account, ...result } = useEntityLookup<Account>(
|
||||
Entities.ACCOUNTS,
|
||||
(account) => account.acct === acct,
|
||||
() => api.get(`/api/v1/accounts/lookup?acct=${acct}`),
|
||||
{ schema: accountSchema, enabled: !!acct },
|
||||
);
|
||||
|
||||
const {
|
||||
relationships,
|
||||
isLoading: isRelationshipLoading,
|
||||
} = useRelationships(account ? [account.id] : []);
|
||||
|
||||
return {
|
||||
...result,
|
||||
isLoading: result.isLoading,
|
||||
isRelationshipLoading,
|
||||
account: account ? { ...account, relationship: relationships[0] || null } : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export { useAccountLookup };
|
|
@ -7,10 +7,11 @@ import { type Relationship, relationshipSchema } from 'soapbox/schemas';
|
|||
function useRelationships(ids: string[]) {
|
||||
const api = useApi();
|
||||
const { isLoggedIn } = useLoggedIn();
|
||||
const q = ids.map(id => `id[]=${id}`).join('&');
|
||||
|
||||
const { entities: relationships, ...result } = useEntities<Relationship>(
|
||||
[Entities.RELATIONSHIPS],
|
||||
() => api.get(`/api/v1/accounts/relationships?${ids.map(id => `id[]=${id}`).join('&')}`),
|
||||
[Entities.RELATIONSHIPS, q],
|
||||
() => api.get(`/api/v1/accounts/relationships?${q}`),
|
||||
{ schema: relationshipSchema, enabled: isLoggedIn && ids.filter(Boolean).length > 0 },
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
// Accounts
|
||||
export { useAccount } from './accounts/useAccount';
|
||||
export { useAccountLookup } from './accounts/useAccountLookup';
|
||||
export { useFollow } from './accounts/useFollow';
|
||||
export { useRelationships } from './accounts/useRelationships';
|
||||
export { usePatronUser } from './accounts/usePatronUser';
|
||||
|
|
|
@ -15,10 +15,9 @@ import { Avatar, Emoji, HStack, Icon, IconButton, Stack, Text } from './ui';
|
|||
|
||||
import type { StatusApprovalStatus } from 'soapbox/normalizers/status';
|
||||
import type { Account as AccountSchema } from 'soapbox/schemas';
|
||||
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
||||
|
||||
interface IInstanceFavicon {
|
||||
account: AccountEntity | AccountSchema
|
||||
account: AccountSchema
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
|
@ -68,7 +67,7 @@ const ProfilePopper: React.FC<IProfilePopper> = ({ condition, wrapper, children
|
|||
};
|
||||
|
||||
export interface IAccount {
|
||||
account: AccountEntity | AccountSchema
|
||||
account: AccountSchema
|
||||
action?: React.ReactElement
|
||||
actionAlignment?: 'center' | 'top'
|
||||
actionIcon?: string
|
||||
|
|
|
@ -5,7 +5,7 @@ import Account from 'soapbox/components/account';
|
|||
import Icon from 'soapbox/components/icon';
|
||||
import { HStack, Text } from 'soapbox/components/ui';
|
||||
|
||||
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
||||
import type { Account as AccountEntity } from 'soapbox/schemas';
|
||||
|
||||
interface IMovedNote {
|
||||
from: AccountEntity
|
||||
|
|
|
@ -28,8 +28,8 @@ import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soap
|
|||
import { normalizeAttachment } from 'soapbox/normalizers';
|
||||
import { ChatKeys, useChats } from 'soapbox/queries/chats';
|
||||
import { queryClient } from 'soapbox/queries/client';
|
||||
import { Account } from 'soapbox/schemas';
|
||||
import toast from 'soapbox/toast';
|
||||
import { Account } from 'soapbox/types/entities';
|
||||
import { isDefaultHeader, isLocal, isRemote } from 'soapbox/utils/accounts';
|
||||
import copy from 'soapbox/utils/copy';
|
||||
import { MASTODON, parseVersion } from 'soapbox/utils/features';
|
||||
|
@ -576,7 +576,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
|||
disabled={createAndNavigateToChat.isLoading}
|
||||
/>
|
||||
);
|
||||
} else if (account.getIn(['pleroma', 'accepts_chat_messages']) === true) {
|
||||
} else if (account.pleroma?.accepts_chat_messages) {
|
||||
return (
|
||||
<IconButton
|
||||
src={require('@tabler/icons/messages.svg')}
|
||||
|
|
|
@ -9,12 +9,12 @@ import {
|
|||
expandFollowers,
|
||||
fetchAccountByUsername,
|
||||
} from 'soapbox/actions/accounts';
|
||||
import { useAccountLookup } from 'soapbox/api/hooks';
|
||||
import MissingIndicator from 'soapbox/components/missing-indicator';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Column, Spinner } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
||||
import { findAccountByUsername } from 'soapbox/selectors';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.followers', defaultMessage: 'Followers' },
|
||||
|
@ -36,7 +36,7 @@ const Followers: React.FC<IFollowers> = (props) => {
|
|||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const username = props.params?.username || '';
|
||||
const account = useAppSelector(state => findAccountByUsername(state, username));
|
||||
const { account } = useAccountLookup(username);
|
||||
const isOwnAccount = username.toLowerCase() === ownAccount?.username?.toLowerCase();
|
||||
|
||||
const accountIds = useAppSelector(state => state.user_lists.followers.get(account!?.id)?.items || ImmutableOrderedSet<string>());
|
||||
|
|
|
@ -9,12 +9,12 @@ import {
|
|||
expandFollowing,
|
||||
fetchAccountByUsername,
|
||||
} from 'soapbox/actions/accounts';
|
||||
import { useAccountLookup } from 'soapbox/api/hooks';
|
||||
import MissingIndicator from 'soapbox/components/missing-indicator';
|
||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||
import { Column, Spinner } from 'soapbox/components/ui';
|
||||
import AccountContainer from 'soapbox/containers/account-container';
|
||||
import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
||||
import { findAccountByUsername } from 'soapbox/selectors';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.following', defaultMessage: 'Following' },
|
||||
|
@ -36,7 +36,7 @@ const Following: React.FC<IFollowing> = (props) => {
|
|||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const username = props.params?.username || '';
|
||||
const account = useAppSelector(state => findAccountByUsername(state, username));
|
||||
const { account } = useAccountLookup(username);
|
||||
const isOwnAccount = username.toLowerCase() === ownAccount?.username?.toLowerCase();
|
||||
|
||||
const accountIds = useAppSelector(state => state.user_lists.following.get(account!?.id)?.items || ImmutableOrderedSet<string>());
|
||||
|
|
|
@ -15,7 +15,6 @@ import { Button, HStack } from 'soapbox/components/ui';
|
|||
import { useAppDispatch, useFeatures, useLoggedIn } from 'soapbox/hooks';
|
||||
|
||||
import type { Account } from 'soapbox/schemas';
|
||||
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
||||
|
||||
const messages = defineMessages({
|
||||
block: { id: 'account.block', defaultMessage: 'Block @{name}' },
|
||||
|
@ -35,7 +34,7 @@ const messages = defineMessages({
|
|||
|
||||
interface IActionButton {
|
||||
/** Target account for the action. */
|
||||
account: AccountEntity | Account
|
||||
account: Account
|
||||
/** Type of action to prioritize, eg on Blocks and Mutes pages. */
|
||||
actionType?: 'muting' | 'blocking' | 'follow_request'
|
||||
/** Displays shorter text on the "Awaiting approval" button. */
|
||||
|
|
|
@ -177,6 +177,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
|||
};
|
||||
|
||||
const submitVerification = () => {
|
||||
if (!accessToken) return;
|
||||
// TODO: handle proper validation from Pepe -- expired vs invalid
|
||||
dispatch(reConfirmPhoneVerification(verificationCode))
|
||||
.then(() => {
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
import { Redirect, useHistory } from 'react-router-dom';
|
||||
|
||||
import { useAccountLookup } from 'soapbox/api/hooks';
|
||||
import { Column, Layout, Tabs } from 'soapbox/components/ui';
|
||||
import Header from 'soapbox/features/account/components/header';
|
||||
import LinkFooter from 'soapbox/features/ui/components/link-footer';
|
||||
|
@ -16,7 +17,6 @@ import {
|
|||
PinnedAccountsPanel,
|
||||
} from 'soapbox/features/ui/util/async-components';
|
||||
import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks';
|
||||
import { findAccountByUsername, makeGetAccount } from 'soapbox/selectors';
|
||||
import { getAcct, isLocal } from 'soapbox/utils/accounts';
|
||||
|
||||
interface IProfilePage {
|
||||
|
@ -26,21 +26,14 @@ interface IProfilePage {
|
|||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
/** Page to display a user's profile. */
|
||||
const ProfilePage: React.FC<IProfilePage> = ({ params, children }) => {
|
||||
const history = useHistory();
|
||||
const username = params?.username || '';
|
||||
|
||||
const account = useAppSelector(state => {
|
||||
if (username) {
|
||||
const account = findAccountByUsername(state, username);
|
||||
if (account) {
|
||||
return getAccount(state, account.id) || undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
const { account } = useAccountLookup(username);
|
||||
|
||||
console.log(account?.relationship);
|
||||
|
||||
const me = useAppSelector(state => state.me);
|
||||
const features = useFeatures();
|
||||
|
|
|
@ -48,7 +48,7 @@ export function connectStream(
|
|||
// If the WebSocket fails to be created, don't crash the whole page,
|
||||
// just proceed without a subscription.
|
||||
try {
|
||||
subscription = getStream(streamingAPIBaseURL!, accessToken, path, {
|
||||
subscription = getStream(streamingAPIBaseURL!, accessToken!, path, {
|
||||
connected() {
|
||||
if (pollingRefresh) {
|
||||
clearPolling();
|
||||
|
|
|
@ -34,8 +34,10 @@ export const isLoggedIn = (getState: () => RootState) => {
|
|||
export const getAppToken = (state: RootState) => state.auth.app.access_token as string;
|
||||
|
||||
export const getUserToken = (state: RootState, accountId?: string | false | null) => {
|
||||
const accountUrl = state.accounts.getIn([accountId, 'url']) as string;
|
||||
return state.auth.users.get(accountUrl)?.access_token as string;
|
||||
if (!accountId) return;
|
||||
const accountUrl = state.accounts[accountId]?.url;
|
||||
if (!accountUrl) return;
|
||||
return state.auth.users.get(accountUrl)?.access_token;
|
||||
};
|
||||
|
||||
export const getAccessToken = (state: RootState) => {
|
||||
|
|
Loading…
Reference in a new issue