diff --git a/src/components/EphemeralAccountSwitcher.tsx b/src/components/EphemeralAccountSwitcher.tsx index 0a159ad96..23ea0553c 100644 --- a/src/components/EphemeralAccountSwitcher.tsx +++ b/src/components/EphemeralAccountSwitcher.tsx @@ -18,7 +18,7 @@ import {useDialogControl} from '#/components/Dialog' import {SwitchAccountDialog} from '#/components/dialogs/SwitchAccount' import * as Menu from '#/components/Menu' import * as Prompt from '#/components/Prompt' -import {IS_NATIVE, IS_WEB, IS_WEB_TOUCH_DEVICE} from '#/env' +import {IS_WEB, IS_WEB_TOUCH_DEVICE} from '#/env' type AccountListItem = { account: SessionAccount @@ -37,24 +37,18 @@ export type SwitcherTriggerProps = { accessibilityRole: 'button' } -type SwitcherRequest = { - title: string - onSelectAccount: (account: SessionAccount) => void - accounts?: AccountListItem[] - resolveAccounts?: () => Promise -} - type EphemeralAccountSwitcherContextValue = { hasAlternateAccounts: boolean currentProfile?: AppBskyActorDefs.ProfileViewDetailed switcherAccounts: AccountListItem[] signOutPromptControl: ReturnType - getLongPressProps: (request: SwitcherRequest) => Pick< - SwitcherTriggerProps, - 'onLongPress' | 'accessibilityLabel' | 'accessibilityRole' - > } +type EphemeralAccountSwitcherData = Pick< + EphemeralAccountSwitcherContextValue, + 'currentProfile' | 'hasAlternateAccounts' | 'switcherAccounts' +> + const EphemeralAccountSwitcherContext = createContext(null) @@ -70,13 +64,23 @@ const noopTriggerProps: SwitcherTriggerProps = { accessibilityRole: 'button', } -function useEphemeralAccountSwitcherData(selectedDid: string) { +function useEphemeralAccountSwitcherData( + selectedDid: string, + currentProfileFromBatch = false, +) { const {accounts} = useSession() - const {data: currentProfile} = useProfileQuery({did: selectedDid}) + const {data: currentProfileQuery} = useProfileQuery({ + did: currentProfileFromBatch ? undefined : selectedDid, + }) const {data} = useProfilesQuery({ - handles: accounts.map(acc => acc.did), + handles: accounts + .filter(account => currentProfileFromBatch || account.did !== selectedDid) + .map(account => account.did), }) const profiles = data?.profiles + const currentProfile = currentProfileFromBatch + ? profiles?.find(profile => profile.did === selectedDid) + : currentProfileQuery const switcherAccounts = useMemo( () => @@ -96,118 +100,24 @@ function useEphemeralAccountSwitcherData(selectedDid: string) { } } -export function EphemeralAccountSwitcherScope({ - selectedDid, +function EphemeralAccountSwitcherProvider({ + data: {switcherAccounts, hasAlternateAccounts, currentProfile}, + signOutPromptControl, children, }: { - selectedDid: string + data: EphemeralAccountSwitcherData + signOutPromptControl: ReturnType children: React.ReactNode }) { - const {t: l} = useLingui() - const {switcherAccounts, hasAlternateAccounts, currentProfile} = - useEphemeralAccountSwitcherData(selectedDid) - const menuControl = Menu.useMenuControl() - const signOutPromptControl = Prompt.usePromptControl() - const dismissGuardRef = useRef(false) - const [activeRequest, setActiveRequest] = useState( - null, - ) - const [resolvedAccounts, setResolvedAccounts] = useState< - AccountListItem[] | null - >(null) - const [isResolvingAccounts, setIsResolvingAccounts] = useState(false) - - const openMenuControl = useCallback(() => { - if (IS_WEB && !IS_WEB_TOUCH_DEVICE) { - dismissGuardRef.current = true - menuControl.open() - - const releaseGuard = () => { - requestAnimationFrame(() => { - dismissGuardRef.current = false - }) - } - window.addEventListener('pointerup', releaseGuard, {once: true}) - window.addEventListener('pointercancel', releaseGuard, {once: true}) - return - } - menuControl.open() - }, [menuControl]) - - const openSwitcher = useCallback( - (request: SwitcherRequest) => { - setActiveRequest(request) - - if (request.resolveAccounts) { - setResolvedAccounts(null) - setIsResolvingAccounts(true) - openMenuControl() - void request.resolveAccounts().then(accounts => { - setResolvedAccounts(accounts) - setIsResolvingAccounts(false) - if (accounts.length === 0) { - menuControl.close() - } - }).catch(() => { - setIsResolvingAccounts(false) - menuControl.close() - }) - return - } - - const accounts = request.accounts ?? switcherAccounts - if (accounts.length === 0) return - setResolvedAccounts(accounts) - openMenuControl() - }, - [switcherAccounts, menuControl, openMenuControl], - ) - - const handleSelectAccount = useCallback( - (account: SessionAccount) => { - activeRequest?.onSelectAccount(account) - }, - [activeRequest], - ) - - const getLongPressProps = useCallback( - (request: SwitcherRequest) => { - const accounts = request.accounts ?? switcherAccounts - if (accounts.length === 0 && !request.resolveAccounts) { - return { - onLongPress: undefined, - accessibilityLabel: l`Switch accounts`, - accessibilityRole: 'button' as const, - } - } - - return { - onLongPress: () => openSwitcher(request), - accessibilityLabel: l`Switch accounts`, - accessibilityRole: 'button' as const, - } - }, - [l, openSwitcher, switcherAccounts], - ) - - const menuAccounts = useMemo(() => { - if (resolvedAccounts !== null) { - return resolvedAccounts - } - return activeRequest?.accounts ?? switcherAccounts - }, [activeRequest?.accounts, resolvedAccounts, switcherAccounts]) - const contextValue = useMemo( () => ({ hasAlternateAccounts, currentProfile, switcherAccounts, signOutPromptControl, - getLongPressProps, }), [ currentProfile, - getLongPressProps, hasAlternateAccounts, signOutPromptControl, switcherAccounts, @@ -217,27 +127,34 @@ export function EphemeralAccountSwitcherScope({ return ( {children} - {hasAlternateAccounts && (IS_NATIVE || (IS_WEB && !IS_WEB_TOUCH_DEVICE)) ? ( - - - - ) : null} ) } +export function EphemeralAccountSwitcherScope({ + selectedDid, + currentProfileFromBatch = false, + children, +}: { + selectedDid: string + currentProfileFromBatch?: boolean + children: React.ReactNode +}) { + const data = useEphemeralAccountSwitcherData( + selectedDid, + currentProfileFromBatch, + ) + const signOutPromptControl = Prompt.usePromptControl() + + return ( + + {children} + + ) +} + export function useEphemeralAccountSwitcher() { const context = useContext(EphemeralAccountSwitcherContext) if (!context) { @@ -355,7 +272,7 @@ export function EphemeralAccountSwitcherMenu({ dismissGuardRef={dismissGuardRef}> {({props: menuTriggerProps}) => ( - + {renderTrigger({ currentProfile, triggerProps: { @@ -386,15 +303,7 @@ export function EphemeralAccountSwitcherMenu({ ) } -export function EphemeralAccountSwitcher({ - selectedDid, - title, - onSelectAccount, - triggerBehavior = 'press', - accounts: accountsOverride, - resolveAccounts, - renderTrigger, -}: { +type EphemeralAccountSwitcherProps = { selectedDid: string title: string onSelectAccount: (account: SessionAccount) => void @@ -405,10 +314,45 @@ export function EphemeralAccountSwitcher({ currentProfile?: AppBskyActorDefs.ProfileViewDetailed triggerProps: SwitcherTriggerProps }) => React.ReactNode +} + +export function EphemeralAccountSwitcher( + props: EphemeralAccountSwitcherProps, +) { + const data = useEphemeralAccountSwitcherData(props.selectedDid) + return +} + +export function EphemeralAccountSwitcherFromScope( + props: EphemeralAccountSwitcherProps, +) { + const data = useEphemeralAccountSwitcher() + return ( + + ) +} + +function EphemeralAccountSwitcherWithData({ + selectedDid, + title, + onSelectAccount, + triggerBehavior = 'press', + accounts: accountsOverride, + resolveAccounts, + renderTrigger, + data, + useExistingScope = false, +}: EphemeralAccountSwitcherProps & { + data: EphemeralAccountSwitcherData + useExistingScope?: boolean }) { const {t: l} = useLingui() const {switcherAccounts, hasAlternateAccounts, currentProfile} = - useEphemeralAccountSwitcherData(selectedDid) + data const menuAccounts = accountsOverride ?? switcherAccounts const control = useDialogControl() const menuControl = Menu.useMenuControl() @@ -485,22 +429,23 @@ export function EphemeralAccountSwitcher({ } if (!IS_WEB_TOUCH_DEVICE && triggerBehavior === 'longPress') { - return ( - - {IS_NATIVE ? ( - - ) : ( - - )} - + const trigger = ( + + ) + + return useExistingScope ? ( + trigger + ) : ( + + {trigger} + ) } @@ -566,28 +511,3 @@ export function EphemeralAccountSwitcher({ ) } - -function EphemeralAccountSwitcherNativeTrigger({ - request, - renderTrigger, -}: { - request: SwitcherRequest - renderTrigger: (args: { - currentProfile?: AppBskyActorDefs.ProfileViewDetailed - triggerProps: SwitcherTriggerProps - }) => React.ReactNode -}) { - const {currentProfile, getLongPressProps} = useEphemeralAccountSwitcher() - - return ( - - {renderTrigger({ - currentProfile, - triggerProps: { - ...noopTriggerProps, - ...getLongPressProps(request), - }, - })} - - ) -} diff --git a/src/components/PostControls/index.tsx b/src/components/PostControls/index.tsx index c3e850498..fe01e79bf 100644 --- a/src/components/PostControls/index.tsx +++ b/src/components/PostControls/index.tsx @@ -30,18 +30,21 @@ import { usePostLikeMutationQueue, usePostRepostMutationQueue, } from '#/state/queries/post' -import {useRequireAuth, useSession, useSessionApi} from '#/state/session' import { threadgateRecordToAllowUISetting, threadgateViewToAllowUISetting, } from '#/state/queries/threadgate/util' +import {useRequireAuth, useSession, useSessionApi} from '#/state/session' import { ProgressGuideAction, useProgressGuideControls, } from '#/state/shell/progress-guide' import * as userActionHistory from '#/state/userActionHistory' import {atoms as a, useBreakpoints, useTheme} from '#/alf' -import {EphemeralAccountSwitcher} from '#/components/EphemeralAccountSwitcher' +import { + EphemeralAccountSwitcherFromScope, + EphemeralAccountSwitcherScope, +} from '#/components/EphemeralAccountSwitcher' import {Reply as Bubble} from '#/components/icons/Reply' import {useFormatPostStatCount} from '#/components/PostControls/util' import * as Skele from '#/components/Skeleton' @@ -49,8 +52,8 @@ import * as Toast from '#/components/Toast' import {useAnalytics} from '#/analytics' import {useAutoLikeOnRepost} from '../../state/preferences/auto-like-on-repost.tsx' import {useRunWithEphemeralAgent} from '../hooks/useRunWithEphemeralAgent' -import {BookmarkButton} from './BookmarkButton' import {fetchReplyableSwitcherAccounts} from './alternateAccountsReplyEligibility' +import {BookmarkButton} from './BookmarkButton' import {MetricCountLabel} from './MetricCountLabel' import { PostControlButton, @@ -291,7 +294,7 @@ function PostControlsInner({ big, gtPhone, }) - const hasAlternateAccounts = accounts.length > 1 + const hasAlternateAccounts = accounts.length > 1 && Boolean(currentAccount) const switcherAccounts = useMemo( () => accounts @@ -557,7 +560,7 @@ function PostControlsInner({ replyDisabled ? {opacity: 0.6} : undefined, ]}> {hasAlternateAccounts && currentAccount ? ( - {hasAlternateAccounts && currentAccount ? ( - {hasAlternateAccounts && currentAccount ? ( - {hasAlternateAccounts && currentAccount ? ( - [0], -) { - return +type PostControlsProps = Parameters[0] + +const PostControls = memo(function PostControls(props: PostControlsProps) { + const {accounts, currentAccount} = useSession() + + if (accounts.length < 2 || !currentAccount) { + return + } + + return ( + + + + ) }) export {PostControls} diff --git a/src/components/ProfileBadges.tsx b/src/components/ProfileBadges.tsx index eeb622fcb..a969511f9 100644 --- a/src/components/ProfileBadges.tsx +++ b/src/components/ProfileBadges.tsx @@ -3,11 +3,13 @@ import {View} from 'react-native' import {useLingui} from '@lingui/react/macro' import {useProfileShadow} from '#/state/cache/profile-shadow' +import {type Shadow} from '#/state/cache/types' import { usePdsLabelEnabled, usePdsLabelHideBskyPds, } from '#/state/preferences/pds-label' import {usePdsFaviconQuery, usePdsLabelQuery} from '#/state/queries/pds-label' +import {useDeerVerificationProfileOverlay} from '#/state/queries/deer-verification' import {atoms as a, useAlf, type ViewStyleProp} from '#/alf' import {useNativeFontScale} from '#/alf/util/dimensions' import {BotBadge, BotBadgeButton, isBotAccount} from '#/components/BotBadge' @@ -39,32 +41,42 @@ const botIconSizes: Record = { xl: 23, } as const -export function ProfileBadges({ +type ProfileBadgesProps = ViewStyleProp & { + profile: bsky.profile.AnyProfileView + interactive?: boolean + pdsInteractive?: boolean + size: Size + allowFontScaling?: boolean +} + +export function ProfileBadges(props: ProfileBadgesProps) { + const profile = useProfileShadow(props.profile) + return +} + +/** + * Use when the parent already owns a profile-shadow subscription. Feed rows + * use this path to avoid subscribing twice for the same author. + */ +export function ProfileBadgesFromProfileShadow({ profile, interactive = false, pdsInteractive = true, size, style, allowFontScaling = true, -}: ViewStyleProp & { - profile: bsky.profile.AnyProfileView - interactive?: boolean - pdsInteractive?: boolean - size: Size - allowFontScaling?: boolean +}: Omit & { + profile: Shadow }) { - const shadowed = useProfileShadow(profile) - const verification = useSimpleVerificationState({profile}) + const shadowed = useDeerVerificationProfileOverlay(profile) + const verification = useSimpleVerificationState({profile: shadowed}) const pdsLabelEnabled = usePdsLabelEnabled() const hideBskyPds = usePdsLabelHideBskyPds() - const isBskyHandle = !!shadowed.handle && shadowed.handle.endsWith('.bsky.social') - const shouldResolvePds = pdsLabelEnabled && !(hideBskyPds && isBskyHandle) - const {data: pdsData, isLoading: isPdsLoading} = usePdsLabelQuery( shouldResolvePds ? shadowed.did : undefined, ) diff --git a/src/components/verification/index.ts b/src/components/verification/index.ts index b8d4ef193..57ba34a3c 100644 --- a/src/components/verification/index.ts +++ b/src/components/verification/index.ts @@ -34,8 +34,10 @@ export function useFullVerificationState({ const {currentAccount} = useSession() const currentAccountProfile = useCurrentAccountProfile() const profileState = useSimpleVerificationState({profile}) + const currentAccountProfileWithDeer = + useMaybeDeerVerificationProfileOverlay(currentAccountProfile) const viewerState = useSimpleVerificationState({ - profile: currentAccountProfile, + profile: currentAccountProfileWithDeer, }) return useMemo(() => { @@ -80,7 +82,7 @@ export type SimpleVerificationState = { } export function useSimpleVerificationState({ - profile: baseProfile, + profile, }: { profile?: bsky.profile.AnyProfileView }): SimpleVerificationState { @@ -89,8 +91,6 @@ export function useSimpleVerificationState({ () => preferences.data?.verificationPrefs || {hideBadges: false}, [preferences.data?.verificationPrefs], ) - const profile = useMaybeDeerVerificationProfileOverlay(baseProfile) - return useMemo(() => { if (!profile || !profile.verification) { return { @@ -114,3 +114,17 @@ export function useSimpleVerificationState({ } }, [profile, prefs]) } + +/** + * Fork-specific verification state for profiles that have not already had + * the deer verification overlay applied. Keep the upstream-shaped base hook + * above free of query work so callers can share one overlay per profile. + */ +export function useSimpleVerificationStateWithDeer({ + profile, +}: { + profile?: bsky.profile.AnyProfileView +}): SimpleVerificationState { + const shadowed = useMaybeDeerVerificationProfileOverlay(profile) + return useSimpleVerificationState({profile: shadowed}) +} diff --git a/src/screens/Profile/Header/EditProfileDialog.tsx b/src/screens/Profile/Header/EditProfileDialog.tsx index 26e51f953..2587d6bcb 100644 --- a/src/screens/Profile/Header/EditProfileDialog.tsx +++ b/src/screens/Profile/Header/EditProfileDialog.tsx @@ -35,7 +35,7 @@ import {Loader} from '#/components/Loader' import * as Prompt from '#/components/Prompt' import * as Toast from '#/components/Toast' import {Text} from '#/components/Typography' -import {useSimpleVerificationState} from '#/components/verification' +import {useSimpleVerificationStateWithDeer} from '#/components/verification' const PRONOUNS_MAX_GRAPHEMES = 20 const WEBSITE_MAX_GRAPHEMES = 2048 @@ -112,7 +112,7 @@ function DialogInner({ const t = useTheme() const control = Dialog.useDialogContext() const enableSquareButtons = useEnableSquareButtons() - const verification = useSimpleVerificationState({ + const verification = useSimpleVerificationStateWithDeer({ profile, }) const { diff --git a/src/screens/Settings/AutomationLabelSettings.tsx b/src/screens/Settings/AutomationLabelSettings.tsx index 423bc0073..5dbb75dc8 100644 --- a/src/screens/Settings/AutomationLabelSettings.tsx +++ b/src/screens/Settings/AutomationLabelSettings.tsx @@ -19,7 +19,7 @@ import * as Toggle from '#/components/forms/Toggle' import {Bot_Filled as RobotIcon} from '#/components/icons/Bot' import * as Layout from '#/components/Layout' import {Text} from '#/components/Typography' -import {useSimpleVerificationState} from '#/components/verification' +import {useSimpleVerificationStateWithDeer} from '#/components/verification' import {VerificationCheck} from '#/components/verification/VerificationCheck' import {useAnalytics} from '#/analytics' import * as bsky from '#/types/bsky' @@ -36,7 +36,7 @@ export function AutomationLabelSettingsScreen({}: Props) { const {currentAccount} = useSession() const {data: profile} = useProfileQuery({did: currentAccount?.did}) const updateProfile = useProfileUpdateMutation() - const verification = useSimpleVerificationState({profile}) + const verification = useSimpleVerificationStateWithDeer({profile}) const isBotLabeled = profile?.labels?.some(l => l.val === 'bot' && l.src === profile.did) ?? diff --git a/src/screens/Settings/PetLabelSettings.tsx b/src/screens/Settings/PetLabelSettings.tsx index ec37a36b0..52b987cab 100644 --- a/src/screens/Settings/PetLabelSettings.tsx +++ b/src/screens/Settings/PetLabelSettings.tsx @@ -19,7 +19,7 @@ import {Pet_Filled as PetIcon} from '#/components/icons/Pet' import * as Layout from '#/components/Layout' import {PetBadge} from '#/components/PetBadge' import {Text} from '#/components/Typography' -import {useSimpleVerificationState} from '#/components/verification' +import {useSimpleVerificationStateWithDeer} from '#/components/verification' import {VerificationCheck} from '#/components/verification/VerificationCheck' import {useAnalytics} from '#/analytics' import * as bsky from '#/types/bsky' @@ -33,7 +33,7 @@ export function PetLabelSettingsScreen({}: Props) { const {currentAccount} = useSession() const {data: profile} = useProfileQuery({did: currentAccount?.did}) const updateProfile = useProfileUpdateMutation() - const verification = useSimpleVerificationState({profile}) + const verification = useSimpleVerificationStateWithDeer({profile}) const isPetLabeled = profile?.labels?.some(l => l.val === 'pet' && l.src === profile.did) ?? diff --git a/src/screens/Settings/components/ChangeHandleDialog.tsx b/src/screens/Settings/components/ChangeHandleDialog.tsx index 52c7c7348..678520101 100644 --- a/src/screens/Settings/components/ChangeHandleDialog.tsx +++ b/src/screens/Settings/components/ChangeHandleDialog.tsx @@ -46,7 +46,7 @@ import {SquareBehindSquare4_Stroke2_Corner0_Rounded as CopyIcon} from '#/compone import {InlineLinkText} from '#/components/Link' import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' -import {useSimpleVerificationState} from '#/components/verification' +import {useSimpleVerificationStateWithDeer} from '#/components/verification' import {LegacyAuthRequiredDialogContent} from '#/components/dialogs/LegacyAuthRequiredDialog' import {CopyButton} from './CopyButton' @@ -169,7 +169,7 @@ function ProvidedHandlePage({ const {currentAccount} = useSession() const queryClient = useQueryClient() const profile = useCurrentAccountProfile() - const verification = useSimpleVerificationState({ + const verification = useSimpleVerificationStateWithDeer({ profile, }) diff --git a/src/state/cache/profile-shadow.ts b/src/state/cache/profile-shadow.ts index 37680adfe..facf0cebd 100644 --- a/src/state/cache/profile-shadow.ts +++ b/src/state/cache/profile-shadow.ts @@ -38,7 +38,6 @@ import {findAllProfilesInQueryData as findAllProfilesInSuggestedUsersForExploreQ import {findAllProfilesInQueryData as findAllProfilesInSuggestedUsersForSeeMoreQueryData} from '#/state/queries/trending/useGetSuggestedUsersForSeeMoreQuery' import {findAllProfilesInQueryData as findAllProfilesInPostThreadV2QueryData} from '#/state/queries/usePostThread/queryCache' import type * as bsky from '#/types/bsky' -import {useDeerVerificationProfileOverlay} from '../queries/deer-verification' import {castAsShadow, type Shadow} from './types' export type {Shadow} from './types' @@ -93,14 +92,13 @@ export function useProfileShadow< } }, [profile]) - const shadowed = useMemo(() => { + return useMemo(() => { if (shadow) { return mergeShadow(profile, shadow) } else { return castAsShadow(profile) } }, [profile, shadow]) - return useDeerVerificationProfileOverlay(shadowed) } /** diff --git a/src/state/queries/deer-verification.ts b/src/state/queries/deer-verification.ts index abab50495..e063d2ca2 100644 --- a/src/state/queries/deer-verification.ts +++ b/src/state/queries/deer-verification.ts @@ -5,6 +5,7 @@ import { } from '@atproto/api' import {useQuery} from '@tanstack/react-query' +import {useDeferredEnable} from '#/lib/hooks/useDeferredEnable' import {STALE} from '#/state/queries' import * as bsky from '#/types/bsky' import {type AnyProfileView} from '#/types/bsky/profile' @@ -183,6 +184,7 @@ export function useDeerVerificationState({ const instance = useConstellationInstance() const trusted = useDeerVerificationTrusted() const trustAppView = useDeerVerificationTrustAppView() + const deferredEnabled = useDeferredEnable(Boolean(enabled && profile)) const linkedRecords = useQuery({ staleTime: STALE.HOURS.ONE, @@ -196,7 +198,8 @@ export function useDeerVerificationState({ trusted, ) }, - enabled: enabled && profile !== undefined, + enabled: deferredEnabled, + subscribed: deferredEnabled, }) if (linkedRecords.data === undefined || profile === undefined) return diff --git a/src/state/queries/pds-label.ts b/src/state/queries/pds-label.ts index 6e3d01876..c2e3d2d07 100644 --- a/src/state/queries/pds-label.ts +++ b/src/state/queries/pds-label.ts @@ -28,6 +28,7 @@ export function usePdsLabelQuery(did: string | undefined) { return {pdsUrl, isBsky, isBridged} }, enabled: !!did, + subscribed: !!did, staleTime: 1000 * 60 * 60, // 1 hour }) } @@ -51,6 +52,7 @@ export function usePdsFaviconQuery(pdsUrl: string | undefined) { queryFn: () => isEnabled ? getFaviconServiceUrl(pdsUrl!, faviconService!) : undefined, enabled: isEnabled, + subscribed: isEnabled, staleTime: 1000 * 60 * 60, // 1 hour }) } diff --git a/src/view/com/composer/state/composer.ts b/src/view/com/composer/state/composer.ts index 19774146a..db1adee0b 100644 --- a/src/view/com/composer/state/composer.ts +++ b/src/view/com/composer/state/composer.ts @@ -786,4 +786,3 @@ function getShortenedLength(rt: RichText) { newRt.detectFacetsWithoutResolution() return shortenLinks(newRt).graphemeLength } - diff --git a/src/view/com/profile/ProfileMenu.tsx b/src/view/com/profile/ProfileMenu.tsx index 80726a2d6..a85aec44a 100644 --- a/src/view/com/profile/ProfileMenu.tsx +++ b/src/view/com/profile/ProfileMenu.tsx @@ -26,6 +26,7 @@ import { useProfileFollowMutationQueue, useProfileMuteMutationQueue, } from '#/state/queries/profile' +import {useDeerVerificationProfileOverlay} from '#/state/queries/deer-verification' import {useSession} from '#/state/session' import {EventStopper} from '#/view/com/util/EventStopper' import {atoms as a, useTheme} from '#/alf' @@ -94,7 +95,11 @@ let ProfileMenu = ({ const isFollowingBlockedAccount = isFollowing && isBlocked const isLabeler = !!profile.associated?.labeler const [devModeEnabled] = useDevMode() - const verification = useFullVerificationState({profile}) + const profileWithDeerVerification = + useDeerVerificationProfileOverlay(profile) + const verification = useFullVerificationState({ + profile: profileWithDeerVerification, + }) const {canGoLive} = useLiveNowConfig() const status = useActorStatus(profile) const statusNudge = useNux(Nux.LiveNowBetaNudge) diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx index f42a1fe5c..099a83879 100644 --- a/src/view/com/util/PostMeta.tsx +++ b/src/view/com/util/PostMeta.tsx @@ -17,7 +17,7 @@ import {useHideDisplayNames} from '#/state/preferences/hide-display-names' import {unstableCacheProfileView} from '#/state/queries/profile' import {atoms as a, platform, useTheme, web} from '#/alf' import {WebOnlyInlineLinkText} from '#/components/Link' -import {ProfileBadges} from '#/components/ProfileBadges' +import {ProfileBadgesFromProfileShadow} from '#/components/ProfileBadges' import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {Text} from '#/components/Typography' import {IS_ANDROID} from '#/env' @@ -141,7 +141,7 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => { {forceLTR(displayName)} -