diff options
Diffstat (limited to 'src/screens/StarterPack/Wizard/StepFeeds.tsx')
-rw-r--r-- | src/screens/StarterPack/Wizard/StepFeeds.tsx | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/screens/StarterPack/Wizard/StepFeeds.tsx b/src/screens/StarterPack/Wizard/StepFeeds.tsx new file mode 100644 index 000000000..6752a95db --- /dev/null +++ b/src/screens/StarterPack/Wizard/StepFeeds.tsx @@ -0,0 +1,113 @@ +import React, {useState} from 'react' +import {ListRenderItemInfo, View} from 'react-native' +import {KeyboardAwareScrollView} from 'react-native-keyboard-controller' +import {AppBskyFeedDefs, ModerationOpts} from '@atproto/api' +import {Trans} from '@lingui/macro' + +import {useA11y} from '#/state/a11y' +import {DISCOVER_FEED_URI} from 'lib/constants' +import { + useGetPopularFeedsQuery, + useSavedFeeds, + useSearchPopularFeedsQuery, +} from 'state/queries/feed' +import {SearchInput} from 'view/com/util/forms/SearchInput' +import {List} from 'view/com/util/List' +import {useWizardState} from '#/screens/StarterPack/Wizard/State' +import {atoms as a, useTheme} from '#/alf' +import {useThrottledValue} from '#/components/hooks/useThrottledValue' +import {Loader} from '#/components/Loader' +import {ScreenTransition} from '#/components/StarterPack/Wizard/ScreenTransition' +import {WizardFeedCard} from '#/components/StarterPack/Wizard/WizardListCard' +import {Text} from '#/components/Typography' + +function keyExtractor(item: AppBskyFeedDefs.GeneratorView) { + return item.uri +} + +export function StepFeeds({moderationOpts}: {moderationOpts: ModerationOpts}) { + const t = useTheme() + const [state, dispatch] = useWizardState() + const [query, setQuery] = useState('') + const throttledQuery = useThrottledValue(query, 500) + const {screenReaderEnabled} = useA11y() + + const {data: savedFeedsAndLists} = useSavedFeeds() + const savedFeeds = savedFeedsAndLists?.feeds + .filter(f => f.type === 'feed' && f.view.uri !== DISCOVER_FEED_URI) + .map(f => f.view) as AppBskyFeedDefs.GeneratorView[] + + const {data: popularFeedsPages, fetchNextPage} = useGetPopularFeedsQuery({ + limit: 30, + }) + const popularFeeds = + popularFeedsPages?.pages + .flatMap(page => page.feeds) + .filter(f => !savedFeeds?.some(sf => sf?.uri === f.uri)) ?? [] + + const suggestedFeeds = savedFeeds?.concat(popularFeeds) + + const {data: searchedFeeds, isLoading: isLoadingSearch} = + useSearchPopularFeedsQuery({q: throttledQuery}) + + const renderItem = ({ + item, + }: ListRenderItemInfo<AppBskyFeedDefs.GeneratorView>) => { + return ( + <WizardFeedCard + generator={item} + state={state} + dispatch={dispatch} + moderationOpts={moderationOpts} + /> + ) + } + + return ( + <ScreenTransition style={[a.flex_1]} direction={state.transitionDirection}> + <View style={[a.border_b, t.atoms.border_contrast_medium]}> + <View style={[a.my_sm, a.px_md, {height: 40}]}> + <SearchInput + query={query} + onChangeQuery={t => setQuery(t)} + onPressCancelSearch={() => setQuery('')} + onSubmitQuery={() => {}} + /> + </View> + </View> + <List + data={query ? searchedFeeds : suggestedFeeds} + renderItem={renderItem} + keyExtractor={keyExtractor} + contentContainerStyle={{paddingTop: 6}} + onEndReached={ + !query && !screenReaderEnabled ? () => fetchNextPage() : undefined + } + onEndReachedThreshold={2} + renderScrollComponent={props => <KeyboardAwareScrollView {...props} />} + keyboardShouldPersistTaps="handled" + containWeb={true} + sideBorders={false} + style={{flex: 1}} + ListEmptyComponent={ + <View style={[a.flex_1, a.align_center, a.mt_lg, a.px_lg]}> + {isLoadingSearch ? ( + <Loader size="lg" /> + ) : ( + <Text + style={[ + a.font_bold, + a.text_lg, + a.text_center, + a.mt_lg, + a.leading_snug, + ]}> + <Trans>No feeds found. Try searching for something else.</Trans> + </Text> + )} + </View> + } + /> + </ScreenTransition> + ) +} |