Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 6d68a5bd212dd4eeee816828ffe4e27601cdd7f3 167 lines 4.3 kB view raw
1import React from 'react' 2import { 3 ActivityIndicator, 4 StyleSheet, 5 TouchableOpacity, 6 View, 7 type ViewStyle, 8} from 'react-native' 9import {msg} from '@lingui/macro' 10import {useLingui} from '@lingui/react' 11import {StackActions, useNavigation} from '@react-navigation/native' 12 13import {usePalette} from '#/lib/hooks/usePalette' 14import {type NavigationProp} from '#/lib/routes/types' 15import {useModerationOpts} from '#/state/preferences/moderation-opts' 16import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete' 17import {Link} from '#/view/com/util/Link' 18import {Text} from '#/view/com/util/text/Text' 19import {SearchProfileCard} from '#/screens/Search/components/SearchProfileCard' 20import {atoms as a} from '#/alf' 21import {SearchInput} from '#/components/forms/SearchInput' 22 23let SearchLinkCard = ({ 24 label, 25 to, 26 onPress, 27 style, 28}: { 29 label: string 30 to?: string 31 onPress?: () => void 32 style?: ViewStyle 33}): React.ReactNode => { 34 const pal = usePalette('default') 35 36 const inner = ( 37 <View 38 style={[pal.border, {paddingVertical: 16, paddingHorizontal: 12}, style]}> 39 <Text type="md" style={[pal.text]}> 40 {label} 41 </Text> 42 </View> 43 ) 44 45 if (onPress) { 46 return ( 47 <TouchableOpacity 48 onPress={onPress} 49 accessibilityLabel={label} 50 accessibilityHint=""> 51 {inner} 52 </TouchableOpacity> 53 ) 54 } 55 56 return ( 57 <Link href={to} asAnchor anchorNoUnderline> 58 <View 59 style={[ 60 pal.border, 61 {paddingVertical: 16, paddingHorizontal: 12}, 62 style, 63 ]}> 64 <Text type="md" style={[pal.text]}> 65 {label} 66 </Text> 67 </View> 68 </Link> 69 ) 70} 71SearchLinkCard = React.memo(SearchLinkCard) 72export {SearchLinkCard} 73 74export function DesktopSearch() { 75 const {_} = useLingui() 76 const pal = usePalette('default') 77 const navigation = useNavigation<NavigationProp>() 78 const [isActive, setIsActive] = React.useState<boolean>(false) 79 const [query, setQuery] = React.useState<string>('') 80 const {data: autocompleteData, isFetching} = useActorAutocompleteQuery( 81 query, 82 true, 83 ) 84 85 const moderationOpts = useModerationOpts() 86 87 const onChangeText = React.useCallback((text: string) => { 88 setQuery(text) 89 setIsActive(text.length > 0) 90 }, []) 91 92 const onPressCancelSearch = React.useCallback(() => { 93 setQuery('') 94 setIsActive(false) 95 }, [setQuery]) 96 97 const onSubmit = React.useCallback(() => { 98 setIsActive(false) 99 if (!query.length) return 100 navigation.dispatch(StackActions.push('Search', {q: query})) 101 }, [query, navigation]) 102 103 const onSearchProfileCardPress = React.useCallback(() => { 104 setQuery('') 105 setIsActive(false) 106 }, []) 107 108 return ( 109 <View style={[styles.container, pal.view]}> 110 <SearchInput 111 value={query} 112 onChangeText={onChangeText} 113 onClearText={onPressCancelSearch} 114 onSubmitEditing={onSubmit} 115 /> 116 {query !== '' && isActive && moderationOpts && ( 117 <View 118 style={[ 119 pal.view, 120 pal.borderDark, 121 styles.resultsContainer, 122 a.overflow_hidden, 123 ]}> 124 {isFetching && !autocompleteData?.length ? ( 125 <View style={{padding: 8}}> 126 <ActivityIndicator /> 127 </View> 128 ) : ( 129 <> 130 <SearchLinkCard 131 label={_(msg`Search for "${query}"`)} 132 to={`/search?q=${encodeURIComponent(query)}`} 133 style={ 134 (autocompleteData?.length ?? 0) > 0 135 ? {borderBottomWidth: 1} 136 : undefined 137 } 138 /> 139 {autocompleteData?.map(item => ( 140 <SearchProfileCard 141 key={item.did} 142 profile={item} 143 moderationOpts={moderationOpts} 144 onPress={onSearchProfileCardPress} 145 /> 146 ))} 147 </> 148 )} 149 </View> 150 )} 151 </View> 152 ) 153} 154 155const styles = StyleSheet.create({ 156 container: { 157 position: 'relative', 158 width: '100%', 159 }, 160 resultsContainer: { 161 marginTop: 10, 162 flexDirection: 'column', 163 width: '100%', 164 borderWidth: 1, 165 borderRadius: 6, 166 }, 167})