import React, {memo, useMemo} from 'react' import {View} from 'react-native' import { AppBskyActorDefs, AppBskyLabelerDefs, moderateProfile, ModerationOpts, RichText as RichTextAPI, } from '@atproto/api' import {msg, Plural, plural, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {isAppLabeler} from '#/lib/moderation' import {logger} from '#/logger' import {Shadow} from '#/state/cache/types' import {useModalControls} from '#/state/modals' import {useLabelerSubscriptionMutation} from '#/state/queries/labeler' import {useLikeMutation, useUnlikeMutation} from '#/state/queries/like' import {usePreferencesQuery} from '#/state/queries/preferences' import {useRequireAuth, useSession} from '#/state/session' import {useAnalytics} from 'lib/analytics/analytics' import {useHaptics} from 'lib/haptics' import {isIOS} from 'platform/detection' import {useProfileShadow} from 'state/cache/profile-shadow' import {ProfileMenu} from '#/view/com/profile/ProfileMenu' import * as Toast from '#/view/com/util/Toast' import {atoms as a, tokens, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import {DialogOuterProps} from '#/components/Dialog' import { Heart2_Filled_Stroke2_Corner0_Rounded as HeartFilled, Heart2_Stroke2_Corner0_Rounded as Heart, } from '#/components/icons/Heart2' import {Link} from '#/components/Link' import * as Prompt from '#/components/Prompt' import {RichText} from '#/components/RichText' import {Text} from '#/components/Typography' import {ProfileHeaderDisplayName} from './DisplayName' import {ProfileHeaderHandle} from './Handle' import {ProfileHeaderMetrics} from './Metrics' import {ProfileHeaderShell} from './Shell' interface Props { profile: AppBskyActorDefs.ProfileViewDetailed labeler: AppBskyLabelerDefs.LabelerViewDetailed descriptionRT: RichTextAPI | null moderationOpts: ModerationOpts hideBackButton?: boolean isPlaceholderProfile?: boolean } let ProfileHeaderLabeler = ({ profile: profileUnshadowed, labeler, descriptionRT, moderationOpts, hideBackButton = false, isPlaceholderProfile, }: Props): React.ReactNode => { const profile: Shadow = useProfileShadow(profileUnshadowed) const t = useTheme() const {_} = useLingui() const {currentAccount, hasSession} = useSession() const {openModal} = useModalControls() const {track} = useAnalytics() const requireAuth = useRequireAuth() const playHaptic = useHaptics() const cantSubscribePrompt = Prompt.usePromptControl() const isSelf = currentAccount?.did === profile.did const moderation = useMemo( () => moderateProfile(profile, moderationOpts), [profile, moderationOpts], ) const {data: preferences} = usePreferencesQuery() const {mutateAsync: toggleSubscription, variables} = useLabelerSubscriptionMutation() const isSubscribed = variables?.subscribe ?? preferences?.moderationPrefs.labelers.find(l => l.did === profile.did) const canSubscribe = isSubscribed || (preferences ? preferences?.moderationPrefs.labelers.length < 9 : false) const {mutateAsync: likeMod, isPending: isLikePending} = useLikeMutation() const {mutateAsync: unlikeMod, isPending: isUnlikePending} = useUnlikeMutation() const [likeUri, setLikeUri] = React.useState( labeler.viewer?.like || '', ) const [likeCount, setLikeCount] = React.useState(labeler.likeCount || 0) const onToggleLiked = React.useCallback(async () => { if (!labeler) { return } try { playHaptic() if (likeUri) { await unlikeMod({uri: likeUri}) track('CustomFeed:Unlike') setLikeCount(c => c - 1) setLikeUri('') } else { const res = await likeMod({uri: labeler.uri, cid: labeler.cid}) track('CustomFeed:Like') setLikeCount(c => c + 1) setLikeUri(res.uri) } } catch (e: any) { Toast.show( _( msg`There was an an issue contacting the server, please check your internet connection and try again.`, ), ) logger.error(`Failed to toggle labeler like`, {message: e.message}) } }, [labeler, playHaptic, likeUri, unlikeMod, track, likeMod, _]) const onPressEditProfile = React.useCallback(() => { track('ProfileHeader:EditProfileButtonClicked') openModal({ name: 'edit-profile', profile, }) }, [track, openModal, profile]) const onPressSubscribe = React.useCallback( () => requireAuth(async () => { if (!canSubscribe) { cantSubscribePrompt.open() return } try { await toggleSubscription({ did: profile.did, subscribe: !isSubscribed, }) } catch (e: any) { // setSubscriptionError(e.message) logger.error(`Failed to subscribe to labeler`, {message: e.message}) } }), [ requireAuth, toggleSubscription, isSubscribed, profile, canSubscribe, cantSubscribePrompt, ], ) const isMe = React.useMemo( () => currentAccount?.did === profile.did, [currentAccount, profile], ) return ( {isMe ? ( ) : !isAppLabeler(profile.did) ? ( <> ) : null} {!isPlaceholderProfile && ( <> {isSelf && } {descriptionRT && !moderation.ui('profileView').blur ? ( ) : undefined} {!isAppLabeler(profile.did) && ( {typeof likeCount === 'number' && ( {({hovered, focused, pressed}) => ( )} )} )} )} ) } ProfileHeaderLabeler = memo(ProfileHeaderLabeler) export {ProfileHeaderLabeler} function CantSubscribePrompt({ control, }: { control: DialogOuterProps['control'] }) { const {_} = useLingui() return ( Unable to subscribe We're sorry! You can only subscribe to ten labelers, and you've reached your limit of ten. ) }