diff --git a/src/components/KnownFollowers.tsx b/src/components/KnownFollowers.tsx index b26216b2f7..502b08252f 100644 --- a/src/components/KnownFollowers.tsx +++ b/src/components/KnownFollowers.tsx @@ -5,9 +5,7 @@ import { moderateProfile, type ModerationOpts, } from '@atproto/api' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' -import {Plural, Trans} from '@lingui/react/macro' +import {Plural, Trans, useLingui} from '@lingui/react/macro' import {makeProfileLink} from '#/lib/routes/links' import {sanitizeDisplayName} from '#/lib/strings/display-names' @@ -93,7 +91,7 @@ function KnownFollowersInner({ showIfEmpty?: boolean }) { const t = useTheme() - const {_} = useLingui() + const {t: l} = useLingui() const textStyle = [a.text_sm, a.leading_snug, t.atoms.text_contrast_medium] @@ -124,9 +122,7 @@ function KnownFollowersInner({ return ( {slice.length >= 2 ? ( // 2-n followers, including blocks - serverCount > 2 ? ( // only 2 + // only 2 + serverCount > 2 ? ( Followed by{' '} @@ -254,7 +251,7 @@ function EmptyFallback({show}: {show?: boolean}) { return ( - Not followed by anyone you're following + Not followed by anyone you’re following ) } diff --git a/src/components/dms/LeaveConvoPrompt.tsx b/src/components/dms/LeaveConvoPrompt.tsx index b000040455..f4e7ea843a 100644 --- a/src/components/dms/LeaveConvoPrompt.tsx +++ b/src/components/dms/LeaveConvoPrompt.tsx @@ -1,5 +1,4 @@ -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' +import {useLingui} from '@lingui/react/macro' import {StackActions, useNavigation} from '@react-navigation/native' import {type NavigationProp} from '#/lib/routes/types' @@ -20,7 +19,7 @@ export function LeaveConvoPrompt({ currentScreen: 'list' | 'conversation' hasMessages?: boolean }) { - const {_} = useLingui() + const {t: l} = useLingui() const navigation = useNavigation() const {mutate: leaveConvo} = useLeaveConvo(convoId, { @@ -32,7 +31,7 @@ export function LeaveConvoPrompt({ } }, onError: () => { - Toast.show(_(msg`Could not leave chat`), { + Toast.show(l`Could not leave chat`, { type: 'error', }) }, @@ -41,15 +40,13 @@ export function LeaveConvoPrompt({ return ( leaveConvo()} /> diff --git a/src/screens/Messages/components/ChatStatusInfo.tsx b/src/screens/Messages/components/ChatStatusInfo.tsx index 8f27c55b46..43158e4b1a 100644 --- a/src/screens/Messages/components/ChatStatusInfo.tsx +++ b/src/screens/Messages/components/ChatStatusInfo.tsx @@ -1,19 +1,26 @@ -import {useCallback} from 'react' +import {useCallback, useMemo} from 'react' import {View} from 'react-native' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' +import {LinearGradient} from 'expo-linear-gradient' +import {ChatBskyConvoDefs, moderateProfile} from '@atproto/api' +import {Trans, useLingui} from '@lingui/react/macro' +import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' +import {sanitizeHandle} from '#/lib/strings/handles' +import {useProfileShadow} from '#/state/cache/profile-shadow' import {type ActiveConvoStates} from '#/state/messages/convo' import {useModerationOpts} from '#/state/preferences/moderation-opts' -import {atoms as a, useTheme} from '#/alf' +import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar' +import {atoms as a, useTheme, web} from '#/alf' import {LeaveConvoPrompt} from '#/components/dms/LeaveConvoPrompt' import {KnownFollowers} from '#/components/KnownFollowers' import {usePromptControl} from '#/components/Prompt' +import {Text} from '#/components/Typography' +import type * as bsky from '#/types/bsky' import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons' export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) { const t = useTheme() - const {_} = useLingui() + const {t: l} = useLingui() const moderationOpts = useModerationOpts() const leaveConvoControl = usePromptControl() @@ -25,36 +32,59 @@ export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) { // if we ever allow someone other than the owner to invite people, this will need to change const otherUser = convoState.convo.primaryMember + const lastMessage = ChatBskyConvoDefs.isMessageView( + convoState.convo.view.lastMessage, + ) + ? convoState.convo.view.lastMessage + : null + if (!moderationOpts) { return null } return ( - + + + {otherUser && ( + + )} {otherUser && ( )} {otherUser && ( )} ) } + +function InviterHeader({ + profile: profileUnshadowed, + moderationOpts, +}: { + profile: bsky.profile.AnyProfileView + moderationOpts: NonNullable> +}) { + const t = useTheme() + const profile = useProfileShadow(profileUnshadowed) + const moderation = useMemo( + () => moderateProfile(profile, moderationOpts), + [profile, moderationOpts], + ) + const displayName = createSanitizedDisplayName( + profile, + true, + moderation.ui('displayName'), + ) + + return ( + + + + + {displayName} added you + + + {sanitizeHandle(profile.handle, '@')} + + + + ) +} diff --git a/src/screens/Messages/components/RequestButtons.tsx b/src/screens/Messages/components/RequestButtons.tsx index 5a3b92dbe9..7b0ec9d094 100644 --- a/src/screens/Messages/components/RequestButtons.tsx +++ b/src/screens/Messages/components/RequestButtons.tsx @@ -1,8 +1,6 @@ import {useCallback} from 'react' import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' -import {Trans} from '@lingui/react/macro' +import {Trans, useLingui} from '@lingui/react/macro' import {StackActions, useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' @@ -16,7 +14,6 @@ import { unstableCacheProfileView, useProfileBlockMutationQueue, } from '#/state/queries/profile' -import {atoms as a} from '#/alf' import { Button, ButtonIcon, @@ -29,6 +26,8 @@ import { useEmailDialogControl, } from '#/components/dialogs/EmailDialog' import {AfterReportDialog} from '#/components/dms/AfterReportDialog' +import {ArrowBoxLeft_Stroke2_Corner0_Rounded as LeaveIcon} from '#/components/icons/ArrowBoxLeft' +import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check' import {CircleX_Stroke2_Corner0_Rounded} from '#/components/icons/CircleX' import {Flag_Stroke2_Corner0_Rounded as FlagIcon} from '#/components/icons/Flag' import {PersonX_Stroke2_Corner0_Rounded as PersonXIcon} from '#/components/icons/Person' @@ -40,20 +39,22 @@ import * as Toast from '#/components/Toast' export function RejectMenu({ convo, profile, - size = 'tiny', + size = 'small', color = 'secondary', label, + icon = false, showDeleteConvo, currentScreen, ...props }: Omit & { label?: string + icon?: boolean convo: ChatBskyConvoDefs.ConvoView profile: ChatBskyActorDefs.ProfileViewBasic showDeleteConvo?: boolean currentScreen: 'list' | 'conversation' }) { - const {_} = useLingui() + const {t: l} = useLingui() const shadowedProfile = useProfileShadow(profile) const navigation = useNavigation() const queryClient = useQueryClient() @@ -66,12 +67,10 @@ export function RejectMenu({ }, onError: () => { Toast.show( - _( - msg({ - context: 'toast', - message: 'Failed to delete chat', - }), - ), + l({ + context: 'toast', + message: 'Failed to delete chat', + }), { type: 'error', }, @@ -82,35 +81,31 @@ export function RejectMenu({ const onPressDelete = useCallback(() => { Toast.show( - _( - msg({ - context: 'toast', - message: 'Chat deleted', - }), - ), + l({ + context: 'toast', + message: 'Chat deleted', + }), { type: 'success', }, ) leaveConvo() - }, [leaveConvo, _]) + }, [leaveConvo, l]) const onPressBlock = useCallback(() => { Toast.show( - _( - msg({ - context: 'toast', - message: 'Account blocked', - }), - ), + l({ + context: 'toast', + message: 'Account blocked', + }), { type: 'success', }, ) // block and also delete convo - queueBlock() + void queueBlock() leaveConvo() - }, [queueBlock, leaveConvo, _]) + }, [queueBlock, leaveConvo, l]) const reportControl = useDialogControl() const blockOrDeleteControl = useDialogControl() @@ -122,15 +117,15 @@ export function RejectMenu({ return ( <> - + {({props: triggerProps}) => ( ) } export function DeleteChatButton({ convo, - size = 'tiny', + size = 'small', color = 'secondary', label, + icon = false, currentScreen, ...props }: Omit & { label?: string + icon?: boolean convo: ChatBskyConvoDefs.ConvoView currentScreen: 'list' | 'conversation' }) { - const {_} = useLingui() + const {t: l} = useLingui() const navigation = useNavigation() const {mutate: leaveConvo} = useLeaveConvo(convo.id, { @@ -316,12 +314,10 @@ export function DeleteChatButton({ }, onError: () => { Toast.show( - _( - msg({ - context: 'toast', - message: 'Failed to delete chat', - }), - ), + l({ + context: 'toast', + message: 'Failed to delete chat', + }), { type: 'error', }, @@ -331,27 +327,25 @@ export function DeleteChatButton({ const onPressDelete = useCallback(() => { Toast.show( - _( - msg({ - context: 'toast', - message: 'Chat deleted', - }), - ), + l({ + context: 'toast', + message: 'Chat deleted', + }), { type: 'success', }, ) leaveConvo() - }, [leaveConvo, _]) + }, [leaveConvo, l]) return ( ) diff --git a/src/screens/Messages/components/RequestListItem.tsx b/src/screens/Messages/components/RequestListItem.tsx index 0120c7d9f4..64dbebb164 100644 --- a/src/screens/Messages/components/RequestListItem.tsx +++ b/src/screens/Messages/components/RequestListItem.tsx @@ -42,7 +42,7 @@ export function RequestListItem({ )} {/* spacer, since you can't nest pressables */} - + {/* Placeholder text so that it responds to the font height */} Accept Request