import {useRef} from 'react' import {View} from 'react-native' import Animated, {FadeInDown, FadeOut} from 'react-native-reanimated' import {AppBskyActorDefs} from '@atproto/api' import {Trans} from '@lingui/macro' import {PressableScale} from '#/lib/custom-animations/PressableScale' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete' import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useTheme} from '#/alf' import {Text} from '#/components/Typography' import {useGrapheme} from '../hooks/useGrapheme' export function Autocomplete({ prefix, onSelect, }: { prefix: string onSelect: (item: string) => void }) { const t = useTheme() const {getGraphemeString} = useGrapheme() const isActive = !!prefix const {data: suggestions, isFetching} = useActorAutocompleteQuery(prefix) const suggestionsRef = useRef< AppBskyActorDefs.ProfileViewBasic[] | undefined >(undefined) if (suggestions) { suggestionsRef.current = suggestions } if (!isActive) return null return ( {suggestionsRef.current?.length ? ( suggestionsRef.current.slice(0, 5).map((item, index, arr) => { // Eventually use an average length const MAX_CHARS = 40 const MAX_HANDLE_CHARS = 20 // Using this approach because styling is not respecting // bounding box wrapping (before converting to ellipsis) const {name: displayHandle, remainingCharacters} = getGraphemeString( item.handle, MAX_HANDLE_CHARS, ) const {name: displayName} = getGraphemeString( item.displayName || item.handle, MAX_CHARS - MAX_HANDLE_CHARS + (remainingCharacters > 0 ? remainingCharacters : 0), ) return ( onSelect(item.handle)} accessibilityLabel={`Select ${item.handle}`} accessibilityHint=""> {sanitizeDisplayName(displayName)} {sanitizeHandle(displayHandle, '@')} ) }) ) : ( {isFetching ? Loading... : No result} )} ) }