import React, {useCallback, useMemo, useRef, useState} from 'react' import {Keyboard, View} from 'react-native' import {AppBskyActorDefs, moderateProfile} from '@atproto/api' import {BottomSheetFlatListMethods} from '@discord/bottom-sheet' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {sanitizeDisplayName} from '#/lib/strings/display-names' 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 {useActorAutocompleteQuery} from 'state/queries/actor-autocomplete' import {FAB} from '#/view/com/util/fab/FAB' import * as Toast from '#/view/com/util/Toast' import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useTheme, web} from '#/alf' import * as Dialog from '#/components/Dialog' import * as TextField from '#/components/forms/TextField' import {MagnifyingGlass2_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass2' import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {Button} from '../Button' import {Envelope_Stroke2_Corner0_Rounded as Envelope} from '../icons/Envelope' import {ListMaybePlaceholder} from '../Lists' import {Text} from '../Typography' export function NewChat({ control, onNewChat, }: { control: Dialog.DialogControlProps onNewChat: (chatId: string) => void }) { const t = useTheme() const {_} = useLingui() const {mutate: createChat} = useGetConvoForMembers({ onSuccess: data => { onNewChat(data.convo.id) }, onError: error => { Toast.show(error.message) }, }) const onCreateChat = useCallback( (did: string) => { control.close(() => createChat([did])) }, [control, createChat], ) return ( <> } accessibilityRole="button" accessibilityLabel={_(msg`New chat`)} accessibilityHint="" /> ) } function SearchablePeopleList({ onCreateChat, }: { onCreateChat: (did: string) => void }) { const t = useTheme() const {_} = useLingui() const moderationOpts = useModerationOpts() const control = Dialog.useDialogContext() const listRef = useRef(null) const [searchText, setSearchText] = useState('') const { data: actorAutocompleteData, isFetching, isError, refetch, } = useActorAutocompleteQuery(searchText, true) const renderItem = useCallback( ({item: profile}: {item: AppBskyActorDefs.ProfileView}) => { if (!moderationOpts) return null const moderation = moderateProfile(profile, moderationOpts) return ( ) }, [ moderationOpts, onCreateChat, t.atoms.bg_contrast_25, t.atoms.bg_contrast_50, t.atoms.bg, t.atoms.text, t.atoms.text_contrast_high, ], ) const listHeader = useMemo(() => { return ( {/* cover top corners */} Start a new chat { setSearchText(text) listRef.current?.scrollToOffset({offset: 0, animated: false}) }} returnKeyType="search" clearButtonMode="while-editing" maxLength={50} onKeyPress={({nativeEvent}) => { if (nativeEvent.key === 'Escape') { control.close() } }} autoCorrect={false} autoComplete="off" autoCapitalize="none" autoFocus /> ) }, [t.atoms.bg, _, control, searchText]) return ( {listHeader} {searchText.length === 0 ? ( Search for someone to start a conversation with. ) : ( !actorAutocompleteData?.length && ( ) )} } stickyHeaderIndices={[0]} keyExtractor={(item: AppBskyActorDefs.ProfileView) => item.did} // @ts-expect-error web only style={isWeb && {minHeight: '100vh'}} onScrollBeginDrag={() => Keyboard.dismiss()} /> ) }