[🐴] Show if user can be messaged in new chat search (#4021)

* show if user can be messaged

* allow 2 lines in handle field due to new text

* cannot -> can't

* rework canBeMessaged logic and move to new file

---------

Co-authored-by: Eric Bailey <git@esb.lol>
zio/stable
Samuel Newman 2024-05-15 16:05:17 +01:00 committed by GitHub
parent 2121b5f86f
commit ed8922281a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 61 additions and 17 deletions

View File

@ -136,6 +136,7 @@ let ListMaybePlaceholder = ({
onGoBack,
hideBackButton,
sideBorders,
topBorder = true,
}: {
isLoading: boolean
noEmpty?: boolean
@ -149,6 +150,7 @@ let ListMaybePlaceholder = ({
onGoBack?: () => void
hideBackButton?: boolean
sideBorders?: boolean
topBorder?: boolean
}): React.ReactNode => {
const t = useTheme()
const {_} = useLingui()
@ -165,7 +167,7 @@ let ListMaybePlaceholder = ({
{paddingTop: 175, paddingBottom: 110},
]}
sideBorders={sideBorders ?? gtMobile}
topBorder={!gtTablet}>
topBorder={topBorder && !gtTablet}>
<View style={[a.w_full, a.align_center, {top: 100}]}>
<Loader size="xl" />
</View>

View File

@ -197,6 +197,7 @@ function GifList({
onGoBack={onGoBack}
emptyType="results"
sideBorders={false}
topBorder={false}
errorTitle={_(msg`Failed to load GIFs`)}
errorMessage={_(msg`There was an issue connecting to Tenor.`)}
emptyMessage={

View File

@ -10,6 +10,7 @@ import {sanitizeHandle} from '#/lib/strings/handles'
import {isWeb} from '#/platform/detection'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useGetConvoForMembers} from '#/state/queries/messages/get-convo-for-members'
import {useSession} from '#/state/session'
import {useActorAutocompleteQuery} from 'state/queries/actor-autocomplete'
import {FAB} from '#/view/com/util/fab/FAB'
import * as Toast from '#/view/com/util/Toast'
@ -23,6 +24,7 @@ import {Button} from '../Button'
import {Envelope_Stroke2_Corner0_Rounded as Envelope} from '../icons/Envelope'
import {ListMaybePlaceholder} from '../Lists'
import {Text} from '../Typography'
import {canBeMessaged} from './util'
export function NewChat({
control,
@ -82,6 +84,7 @@ function SearchablePeopleList({
const moderationOpts = useModerationOpts()
const control = Dialog.useDialogContext()
const listRef = useRef<BottomSheetFlatListMethods>(null)
const {currentAccount} = useSession()
const [searchText, setSearchText] = useState('')
@ -95,12 +98,17 @@ function SearchablePeopleList({
const renderItem = useCallback(
({item: profile}: {item: AppBskyActorDefs.ProfileView}) => {
if (!moderationOpts) return null
const moderation = moderateProfile(profile, moderationOpts)
const disabled = !canBeMessaged(profile)
const handle = sanitizeHandle(profile.handle, '@')
return (
<Button
label={profile.displayName || sanitizeHandle(profile.handle)}
onPress={() => onCreateChat(profile.did)}>
{({hovered, pressed}) => (
onPress={() => !disabled && onCreateChat(profile.did)}>
{({hovered, pressed, focused}) => (
<View
style={[
a.flex_1,
@ -110,7 +118,9 @@ function SearchablePeopleList({
a.align_center,
a.flex_row,
a.rounded_sm,
pressed
disabled
? {opacity: 0.5}
: pressed || focused
? t.atoms.bg_contrast_25
: hovered
? t.atoms.bg_contrast_50
@ -131,8 +141,12 @@ function SearchablePeopleList({
moderation.ui('displayName'),
)}
</Text>
<Text style={t.atoms.text_contrast_high} numberOfLines={1}>
{sanitizeHandle(profile.handle, '@')}
<Text style={t.atoms.text_contrast_high} numberOfLines={2}>
{disabled ? (
<Trans>{handle} can't be messaged</Trans>
) : (
handle
)}
</Text>
</View>
</View>
@ -166,7 +180,6 @@ function SearchablePeopleList({
t.atoms.bg,
]}
/>
<Dialog.Close />
<Text
style={[
a.text_2xl,
@ -201,14 +214,23 @@ function SearchablePeopleList({
autoFocus
/>
</TextField.Root>
<Dialog.Close />
</View>
)
}, [t.atoms.bg, _, control, searchText])
const dataWithoutSelf = useMemo(() => {
return (
actorAutocompleteData?.filter(
profile => profile.did !== currentAccount?.did,
) ?? []
)
}, [actorAutocompleteData, currentAccount?.did])
return (
<Dialog.InnerFlatList
ref={listRef}
data={actorAutocompleteData}
data={dataWithoutSelf}
renderItem={renderItem}
ListHeaderComponent={
<>
@ -235,6 +257,7 @@ function SearchablePeopleList({
hideBackButton={true}
emptyType="results"
sideBorders={false}
topBorder={false}
emptyMessage={
isError
? _(msg`No search results found for "${searchText}".`)

View File

@ -0,0 +1,18 @@
import {AppBskyActorDefs} from '@atproto/api'
export function canBeMessaged(profile: AppBskyActorDefs.ProfileView) {
switch (profile.associated?.chat?.allowIncoming) {
case 'none':
return false
case 'all':
return true
// if unset, treat as following
case 'following':
case undefined:
return Boolean(profile.viewer?.followedBy)
// any other values are invalid according to the lexicon, so
// let's treat as false to be safe
default:
return false
}
}

View File

@ -1,4 +1,4 @@
import React from 'react'
import React, {useCallback, useState} from 'react'
import {View} from 'react-native'
import {
AppBskyActorDefs,
@ -88,22 +88,22 @@ function ChatListItemReady({
}
const navigation = useNavigation<NavigationProp>()
const [showActions, setShowActions] = React.useState(false)
const [showActions, setShowActions] = useState(false)
const onMouseEnter = React.useCallback(() => {
const onMouseEnter = useCallback(() => {
setShowActions(true)
}, [])
const onMouseLeave = React.useCallback(() => {
const onMouseLeave = useCallback(() => {
setShowActions(false)
}, [])
const onFocus = React.useCallback<React.FocusEventHandler>(e => {
const onFocus = useCallback<React.FocusEventHandler>(e => {
if (e.nativeEvent.relatedTarget == null) return
setShowActions(true)
}, [])
const onPress = React.useCallback(() => {
const onPress = useCallback(() => {
navigation.push('MessagesConversation', {
conversation: convo.id,
})
@ -119,9 +119,9 @@ function ChatListItemReady({
<Button
label={profile.displayName || profile.handle}
onPress={onPress}
style={a.flex_1}
style={[a.flex_1]}
onLongPress={isNative ? menuControl.open : undefined}>
{({hovered, pressed}) => (
{({hovered, pressed, focused}) => (
<View
style={[
a.flex_row,
@ -129,7 +129,7 @@ function ChatListItemReady({
a.px_lg,
a.py_md,
a.gap_md,
(hovered || pressed) && t.atoms.bg_contrast_25,
(hovered || pressed || focused) && t.atoms.bg_contrast_25,
t.atoms.border_contrast_low,
]}>
<UserAvatar