Update presentation of chat requests (#10417)
This commit is contained in:
@@ -5,9 +5,7 @@ import {
|
|||||||
moderateProfile,
|
moderateProfile,
|
||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Plural, Trans} from '@lingui/react/macro'
|
|
||||||
|
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
@@ -93,7 +91,7 @@ function KnownFollowersInner({
|
|||||||
showIfEmpty?: boolean
|
showIfEmpty?: boolean
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
|
|
||||||
const textStyle = [a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]
|
const textStyle = [a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]
|
||||||
|
|
||||||
@@ -124,9 +122,7 @@ function KnownFollowersInner({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
label={_(
|
label={l`Press to view followers of this account that you also follow`}
|
||||||
msg`Press to view followers of this account that you also follow`,
|
|
||||||
)}
|
|
||||||
onPress={onLinkPress}
|
onPress={onLinkPress}
|
||||||
to={makeProfileLink(profile, 'known-followers')}
|
to={makeProfileLink(profile, 'known-followers')}
|
||||||
style={[
|
style={[
|
||||||
@@ -188,7 +184,8 @@ function KnownFollowersInner({
|
|||||||
numberOfLines={2}>
|
numberOfLines={2}>
|
||||||
{slice.length >= 2 ? (
|
{slice.length >= 2 ? (
|
||||||
// 2-n followers, including blocks
|
// 2-n followers, including blocks
|
||||||
serverCount > 2 ? ( // only 2
|
// only 2
|
||||||
|
serverCount > 2 ? (
|
||||||
<Trans>
|
<Trans>
|
||||||
Followed by{' '}
|
Followed by{' '}
|
||||||
<Text emoji key={slice[0].profile.did} style={textStyle}>
|
<Text emoji key={slice[0].profile.did} style={textStyle}>
|
||||||
@@ -254,7 +251,7 @@ function EmptyFallback({show}: {show?: boolean}) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Text style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
<Text style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
||||||
<Trans>Not followed by anyone you're following</Trans>
|
<Trans>Not followed by anyone you’re following</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import {msg} from '@lingui/core/macro'
|
import {useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {StackActions, useNavigation} from '@react-navigation/native'
|
import {StackActions, useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
@@ -20,7 +19,7 @@ export function LeaveConvoPrompt({
|
|||||||
currentScreen: 'list' | 'conversation'
|
currentScreen: 'list' | 'conversation'
|
||||||
hasMessages?: boolean
|
hasMessages?: boolean
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
const {mutate: leaveConvo} = useLeaveConvo(convoId, {
|
const {mutate: leaveConvo} = useLeaveConvo(convoId, {
|
||||||
@@ -32,7 +31,7 @@ export function LeaveConvoPrompt({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Toast.show(_(msg`Could not leave chat`), {
|
Toast.show(l`Could not leave chat`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -41,15 +40,13 @@ export function LeaveConvoPrompt({
|
|||||||
return (
|
return (
|
||||||
<Prompt.Basic
|
<Prompt.Basic
|
||||||
control={control}
|
control={control}
|
||||||
title={_(msg`Leave conversation`)}
|
title={l`Leave conversation`}
|
||||||
description={
|
description={
|
||||||
hasMessages
|
hasMessages
|
||||||
? _(
|
? l`Are you sure you want to leave this conversation? Your messages will be deleted for you, but not for the other participant.`
|
||||||
msg`Are you sure you want to leave this conversation? Your messages will be deleted for you, but not for the other participant.`,
|
: l`Are you sure you want to leave this conversation?`
|
||||||
)
|
|
||||||
: _(msg`Are you sure you want to leave this conversation?`)
|
|
||||||
}
|
}
|
||||||
confirmButtonCta={_(msg`Leave`)}
|
confirmButtonCta={l`Leave`}
|
||||||
confirmButtonColor="negative"
|
confirmButtonColor="negative"
|
||||||
onConfirm={() => leaveConvo()}
|
onConfirm={() => leaveConvo()}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,19 +1,26 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback, useMemo} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {LinearGradient} from 'expo-linear-gradient'
|
||||||
import {useLingui} from '@lingui/react'
|
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 {type ActiveConvoStates} from '#/state/messages/convo'
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
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 {LeaveConvoPrompt} from '#/components/dms/LeaveConvoPrompt'
|
||||||
import {KnownFollowers} from '#/components/KnownFollowers'
|
import {KnownFollowers} from '#/components/KnownFollowers'
|
||||||
import {usePromptControl} from '#/components/Prompt'
|
import {usePromptControl} from '#/components/Prompt'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
import type * as bsky from '#/types/bsky'
|
||||||
import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons'
|
import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons'
|
||||||
|
|
||||||
export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) {
|
export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const leaveConvoControl = usePromptControl()
|
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
|
// if we ever allow someone other than the owner to invite people, this will need to change
|
||||||
const otherUser = convoState.convo.primaryMember
|
const otherUser = convoState.convo.primaryMember
|
||||||
|
|
||||||
|
const lastMessage = ChatBskyConvoDefs.isMessageView(
|
||||||
|
convoState.convo.view.lastMessage,
|
||||||
|
)
|
||||||
|
? convoState.convo.view.lastMessage
|
||||||
|
: null
|
||||||
|
|
||||||
if (!moderationOpts) {
|
if (!moderationOpts) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[t.atoms.bg, a.p_lg, a.gap_md, a.align_center]}>
|
<View style={[a.gap_md, a.p_2xl, t.atoms.bg]}>
|
||||||
|
<LinearGradient
|
||||||
|
colors={['rgba(0,0,0,0)', 'rgba(0,0,0,0.08)']}
|
||||||
|
style={[a.absolute, {top: -16, left: 0, right: 0, height: 16}]}
|
||||||
|
pointerEvents="none"
|
||||||
|
/>
|
||||||
|
{otherUser && (
|
||||||
|
<InviterHeader profile={otherUser} moderationOpts={moderationOpts} />
|
||||||
|
)}
|
||||||
{otherUser && (
|
{otherUser && (
|
||||||
<KnownFollowers
|
<KnownFollowers
|
||||||
profile={otherUser}
|
profile={otherUser}
|
||||||
moderationOpts={moderationOpts}
|
moderationOpts={moderationOpts}
|
||||||
|
minimal
|
||||||
showIfEmpty
|
showIfEmpty
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<View style={[a.flex_row, a.gap_md, a.w_full, otherUser && a.pt_sm]}>
|
<View style={[a.flex_row, a.gap_md, a.w_full, otherUser && a.pt_sm]}>
|
||||||
{otherUser && (
|
{otherUser && (
|
||||||
<RejectMenu
|
<RejectMenu
|
||||||
label={_(msg`Block or report`)}
|
label={lastMessage ? l`Block or report` : l`Block`}
|
||||||
|
icon={true}
|
||||||
convo={convoState.convo.view}
|
convo={convoState.convo.view}
|
||||||
profile={otherUser}
|
profile={otherUser}
|
||||||
color="negative_subtle"
|
color="negative_subtle"
|
||||||
size="small"
|
size="large"
|
||||||
currentScreen="conversation"
|
currentScreen="conversation"
|
||||||
|
style={[a.flex_1]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<DeleteChatButton
|
<DeleteChatButton
|
||||||
label={_(msg`Delete`)}
|
label={l({
|
||||||
|
message: 'Leave',
|
||||||
|
comment: 'Leave a conversation (reject a chat invitation)',
|
||||||
|
context: 'Button',
|
||||||
|
})}
|
||||||
|
icon={true}
|
||||||
convo={convoState.convo.view}
|
convo={convoState.convo.view}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="small"
|
size="large"
|
||||||
currentScreen="conversation"
|
currentScreen="conversation"
|
||||||
|
style={[a.flex_1]}
|
||||||
onPress={leaveConvoControl.open}
|
onPress={leaveConvoControl.open}
|
||||||
/>
|
/>
|
||||||
<LeaveConvoPrompt
|
<LeaveConvoPrompt
|
||||||
@@ -66,13 +96,53 @@ export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) {
|
|||||||
</View>
|
</View>
|
||||||
<View style={[a.w_full, a.flex_row]}>
|
<View style={[a.w_full, a.flex_row]}>
|
||||||
<AcceptChatButton
|
<AcceptChatButton
|
||||||
|
icon={true}
|
||||||
onAcceptConvo={onAcceptChat}
|
onAcceptConvo={onAcceptChat}
|
||||||
convo={convoState.convo.view}
|
convo={convoState.convo.view}
|
||||||
color="primary_subtle"
|
color="primary"
|
||||||
size="small"
|
size="large"
|
||||||
currentScreen="conversation"
|
currentScreen="conversation"
|
||||||
|
style={[a.flex_1]}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function InviterHeader({
|
||||||
|
profile: profileUnshadowed,
|
||||||
|
moderationOpts,
|
||||||
|
}: {
|
||||||
|
profile: bsky.profile.AnyProfileView
|
||||||
|
moderationOpts: NonNullable<ReturnType<typeof useModerationOpts>>
|
||||||
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
|
const profile = useProfileShadow(profileUnshadowed)
|
||||||
|
const moderation = useMemo(
|
||||||
|
() => moderateProfile(profile, moderationOpts),
|
||||||
|
[profile, moderationOpts],
|
||||||
|
)
|
||||||
|
const displayName = createSanitizedDisplayName(
|
||||||
|
profile,
|
||||||
|
true,
|
||||||
|
moderation.ui('displayName'),
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[a.flex_row, a.align_center, a.gap_sm]}>
|
||||||
|
<PreviewableUserAvatar
|
||||||
|
profile={profile}
|
||||||
|
size={42}
|
||||||
|
moderation={moderation.ui('avatar')}
|
||||||
|
/>
|
||||||
|
<View>
|
||||||
|
<Text style={[a.text_md, a.font_bold, t.atoms.text]}>
|
||||||
|
<Trans>{displayName} added you</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text style={[web(a.pt_xs), a.text_sm, t.atoms.text_contrast_high]}>
|
||||||
|
{sanitizeHandle(profile.handle, '@')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api'
|
import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
import {StackActions, useNavigation} from '@react-navigation/native'
|
import {StackActions, useNavigation} from '@react-navigation/native'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
@@ -16,7 +14,6 @@ import {
|
|||||||
unstableCacheProfileView,
|
unstableCacheProfileView,
|
||||||
useProfileBlockMutationQueue,
|
useProfileBlockMutationQueue,
|
||||||
} from '#/state/queries/profile'
|
} from '#/state/queries/profile'
|
||||||
import {atoms as a} from '#/alf'
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonIcon,
|
ButtonIcon,
|
||||||
@@ -29,6 +26,8 @@ import {
|
|||||||
useEmailDialogControl,
|
useEmailDialogControl,
|
||||||
} from '#/components/dialogs/EmailDialog'
|
} from '#/components/dialogs/EmailDialog'
|
||||||
import {AfterReportDialog} from '#/components/dms/AfterReportDialog'
|
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 {CircleX_Stroke2_Corner0_Rounded} from '#/components/icons/CircleX'
|
||||||
import {Flag_Stroke2_Corner0_Rounded as FlagIcon} from '#/components/icons/Flag'
|
import {Flag_Stroke2_Corner0_Rounded as FlagIcon} from '#/components/icons/Flag'
|
||||||
import {PersonX_Stroke2_Corner0_Rounded as PersonXIcon} from '#/components/icons/Person'
|
import {PersonX_Stroke2_Corner0_Rounded as PersonXIcon} from '#/components/icons/Person'
|
||||||
@@ -40,20 +39,22 @@ import * as Toast from '#/components/Toast'
|
|||||||
export function RejectMenu({
|
export function RejectMenu({
|
||||||
convo,
|
convo,
|
||||||
profile,
|
profile,
|
||||||
size = 'tiny',
|
size = 'small',
|
||||||
color = 'secondary',
|
color = 'secondary',
|
||||||
label,
|
label,
|
||||||
|
icon = false,
|
||||||
showDeleteConvo,
|
showDeleteConvo,
|
||||||
currentScreen,
|
currentScreen,
|
||||||
...props
|
...props
|
||||||
}: Omit<ButtonProps, 'onPress' | 'children' | 'label'> & {
|
}: Omit<ButtonProps, 'onPress' | 'children' | 'label'> & {
|
||||||
label?: string
|
label?: string
|
||||||
|
icon?: boolean
|
||||||
convo: ChatBskyConvoDefs.ConvoView
|
convo: ChatBskyConvoDefs.ConvoView
|
||||||
profile: ChatBskyActorDefs.ProfileViewBasic
|
profile: ChatBskyActorDefs.ProfileViewBasic
|
||||||
showDeleteConvo?: boolean
|
showDeleteConvo?: boolean
|
||||||
currentScreen: 'list' | 'conversation'
|
currentScreen: 'list' | 'conversation'
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const shadowedProfile = useProfileShadow(profile)
|
const shadowedProfile = useProfileShadow(profile)
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@@ -66,12 +67,10 @@ export function RejectMenu({
|
|||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l({
|
||||||
msg({
|
|
||||||
context: 'toast',
|
context: 'toast',
|
||||||
message: 'Failed to delete chat',
|
message: 'Failed to delete chat',
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
{
|
{
|
||||||
type: 'error',
|
type: 'error',
|
||||||
},
|
},
|
||||||
@@ -82,35 +81,31 @@ export function RejectMenu({
|
|||||||
|
|
||||||
const onPressDelete = useCallback(() => {
|
const onPressDelete = useCallback(() => {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l({
|
||||||
msg({
|
|
||||||
context: 'toast',
|
context: 'toast',
|
||||||
message: 'Chat deleted',
|
message: 'Chat deleted',
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
{
|
{
|
||||||
type: 'success',
|
type: 'success',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
leaveConvo()
|
leaveConvo()
|
||||||
}, [leaveConvo, _])
|
}, [leaveConvo, l])
|
||||||
|
|
||||||
const onPressBlock = useCallback(() => {
|
const onPressBlock = useCallback(() => {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l({
|
||||||
msg({
|
|
||||||
context: 'toast',
|
context: 'toast',
|
||||||
message: 'Account blocked',
|
message: 'Account blocked',
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
{
|
{
|
||||||
type: 'success',
|
type: 'success',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
// block and also delete convo
|
// block and also delete convo
|
||||||
queueBlock()
|
void queueBlock()
|
||||||
leaveConvo()
|
leaveConvo()
|
||||||
}, [queueBlock, leaveConvo, _])
|
}, [queueBlock, leaveConvo, l])
|
||||||
|
|
||||||
const reportControl = useDialogControl()
|
const reportControl = useDialogControl()
|
||||||
const blockOrDeleteControl = useDialogControl()
|
const blockOrDeleteControl = useDialogControl()
|
||||||
@@ -122,15 +117,15 @@ export function RejectMenu({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Menu.Root>
|
<Menu.Root>
|
||||||
<Menu.Trigger label={_(msg`Reject chat request`)}>
|
<Menu.Trigger label={l`Reject chat request`}>
|
||||||
{({props: triggerProps}) => (
|
{({props: triggerProps}) => (
|
||||||
<Button
|
<Button
|
||||||
{...triggerProps}
|
{...triggerProps}
|
||||||
{...props}
|
{...props}
|
||||||
label={triggerProps.accessibilityLabel}
|
label={triggerProps.accessibilityLabel}
|
||||||
style={[a.flex_1]}
|
|
||||||
color={color}
|
color={color}
|
||||||
size={size}>
|
size={size}>
|
||||||
|
{icon ? <ButtonIcon icon={FlagIcon} /> : null}
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
{label || (
|
{label || (
|
||||||
<Trans comment="Reject a chat request, this opens a menu with options">
|
<Trans comment="Reject a chat request, this opens a menu with options">
|
||||||
@@ -144,16 +139,14 @@ export function RejectMenu({
|
|||||||
<Menu.Outer showCancel>
|
<Menu.Outer showCancel>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
{showDeleteConvo && (
|
{showDeleteConvo && (
|
||||||
<Menu.Item
|
<Menu.Item label={l`Delete conversation`} onPress={onPressDelete}>
|
||||||
label={_(msg`Delete conversation`)}
|
|
||||||
onPress={onPressDelete}>
|
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Delete conversation</Trans>
|
<Trans>Delete conversation</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
<Menu.ItemIcon icon={CircleX_Stroke2_Corner0_Rounded} />
|
<Menu.ItemIcon icon={CircleX_Stroke2_Corner0_Rounded} />
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
)}
|
)}
|
||||||
<Menu.Item label={_(msg`Block account`)} onPress={onPressBlock}>
|
<Menu.Item label={l`Block account`} onPress={onPressBlock}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Block account</Trans>
|
<Trans>Block account</Trans>
|
||||||
</Menu.ItemText>
|
</Menu.ItemText>
|
||||||
@@ -164,7 +157,7 @@ export function RejectMenu({
|
|||||||
screen to have a message sent by you */}
|
screen to have a message sent by you */}
|
||||||
{lastMessage && (
|
{lastMessage && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
label={_(msg`Report conversation`)}
|
label={l`Report conversation`}
|
||||||
onPress={reportControl.open}>
|
onPress={reportControl.open}>
|
||||||
<Menu.ItemText>
|
<Menu.ItemText>
|
||||||
<Trans>Report conversation</Trans>
|
<Trans>Report conversation</Trans>
|
||||||
@@ -210,19 +203,21 @@ export function RejectMenu({
|
|||||||
|
|
||||||
export function AcceptChatButton({
|
export function AcceptChatButton({
|
||||||
convo,
|
convo,
|
||||||
size = 'tiny',
|
size = 'small',
|
||||||
color = 'secondary_inverted',
|
color = 'primary',
|
||||||
label,
|
label,
|
||||||
|
icon = false,
|
||||||
currentScreen,
|
currentScreen,
|
||||||
onAcceptConvo,
|
onAcceptConvo,
|
||||||
...props
|
...props
|
||||||
}: Omit<ButtonProps, 'onPress' | 'children' | 'label'> & {
|
}: Omit<ButtonProps, 'onPress' | 'children' | 'label'> & {
|
||||||
label?: string
|
label?: string
|
||||||
|
icon?: boolean
|
||||||
convo: ChatBskyConvoDefs.ConvoView
|
convo: ChatBskyConvoDefs.ConvoView
|
||||||
onAcceptConvo?: () => void
|
onAcceptConvo?: () => void
|
||||||
currentScreen: 'list' | 'conversation'
|
currentScreen: 'list' | 'conversation'
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {needsEmailVerification} = useEmail()
|
const {needsEmailVerification} = useEmail()
|
||||||
@@ -245,12 +240,10 @@ export function AcceptChatButton({
|
|||||||
// automatically. The only difference is that when they back out of the convo (without sending a message), the conversation will be rejected.
|
// automatically. The only difference is that when they back out of the convo (without sending a message), the conversation will be rejected.
|
||||||
// the list will still have this chat in it -sfn
|
// the list will still have this chat in it -sfn
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l({
|
||||||
msg({
|
|
||||||
context: 'toast',
|
context: 'toast',
|
||||||
message: 'Failed to accept chat',
|
message: 'Failed to accept chat',
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
{
|
{
|
||||||
type: 'error',
|
type: 'error',
|
||||||
},
|
},
|
||||||
@@ -274,38 +267,43 @@ export function AcceptChatButton({
|
|||||||
}
|
}
|
||||||
}, [acceptConvo, needsEmailVerification, emailDialogControl])
|
}, [acceptConvo, needsEmailVerification, emailDialogControl])
|
||||||
|
|
||||||
|
let Icon: React.ReactNode = null
|
||||||
|
if (isPending) {
|
||||||
|
Icon = <ButtonIcon icon={Loader} />
|
||||||
|
} else if (icon) {
|
||||||
|
Icon = <ButtonIcon icon={CheckIcon} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
{...props}
|
{...props}
|
||||||
label={label || _(msg`Accept chat request`)}
|
label={label || l`Accept chat request`}
|
||||||
size={size}
|
size={size}
|
||||||
color={color}
|
color={color}
|
||||||
style={a.flex_1}
|
|
||||||
onPress={onPressAccept}>
|
onPress={onPressAccept}>
|
||||||
{isPending ? (
|
{Icon}
|
||||||
<ButtonIcon icon={Loader} />
|
|
||||||
) : (
|
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
{label || <Trans comment="Accept a chat request">Accept</Trans>}
|
{label || <Trans comment="Accept a chat request">Accept</Trans>}
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
)}
|
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DeleteChatButton({
|
export function DeleteChatButton({
|
||||||
convo,
|
convo,
|
||||||
size = 'tiny',
|
size = 'small',
|
||||||
color = 'secondary',
|
color = 'secondary',
|
||||||
label,
|
label,
|
||||||
|
icon = false,
|
||||||
currentScreen,
|
currentScreen,
|
||||||
...props
|
...props
|
||||||
}: Omit<ButtonProps, 'children' | 'label'> & {
|
}: Omit<ButtonProps, 'children' | 'label'> & {
|
||||||
label?: string
|
label?: string
|
||||||
|
icon?: boolean
|
||||||
convo: ChatBskyConvoDefs.ConvoView
|
convo: ChatBskyConvoDefs.ConvoView
|
||||||
currentScreen: 'list' | 'conversation'
|
currentScreen: 'list' | 'conversation'
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
|
||||||
const {mutate: leaveConvo} = useLeaveConvo(convo.id, {
|
const {mutate: leaveConvo} = useLeaveConvo(convo.id, {
|
||||||
@@ -316,12 +314,10 @@ export function DeleteChatButton({
|
|||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l({
|
||||||
msg({
|
|
||||||
context: 'toast',
|
context: 'toast',
|
||||||
message: 'Failed to delete chat',
|
message: 'Failed to delete chat',
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
{
|
{
|
||||||
type: 'error',
|
type: 'error',
|
||||||
},
|
},
|
||||||
@@ -331,27 +327,25 @@ export function DeleteChatButton({
|
|||||||
|
|
||||||
const onPressDelete = useCallback(() => {
|
const onPressDelete = useCallback(() => {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
_(
|
l({
|
||||||
msg({
|
|
||||||
context: 'toast',
|
context: 'toast',
|
||||||
message: 'Chat deleted',
|
message: 'Chat deleted',
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
{
|
{
|
||||||
type: 'success',
|
type: 'success',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
leaveConvo()
|
leaveConvo()
|
||||||
}, [leaveConvo, _])
|
}, [leaveConvo, l])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
label={label || _(msg`Delete chat`)}
|
label={label || l`Delete chat`}
|
||||||
size={size}
|
size={size}
|
||||||
color={color}
|
color={color}
|
||||||
style={a.flex_1}
|
|
||||||
onPress={onPressDelete}
|
onPress={onPressDelete}
|
||||||
{...props}>
|
{...props}>
|
||||||
|
{icon ? <ButtonIcon icon={LeaveIcon} /> : null}
|
||||||
<ButtonText>{label || <Trans>Delete chat</Trans>}</ButtonText>
|
<ButtonText>{label || <Trans>Delete chat</Trans>}</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export function RequestListItem({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{/* spacer, since you can't nest pressables */}
|
{/* spacer, since you can't nest pressables */}
|
||||||
<View style={[a.pt_md, a.pb_xs, a.w_full, {opacity: 0}]} aria-hidden>
|
<View style={[a.py_lg, a.w_full, {opacity: 0}]} aria-hidden>
|
||||||
{/* Placeholder text so that it responds to the font height */}
|
{/* Placeholder text so that it responds to the font height */}
|
||||||
<Text style={[a.text_xs, a.leading_tight, a.font_semi_bold]}>
|
<Text style={[a.text_xs, a.leading_tight, a.font_semi_bold]}>
|
||||||
<Trans comment="Accept a chat request">Accept Request</Trans>
|
<Trans comment="Accept a chat request">Accept Request</Trans>
|
||||||
|
|||||||
Reference in New Issue
Block a user