import React from 'react' import { ActivityIndicator, StyleSheet, TextInput, TouchableOpacity, View, ViewStyle, } from 'react-native' import { AppBskyActorDefs, moderateProfile, ModerationDecision, } from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {StackActions, useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' import {makeProfileLink} from '#/lib/routes/links' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' import {s} from '#/lib/styles' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete' import {usePalette} from 'lib/hooks/usePalette' import {MagnifyingGlassIcon2} from 'lib/icons' import {NavigationProp} from 'lib/routes/types' import {precacheProfile} from 'state/queries/profile' import {Link} from '#/view/com/util/Link' import {UserAvatar} from '#/view/com/util/UserAvatar' import {Text} from 'view/com/util/text/Text' let SearchLinkCard = ({ label, to, onPress, style, }: { label: string to?: string onPress?: () => void style?: ViewStyle }): React.ReactNode => { const pal = usePalette('default') const inner = ( {label} ) if (onPress) { return ( {inner} ) } return ( {label} ) } SearchLinkCard = React.memo(SearchLinkCard) export {SearchLinkCard} let SearchProfileCard = ({ profile, moderation, onPress: onPressInner, }: { profile: AppBskyActorDefs.ProfileViewBasic moderation: ModerationDecision onPress: () => void }): React.ReactNode => { const pal = usePalette('default') const queryClient = useQueryClient() const onPress = React.useCallback(() => { precacheProfile(queryClient, profile) onPressInner() }, [queryClient, profile, onPressInner]) return ( {sanitizeDisplayName( profile.displayName || sanitizeHandle(profile.handle), moderation.ui('displayName'), )} {sanitizeHandle(profile.handle, '@')} ) } SearchProfileCard = React.memo(SearchProfileCard) export {SearchProfileCard} export function DesktopSearch() { const {_} = useLingui() const pal = usePalette('default') const navigation = useNavigation() const [isActive, setIsActive] = React.useState(false) const [query, setQuery] = React.useState('') const {data: autocompleteData, isFetching} = useActorAutocompleteQuery( query, true, ) const moderationOpts = useModerationOpts() const onChangeText = React.useCallback((text: string) => { setQuery(text) setIsActive(text.length > 0) }, []) const onPressCancelSearch = React.useCallback(() => { setQuery('') setIsActive(false) }, [setQuery]) const onSubmit = React.useCallback(() => { setIsActive(false) if (!query.length) return navigation.dispatch(StackActions.push('Search', {q: query})) }, [query, navigation]) const onSearchProfileCardPress = React.useCallback(() => { setQuery('') setIsActive(false) }, []) return ( {query ? ( Cancel ) : undefined} {query !== '' && isActive && moderationOpts && ( {isFetching && !autocompleteData?.length ? ( ) : ( <> 0 ? {borderBottomWidth: 1} : undefined } /> {autocompleteData?.map(item => ( ))} )} )} ) } const styles = StyleSheet.create({ container: { position: 'relative', width: 300, }, search: { paddingHorizontal: 16, paddingVertical: 2, width: 300, borderRadius: 20, }, inputContainer: { flexDirection: 'row', }, iconWrapper: { position: 'relative', top: 2, paddingVertical: 7, marginRight: 8, }, input: { flex: 1, fontSize: 18, width: '100%', paddingTop: 7, paddingBottom: 7, }, cancelBtn: { paddingRight: 4, paddingLeft: 10, paddingVertical: 7, }, resultsContainer: { marginTop: 10, flexDirection: 'column', width: 300, borderWidth: 1, borderRadius: 6, }, noResults: { textAlign: 'center', paddingVertical: 10, }, })