diff options
Diffstat (limited to 'src/screens')
-rw-r--r-- | src/screens/Messages/Conversation/index.tsx | 104 | ||||
-rw-r--r-- | src/screens/Messages/List/ChatListItem.tsx | 70 | ||||
-rw-r--r-- | src/screens/Messages/List/index.tsx | 12 |
3 files changed, 129 insertions, 57 deletions
diff --git a/src/screens/Messages/Conversation/index.tsx b/src/screens/Messages/Conversation/index.tsx index f382647a5..05df3e23b 100644 --- a/src/screens/Messages/Conversation/index.tsx +++ b/src/screens/Messages/Conversation/index.tsx @@ -3,7 +3,7 @@ import {TouchableOpacity, View} from 'react-native' import {KeyboardProvider} from 'react-native-keyboard-controller' import {KeyboardAvoidingView} from 'react-native-keyboard-controller' import {useSafeAreaInsets} from 'react-native-safe-area-context' -import {AppBskyActorDefs} from '@atproto/api' +import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -12,8 +12,12 @@ import {NativeStackScreenProps} from '@react-navigation/native-stack' import {CommonNavigatorParams, NavigationProp} 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 {isIOS, isWeb} from 'platform/detection' import {ConvoProvider, isConvoActive, useConvo} from 'state/messages/convo' import {ConvoStatus} from 'state/messages/convo/types' @@ -27,6 +31,7 @@ import {ListMaybePlaceholder} from '#/components/Lists' import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' import {ClipClopGate} from '../gate' + type Props = NativeStackScreenProps< CommonNavigatorParams, 'MessagesConversation' @@ -137,7 +142,7 @@ function Inner() { } let Header = ({ - profile, + profile: initialProfile, }: { profile?: AppBskyActorDefs.ProfileViewBasic }): React.ReactNode => { @@ -145,12 +150,8 @@ let Header = ({ const {_} = useLingui() const {gtTablet} = useBreakpoints() const navigation = useNavigation<NavigationProp>() - const convoState = useConvo() - - const isDeletedAccount = profile?.handle === 'missing.invalid' - const displayName = isDeletedAccount - ? 'Deleted Account' - : profile?.displayName + const moderationOpts = useModerationOpts() + const {data: profile} = useProfileQuery({did: initialProfile?.did}) const onPressBack = useCallback(() => { if (isWeb) { @@ -195,23 +196,12 @@ let Header = ({ ) : ( <View style={{width: 30}} /> )} - <View style={[a.align_center, a.gap_sm, a.flex_1]}> - {profile ? ( - <View style={[a.align_center]}> - <PreviewableUserAvatar size={32} profile={profile} /> - <Text - style={[a.text_lg, a.font_bold, a.pt_sm, a.pb_2xs]} - numberOfLines={1}> - {displayName} - </Text> - {!isDeletedAccount && ( - <Text style={[t.atoms.text_contrast_medium]} numberOfLines={1}> - @{profile.handle} - </Text> - )} - </View> - ) : ( - <> + + {profile && moderationOpts ? ( + <HeaderReady profile={profile} moderationOpts={moderationOpts} /> + ) : ( + <> + <View style={[a.align_center, a.gap_sm, a.flex_1]}> <View style={[ {width: 32, height: 32}, @@ -234,19 +224,69 @@ let Header = ({ t.atoms.bg_contrast_25, ]} /> - </> - )} + </View> + + <View style={{width: 30}} /> + </> + )} + </View> + ) +} +Header = React.memo(Header) + +function HeaderReady({ + profile: profileUnshadowed, + moderationOpts, +}: { + profile: AppBskyActorDefs.ProfileViewBasic + moderationOpts: ModerationOpts +}) { + 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'), + ) + + return ( + <> + <View style={[a.align_center, a.gap_sm, a.flex_1]}> + <View style={[a.align_center]}> + <PreviewableUserAvatar + size={32} + profile={profile} + moderation={moderation.ui('avatar')} + /> + <Text + style={[a.text_lg, a.font_bold, a.pt_sm, a.pb_2xs]} + numberOfLines={1}> + {displayName} + </Text> + {!isDeletedAccount && ( + <Text style={[t.atoms.text_contrast_medium]} numberOfLines={1}> + @{profile.handle} + </Text> + )} + </View> </View> - {isConvoActive(convoState) && profile ? ( + + {isConvoActive(convoState) && ( <ConvoMenu convo={convoState.convo} profile={profile} currentScreen="conversation" + moderation={moderation} /> - ) : ( - <View style={{width: 30}} /> )} - </View> + </> ) } -Header = React.memo(Header) diff --git a/src/screens/Messages/List/ChatListItem.tsx b/src/screens/Messages/List/ChatListItem.tsx index 57a8e0348..aa47e9503 100644 --- a/src/screens/Messages/List/ChatListItem.tsx +++ b/src/screens/Messages/List/ChatListItem.tsx @@ -1,13 +1,21 @@ import React from 'react' import {View} from 'react-native' -import {ChatBskyConvoDefs} from '@atproto/api' +import { + AppBskyActorDefs, + ChatBskyConvoDefs, + moderateProfile, + ModerationOpts, +} from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' import {NavigationProp} from '#/lib/routes/types' import {isNative} from '#/platform/detection' +import {useProfileShadow} from '#/state/cache/profile-shadow' +import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useSession} from '#/state/session' +import {sanitizeDisplayName} from 'lib/strings/display-names' import {TimeElapsed} from '#/view/com/util/TimeElapsed' import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' @@ -17,25 +25,53 @@ import {Bell2Off_Filled_Corner0_Rounded as BellStroke} from '#/components/icons/ import {useMenuControl} from '#/components/Menu' import {Text} from '#/components/Typography' -export function ChatListItem({ +export function ChatListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) { + const {currentAccount} = useSession() + const otherUser = convo.members.find( + member => member.did !== currentAccount?.did, + ) + const moderationOpts = useModerationOpts() + + if (!otherUser || !moderationOpts) { + return null + } + + return ( + <ChatListItemReady + convo={convo} + profile={otherUser} + moderationOpts={moderationOpts} + /> + ) +} + +function ChatListItemReady({ convo, - index, + profile: profileUnshadowed, + moderationOpts, }: { convo: ChatBskyConvoDefs.ConvoView - index: number + profile: AppBskyActorDefs.ProfileViewBasic + moderationOpts: ModerationOpts }) { const t = useTheme() const {_} = useLingui() const {currentAccount} = useSession() const menuControl = useMenuControl() const {gtMobile} = useBreakpoints() - const otherUser = convo.members.find( - member => member.did !== currentAccount?.did, + const profile = useProfileShadow(profileUnshadowed) + const moderation = React.useMemo( + () => moderateProfile(profile, moderationOpts), + [profile, moderationOpts], ) - const isDeletedAccount = otherUser?.handle === 'missing.invalid' + + const isDeletedAccount = profile.handle === 'missing.invalid' const displayName = isDeletedAccount ? 'Deleted Account' - : otherUser?.displayName || otherUser?.handle + : sanitizeDisplayName( + profile.displayName || profile.handle, + moderation.ui('displayName'), + ) let lastMessage = _(msg`No messages yet`) let lastMessageSentAt: string | null = null @@ -73,10 +109,6 @@ export function ChatListItem({ }) }, [convo.id, navigation]) - if (!otherUser) { - return null - } - return ( <View // @ts-expect-error web only @@ -85,7 +117,7 @@ export function ChatListItem({ onFocus={onFocus} onBlur={onMouseLeave}> <Button - label={otherUser.displayName || otherUser.handle} + label={profile.displayName || profile.handle} onPress={onPress} style={a.flex_1} onLongPress={isNative ? menuControl.open : undefined}> @@ -98,10 +130,13 @@ export function ChatListItem({ a.py_md, a.gap_md, (hovered || pressed) && t.atoms.bg_contrast_25, - index === 0 && [a.border_t, a.pt_lg], t.atoms.border_contrast_low, ]}> - <UserAvatar avatar={otherUser?.avatar} size={52} /> + <UserAvatar + avatar={profile.avatar} + size={52} + moderation={moderation.ui('avatar')} + /> <View style={[a.flex_1, a.flex_row, a.align_center]}> <View style={[a.flex_1]}> <View @@ -154,7 +189,7 @@ export function ChatListItem({ <Text numberOfLines={1} style={[a.text_sm, t.atoms.text_contrast_medium, a.pb_xs]}> - @{otherUser.handle} + @{profile.handle} </Text> )} <Text @@ -196,7 +231,7 @@ export function ChatListItem({ )} <ConvoMenu convo={convo} - profile={otherUser} + profile={profile} control={menuControl} currentScreen="list" showMarkAsRead={convo.unreadCount > 0} @@ -204,6 +239,7 @@ export function ChatListItem({ triggerOpacity={ !gtMobile || showActions || menuControl.isOpen ? 1 : 0 } + moderation={moderation} /> </View> </View> diff --git a/src/screens/Messages/List/index.tsx b/src/screens/Messages/List/index.tsx index 6300a976b..2ae17a141 100644 --- a/src/screens/Messages/List/index.tsx +++ b/src/screens/Messages/List/index.tsx @@ -29,14 +29,8 @@ import {ChatListItem} from './ChatListItem' type Props = NativeStackScreenProps<MessagesTabNavigatorParams, 'Messages'> -function renderItem({ - item, - index, -}: { - item: ChatBskyConvoDefs.ConvoView - index: number -}) { - return <ChatListItem convo={item} index={index} /> +function renderItem({item}: {item: ChatBskyConvoDefs.ConvoView}) { + return <ChatListItem convo={item} /> } function keyExtractor(item: ChatBskyConvoDefs.ConvoView) { @@ -232,6 +226,8 @@ function DesktopHeader({ a.gap_lg, a.px_lg, a.py_sm, + a.border_b, + t.atoms.border_contrast_low, ]}> <Text style={[a.text_2xl, a.font_bold]}> <Trans>Messages</Trans> |