From e01ee84ee9a2e16355b8cbfa605288c807f49311 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 21 Jun 2023 16:20:07 -0500 Subject: [PATCH] ProfileHoverCard: use useAccount hook, add usePatronUser hook --- app/soapbox/api/hooks/accounts/useAccount.ts | 17 ++++++++------- .../api/hooks/accounts/usePatronUser.ts | 18 ++++++++++++++++ app/soapbox/api/hooks/index.ts | 1 + app/soapbox/components/profile-hover-card.tsx | 21 +++++++++---------- app/soapbox/entity-store/entities.ts | 1 + app/soapbox/schemas/index.ts | 1 + app/soapbox/schemas/patron.ts | 15 +++++++++++++ 7 files changed, 56 insertions(+), 18 deletions(-) create mode 100644 app/soapbox/api/hooks/accounts/usePatronUser.ts create mode 100644 app/soapbox/schemas/patron.ts diff --git a/app/soapbox/api/hooks/accounts/useAccount.ts b/app/soapbox/api/hooks/accounts/useAccount.ts index 2442ad642..222a7c94f 100644 --- a/app/soapbox/api/hooks/accounts/useAccount.ts +++ b/app/soapbox/api/hooks/accounts/useAccount.ts @@ -3,22 +3,25 @@ import { useEntity } from 'soapbox/entity-store/hooks'; import { useApi } from 'soapbox/hooks/useApi'; import { type Account, accountSchema } from 'soapbox/schemas'; - import { useRelationships } from './useRelationships'; -function useAccount(id: string) { +function useAccount(accountId?: string) { const api = useApi(); const { entity: account, ...result } = useEntity( - [Entities.ACCOUNTS, id], - () => api.get(`/api/v1/accounts/${id}`), - { schema: accountSchema }, + [Entities.ACCOUNTS, accountId || ''], + () => api.get(`/api/v1/accounts/${accountId}`), + { schema: accountSchema, enabled: !!accountId }, ); - const { relationships, isLoading } = useRelationships([account?.id as string]); + const { + relationships, + isLoading: isRelationshipLoading, + } = useRelationships(accountId ? [accountId] : []); return { ...result, - isLoading: result.isLoading || isLoading, + isLoading: result.isLoading, + isRelationshipLoading, account: account ? { ...account, relationship: relationships[0] || null } : undefined, }; } diff --git a/app/soapbox/api/hooks/accounts/usePatronUser.ts b/app/soapbox/api/hooks/accounts/usePatronUser.ts new file mode 100644 index 000000000..283f02b3d --- /dev/null +++ b/app/soapbox/api/hooks/accounts/usePatronUser.ts @@ -0,0 +1,18 @@ +import { Entities } from 'soapbox/entity-store/entities'; +import { useEntity } from 'soapbox/entity-store/hooks'; +import { useApi } from 'soapbox/hooks/useApi'; +import { type PatronUser, patronUserSchema } from 'soapbox/schemas'; + +function usePatronUser(url?: string) { + const api = useApi(); + + const { entity: patronUser, ...result } = useEntity( + [Entities.PATRON_USERS, url || ''], + () => api.get(`/api/patron/v1/accounts/${encodeURIComponent(url!)}`), + { schema: patronUserSchema, enabled: !!url }, + ); + + return { patronUser, ...result }; +} + +export { usePatronUser }; \ No newline at end of file diff --git a/app/soapbox/api/hooks/index.ts b/app/soapbox/api/hooks/index.ts index ade03f799..e411e2133 100644 --- a/app/soapbox/api/hooks/index.ts +++ b/app/soapbox/api/hooks/index.ts @@ -3,6 +3,7 @@ * Accounts */ export { useAccount } from './accounts/useAccount'; +export { usePatronUser } from './accounts/usePatronUser'; /** * Groups diff --git a/app/soapbox/components/profile-hover-card.tsx b/app/soapbox/components/profile-hover-card.tsx index d0c8a93d4..98487f4ac 100644 --- a/app/soapbox/components/profile-hover-card.tsx +++ b/app/soapbox/components/profile-hover-card.tsx @@ -9,32 +9,30 @@ import { closeProfileHoverCard, updateProfileHoverCard, } from 'soapbox/actions/profile-hover-card'; +import { useAccount, usePatronUser } from 'soapbox/api/hooks'; import Badge from 'soapbox/components/badge'; import ActionButton from 'soapbox/features/ui/components/action-button'; import BundleContainer from 'soapbox/features/ui/containers/bundle-container'; import { UserPanel } from 'soapbox/features/ui/util/async-components'; import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; -import { makeGetAccount } from 'soapbox/selectors'; import { isLocal } from 'soapbox/utils/accounts'; import { showProfileHoverCard } from './hover-ref-wrapper'; import { Card, CardBody, HStack, Icon, Stack, Text } from './ui'; +import type { Account, PatronUser } from 'soapbox/schemas'; import type { AppDispatch } from 'soapbox/store'; -import type { Account } from 'soapbox/types/entities'; -const getAccount = makeGetAccount(); - -const getBadges = (account: Account): JSX.Element[] => { +const getBadges = (account?: Account, patronUser?: PatronUser): JSX.Element[] => { const badges = []; - if (account.admin) { + if (account?.admin) { badges.push(); - } else if (account.moderator) { + } else if (account?.moderator) { badges.push(); } - if (account.getIn(['patron', 'is_patron'])) { + if (patronUser?.is_patron) { badges.push(); } @@ -67,9 +65,10 @@ export const ProfileHoverCard: React.FC = ({ visible = true } const me = useAppSelector(state => state.me); const accountId: string | undefined = useAppSelector(state => state.profile_hover_card.accountId || undefined); - const account = useAppSelector(state => accountId && getAccount(state, accountId)); + const { account } = useAccount(accountId); + const { patronUser } = usePatronUser(account?.url); const targetRef = useAppSelector(state => state.profile_hover_card.ref?.current); - const badges = account ? getBadges(account) : []; + const badges = getBadges(account, patronUser); useEffect(() => { if (accountId) dispatch(fetchRelationships([accountId])); @@ -112,7 +111,7 @@ export const ProfileHoverCard: React.FC = ({ visible = true } {Component => ( } badges={badges} /> diff --git a/app/soapbox/entity-store/entities.ts b/app/soapbox/entity-store/entities.ts index 9878cbbf2..b8129940e 100644 --- a/app/soapbox/entity-store/entities.ts +++ b/app/soapbox/entity-store/entities.ts @@ -4,6 +4,7 @@ export enum Entities { GROUP_MEMBERSHIPS = 'GroupMemberships', GROUP_RELATIONSHIPS = 'GroupRelationships', GROUP_TAGS = 'GroupTags', + PATRON_USERS = 'PatronUsers', RELATIONSHIPS = 'Relationships', STATUSES = 'Statuses' } \ No newline at end of file diff --git a/app/soapbox/schemas/index.ts b/app/soapbox/schemas/index.ts index 1fa8ac5b4..2c99ef8b8 100644 --- a/app/soapbox/schemas/index.ts +++ b/app/soapbox/schemas/index.ts @@ -10,6 +10,7 @@ export { groupRelationshipSchema, type GroupRelationship } from './group-relatio export { groupTagSchema, type GroupTag } from './group-tag'; export { mentionSchema, type Mention } from './mention'; export { notificationSchema, type Notification } from './notification'; +export { patronUserSchema, type PatronUser } from './patron'; export { pollSchema, type Poll, type PollOption } from './poll'; export { relationshipSchema, type Relationship } from './relationship'; export { statusSchema, type Status } from './status'; diff --git a/app/soapbox/schemas/patron.ts b/app/soapbox/schemas/patron.ts new file mode 100644 index 000000000..c7aa5a569 --- /dev/null +++ b/app/soapbox/schemas/patron.ts @@ -0,0 +1,15 @@ +import { z } from 'zod'; + +const patronUserSchema = z.object({ + is_patron: z.boolean().catch(false), + url: z.string().url(), +}).transform((patron) => { + return { + id: patron.url, + ...patron, + }; +}); + +type PatronUser = z.infer; + +export { patronUserSchema, type PatronUser }; \ No newline at end of file