diff options
author | Hailey <me@haileyok.com> | 2024-05-17 14:21:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-17 16:21:15 -0500 |
commit | d02e0884c40adebe3799254395d933205b104a86 (patch) | |
tree | 00cd164d727072ad04179662a2d7bfe914691ba9 /src/screens/Messages/Conversation/index.tsx | |
parent | 1b47ea7367c7d0f37557d8f07329c3b6f97a5e03 (diff) | |
download | voidsky-d02e0884c40adebe3799254395d933205b104a86.tar.zst |
[🐴] Block Info (#4068)
* get the damn thing in there 😮💨 * more cleanup and little fixes another nit nit small annoyance add a comment only use `scrollTo` when necessary remove now unnecessary styles * move padding out * add unblock function * rm need for moderationpts * ? * ?? * extract leaveconvoprompt * move `setHasScrolled` to `onContentSizeChanged` * account for block footer * wrap up nit make sure recipient is loaded before showing refactor to hide chat input typo squigglie add report dialog finalize delete implement custom animation add configurable replace animation add leave convo to block options * correct functionality for report * moev component to another file * maybe... * fix chat item * improve * remove unused gtmobile * nit * more cleanup * more cleanup * fix merge * fix header * few more changes * nit * remove old
Diffstat (limited to 'src/screens/Messages/Conversation/index.tsx')
-rw-r--r-- | src/screens/Messages/Conversation/index.tsx | 228 |
1 files changed, 61 insertions, 167 deletions
diff --git a/src/screens/Messages/Conversation/index.tsx b/src/screens/Messages/Conversation/index.tsx index 2c42ed16d..0fe4138bb 100644 --- a/src/screens/Messages/Conversation/index.tsx +++ b/src/screens/Messages/Conversation/index.tsx @@ -1,35 +1,28 @@ import React, {useCallback} from 'react' -import {TouchableOpacity, View} from 'react-native' +import {View} from 'react-native' import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useFocusEffect, useNavigation} from '@react-navigation/native' +import {useFocusEffect} from '@react-navigation/native' import {NativeStackScreenProps} from '@react-navigation/native-stack' -import {makeProfileLink} from '#/lib/routes/links' -import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types' +import {CommonNavigatorParams} from '#/lib/routes/types' import {useGate} from '#/lib/statsig/statsig' -import {useProfileShadow} from '#/state/cache/profile-shadow' import {useCurrentConvoId} from '#/state/messages/current-convo-id' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useProfileQuery} from '#/state/queries/profile' -import {BACK_HITSLOP} from 'lib/constants' -import {sanitizeDisplayName} from 'lib/strings/display-names' import {isWeb} from 'platform/detection' +import {useProfileShadow} from 'state/cache/profile-shadow' import {ConvoProvider, isConvoActive, useConvo} from 'state/messages/convo' import {ConvoStatus} from 'state/messages/convo/types' import {useSetMinimalShellMode} from 'state/shell' -import {PreviewableUserAvatar} from 'view/com/util/UserAvatar' import {CenteredView} from 'view/com/util/Views' import {MessagesList} from '#/screens/Messages/Conversation/MessagesList' -import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' -import {ConvoMenu} from '#/components/dms/ConvoMenu' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {MessagesListBlockedFooter} from '#/components/dms/MessagesListBlockedFooter' +import {MessagesListHeader} from '#/components/dms/MessagesListHeader' import {Error} from '#/components/Error' -import {Link} from '#/components/Link' -import {ListMaybePlaceholder} from '#/components/Lists' import {Loader} from '#/components/Loader' -import {Text} from '#/components/Typography' import {ClipClopGate} from '../gate' type Props = NativeStackScreenProps< @@ -73,6 +66,11 @@ function Inner() { const convoState = useConvo() const {_} = useLingui() + const moderationOpts = useModerationOpts() + const {data: recipient} = useProfileQuery({ + did: convoState.recipients?.[0].did, + }) + // Because we want to give the list a chance to asynchronously scroll to the end before it is visible to the user, // we use `hasScrolled` to determine when to render. With that said however, there is a chance that the chat will be // empty. So, we also check for that possible state as well and render once we can. @@ -86,7 +84,7 @@ function Inner() { if (convoState.status === ConvoStatus.Error) { return ( <CenteredView style={a.flex_1} sideBorders> - <Header /> + <MessagesListHeader /> <Error title={_(msg`Something went wrong`)} message={_(msg`We couldn't load this conversation`)} @@ -96,20 +94,21 @@ function Inner() { ) } - /* - * Any other convo states (atm) are "ready" states - */ return ( <CenteredView style={[a.flex_1]} sideBorders> - <Header profile={convoState.recipients?.[0]} /> + {!readyToShow && <MessagesListHeader />} <View style={[a.flex_1]}> - {isConvoActive(convoState) ? ( - <MessagesList + {moderationOpts && recipient ? ( + <InnerReady + moderationOpts={moderationOpts} + recipient={recipient} hasScrolled={hasScrolled} setHasScrolled={setHasScrolled} /> ) : ( - <ListMaybePlaceholder isLoading /> + <> + <View style={[a.align_center, a.gap_sm, a.flex_1]} /> + </> )} {!readyToShow && ( <View @@ -132,160 +131,55 @@ function Inner() { ) } -const PFP_SIZE = isWeb ? 40 : 34 - -let Header = ({ - profile: initialProfile, -}: { - profile?: AppBskyActorDefs.ProfileViewBasic -}): React.ReactNode => { - const t = useTheme() - const {_} = useLingui() - const {gtTablet} = useBreakpoints() - const navigation = useNavigation<NavigationProp>() - const moderationOpts = useModerationOpts() - const {data: profile} = useProfileQuery({did: initialProfile?.did}) - - const onPressBack = useCallback(() => { - if (isWeb) { - navigation.replace('Messages') - } else { - navigation.goBack() - } - }, [navigation]) - - return ( - <View - style={[ - t.atoms.bg, - t.atoms.border_contrast_low, - a.border_b, - a.flex_row, - a.align_center, - a.gap_sm, - gtTablet ? a.pl_lg : a.pl_xl, - a.pr_lg, - a.py_sm, - ]}> - {!gtTablet && ( - <TouchableOpacity - testID="conversationHeaderBackBtn" - onPress={onPressBack} - hitSlop={BACK_HITSLOP} - style={{width: 30, height: 30}} - accessibilityRole="button" - accessibilityLabel={_(msg`Back`)} - accessibilityHint=""> - <FontAwesomeIcon - size={18} - icon="angle-left" - style={{ - marginTop: 6, - }} - color={t.atoms.text.color} - /> - </TouchableOpacity> - )} - - {profile && moderationOpts ? ( - <HeaderReady profile={profile} moderationOpts={moderationOpts} /> - ) : ( - <> - <View style={[a.flex_row, a.align_center, a.gap_md, a.flex_1]}> - <View - style={[ - {width: PFP_SIZE, height: PFP_SIZE}, - a.rounded_full, - t.atoms.bg_contrast_25, - ]} - /> - <View style={a.gap_xs}> - <View - style={[ - {width: 120, height: 16}, - a.rounded_xs, - t.atoms.bg_contrast_25, - a.mt_xs, - ]} - /> - <View - style={[ - {width: 175, height: 12}, - a.rounded_xs, - t.atoms.bg_contrast_25, - ]} - /> - </View> - </View> - - <View style={{width: 30}} /> - </> - )} - </View> - ) -} -Header = React.memo(Header) - -function HeaderReady({ - profile: profileUnshadowed, +function InnerReady({ moderationOpts, + recipient: recipientUnshadowed, + hasScrolled, + setHasScrolled, }: { - profile: AppBskyActorDefs.ProfileViewBasic moderationOpts: ModerationOpts + recipient: AppBskyActorDefs.ProfileViewBasic + hasScrolled: boolean + setHasScrolled: React.Dispatch<React.SetStateAction<boolean>> }) { - const t = useTheme() const convoState = useConvo() - const profile = useProfileShadow(profileUnshadowed) - const moderation = React.useMemo( - () => moderateProfile(profile, moderationOpts), - [profile, moderationOpts], - ) - - const isDeletedAccount = profile?.handle === 'missing.invalid' - const displayName = isDeletedAccount - ? 'Deleted Account' - : sanitizeDisplayName( - profile.displayName || profile.handle, - moderation.ui('displayName'), - ) + const recipient = useProfileShadow(recipientUnshadowed) + + const moderation = React.useMemo(() => { + return moderateProfile(recipient, moderationOpts) + }, [recipient, moderationOpts]) + + const blockInfo = React.useMemo(() => { + const modui = moderation.ui('profileView') + const blocks = modui.alerts.filter(alert => alert.type === 'blocking') + const listBlocks = blocks.filter(alert => alert.source.type === 'list') + const userBlock = blocks.find(alert => alert.source.type === 'user') + return { + listBlocks, + userBlock, + } + }, [moderation]) return ( <> - <Link - style={[a.flex_row, a.align_center, a.gap_md, a.flex_1, a.pr_md]} - to={makeProfileLink(profile)}> - <PreviewableUserAvatar - size={PFP_SIZE} - profile={profile} - moderation={moderation.ui('avatar')} - disableHoverCard={moderation.blocked} - /> - <View style={a.flex_1}> - <Text - style={[a.text_md, a.font_bold, web(a.leading_normal)]} - numberOfLines={1}> - {displayName} - </Text> - {!isDeletedAccount && ( - <Text - style={[ - t.atoms.text_contrast_medium, - a.text_sm, - web([a.leading_normal, {marginTop: -2}]), - ]} - numberOfLines={1}> - @{profile.handle} - </Text> - )} - </View> - </Link> - + <MessagesListHeader + profile={recipient} + moderation={moderation} + blockInfo={blockInfo} + /> {isConvoActive(convoState) && ( - <ConvoMenu - convo={convoState.convo} - profile={profile} - currentScreen="conversation" - moderation={moderation} + <MessagesList + hasScrolled={hasScrolled} + setHasScrolled={setHasScrolled} + blocked={moderation?.blocked} + footer={ + <MessagesListBlockedFooter + recipient={recipient} + convoId={convoState.convo.id} + hasMessages={convoState.items.length > 0} + blockInfo={blockInfo} + /> + } /> )} </> |