Bluesky app fork with some witchin' additions 馃挮
witchsky.app
bluesky
fork
client
1import {useState} from 'react'
2import {View} from 'react-native'
3import {useSift} from '@bsky.app/sift'
4import {StackActions, useNavigation} from '@react-navigation/native'
5
6import {type NavigationProp} from '#/lib/routes/types'
7import {atoms as a} from '#/alf'
8import {
9 Autocomplete as AutocompleteBase,
10 type AutocompleteItem,
11 useAutocomplete,
12} from '#/components/Autocomplete'
13import {SearchInput} from '#/components/forms/SearchInput'
14
15export function DesktopSearch() {
16 const navigation = useNavigation<NavigationProp>()
17 const [active, setActive] = useState(false)
18 const [query, setQuery] = useState<string>('')
19 const showResults = active && !!query.length
20
21 const sift = useSift({
22 offset: a.p_sm.padding,
23 placement: 'bottom',
24 })
25
26 const onFocus = () => {
27 if (query.length) setActive(true)
28 }
29
30 const onChangeText = (text: string) => {
31 setQuery(text)
32 if (!active) {
33 setActive(true)
34 }
35 }
36
37 const onClearText = () => {
38 setQuery('')
39 setActive(false)
40 }
41
42 const onSubmit = () => {
43 if (!query.length) return
44 onClearText()
45 sift.elements.input.blur()
46 navigation.dispatch(StackActions.push('Search', {q: query}))
47 }
48
49 const onSelect = (item: AutocompleteItem) => {
50 if (item.type === 'profile') {
51 onClearText()
52 sift.elements.input.blur()
53 navigation.navigate('Profile', {name: item.profile.handle})
54 } else if (item.type === 'search') {
55 onClearText()
56 sift.elements.input.blur()
57 navigation.navigate('Search', {q: item.value})
58 }
59 }
60
61 return (
62 <View collapsable={false} ref={sift.refs.setAnchor}>
63 <SearchInput
64 hotkey
65 value={query}
66 onFocus={onFocus}
67 onChangeText={onChangeText}
68 onClearText={onClearText}
69 onSubmitEditing={onSubmit}
70 {...sift.targetProps}
71 />
72 {showResults && (
73 <Inner
74 query={query}
75 sift={sift}
76 onSelect={onSelect}
77 onDismiss={() => setActive(false)}
78 />
79 )}
80 </View>
81 )
82}
83
84function Inner({
85 query,
86 sift,
87 onSelect,
88 onDismiss,
89}: {
90 query: string
91 sift: ReturnType<typeof useSift>
92 onSelect: (item: AutocompleteItem) => void
93 onDismiss: () => void
94}) {
95 const {items} = useAutocomplete({
96 type: 'profile',
97 query,
98 showSearchFallback: true,
99 })
100
101 return items && items.length ? (
102 <AutocompleteBase
103 sift={sift}
104 data={items}
105 onSelect={onSelect}
106 onDismiss={onDismiss}
107 />
108 ) : null
109}