forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useState} from 'react'
2import {type ListRenderItemInfo, View} from 'react-native'
3import {KeyboardAwareScrollView} from 'react-native-keyboard-controller'
4import {type AppBskyActorDefs, type ModerationOpts} from '@atproto/api'
5import {Trans} from '@lingui/macro'
6
7import {useA11y} from '#/state/a11y'
8import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
9import {useActorSearch} from '#/state/queries/actor-search'
10import {List} from '#/view/com/util/List'
11import {useWizardState} from '#/screens/StarterPack/Wizard/State'
12import {atoms as a, useTheme} from '#/alf'
13import {SearchInput} from '#/components/forms/SearchInput'
14import {Loader} from '#/components/Loader'
15import {ScreenTransition} from '#/components/ScreenTransition'
16import {WizardProfileCard} from '#/components/StarterPack/Wizard/WizardListCard'
17import {Text} from '#/components/Typography'
18import {IS_NATIVE} from '#/env'
19import type * as bsky from '#/types/bsky'
20
21function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic) {
22 return item?.did ?? ''
23}
24
25export function StepProfiles({
26 moderationOpts,
27}: {
28 moderationOpts: ModerationOpts
29}) {
30 const t = useTheme()
31 const [state, dispatch] = useWizardState()
32 const [query, setQuery] = useState('')
33 const {screenReaderEnabled} = useA11y()
34
35 const {
36 data: topPages,
37 fetchNextPage,
38 isLoading: isLoadingTopPages,
39 } = useActorSearch({
40 query: encodeURIComponent('*'),
41 })
42 const topFollowers = topPages?.pages
43 .flatMap(p => p.actors)
44 .filter(p => !p.associated?.labeler)
45
46 const {data: resultsUnfiltered, isFetching: isFetchingResults} =
47 useActorAutocompleteQuery(query, true, 12)
48 const results = resultsUnfiltered?.filter(p => !p.associated?.labeler)
49
50 const isLoading = isLoadingTopPages || isFetchingResults
51
52 const renderItem = ({
53 item,
54 }: ListRenderItemInfo<bsky.profile.AnyProfileView>) => {
55 return (
56 <WizardProfileCard
57 profile={item}
58 btnType="checkbox"
59 state={state}
60 dispatch={dispatch}
61 moderationOpts={moderationOpts}
62 />
63 )
64 }
65
66 return (
67 <ScreenTransition
68 style={[a.flex_1]}
69 direction={state.transitionDirection}
70 enabledWeb>
71 <View style={[a.border_b, t.atoms.border_contrast_medium]}>
72 <View style={[a.py_sm, a.px_md, {height: 60}]}>
73 <SearchInput
74 value={query}
75 onChangeText={setQuery}
76 onClearText={() => setQuery('')}
77 />
78 </View>
79 </View>
80 <List
81 data={query ? results : topFollowers}
82 renderItem={renderItem}
83 keyExtractor={keyExtractor}
84 renderScrollComponent={props => <KeyboardAwareScrollView {...props} />}
85 keyboardShouldPersistTaps="handled"
86 disableFullWindowScroll={true}
87 sideBorders={false}
88 style={[a.flex_1]}
89 onEndReached={
90 !query && !screenReaderEnabled ? () => fetchNextPage() : undefined
91 }
92 onEndReachedThreshold={IS_NATIVE ? 2 : 0.25}
93 keyboardDismissMode="on-drag"
94 ListEmptyComponent={
95 <View style={[a.flex_1, a.align_center, a.mt_lg, a.px_lg]}>
96 {isLoading ? (
97 <Loader size="lg" />
98 ) : (
99 <Text
100 style={[
101 a.font_semi_bold,
102 a.text_lg,
103 a.text_center,
104 a.mt_lg,
105 a.leading_snug,
106 ]}>
107 <Trans>Nobody was found. Try searching for someone else.</Trans>
108 </Text>
109 )}
110 </View>
111 }
112 />
113 </ScreenTransition>
114 )
115}