add for feeds

This commit is contained in:
Hailey
2024-06-05 23:58:32 -07:00
parent 695099d4d2
commit a724d24955
4 changed files with 66 additions and 62 deletions
@@ -1,40 +0,0 @@
import React from 'react'
import {View} from 'react-native'
import {Trans} from '@lingui/macro'
import {atoms as a, useTheme} from '#/alf'
import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
import {UserCircle_Stroke2_Corner0_Rounded as UserCircle} from '#/components/icons/UserCircle'
import {Text} from '#/components/Typography'
export function WizardListEmpty({type}: {type: 'profiles' | 'feeds'}) {
const t = useTheme()
return (
<View
style={[a.flex_1, a.px_md, a.align_center, a.gap_md, {marginTop: 100}]}>
{type === 'profiles' ? (
<UserCircle
width={100}
height={100}
style={t.atoms.text_contrast_medium}
/>
) : (
<Hashtag
width={100}
height={100}
style={t.atoms.text_contrast_medium}
/>
)}
<Text style={[a.text_md, a.text_center, t.atoms.text_contrast_medium]}>
{type === 'profiles' ? (
<Trans>
Search for people that you want to suggest others to follow
</Trans>
) : (
<Trans>Add some cool feeds!</Trans>
)}
</Text>
</View>
)
}
+51 -10
View File
@@ -1,12 +1,17 @@
import React from 'react' import React, {useState} from 'react'
import {ListRenderItemInfo} from 'react-native' import {ListRenderItemInfo, View} from 'react-native'
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
import debounce from 'lodash.debounce'
import {
useGetPopularFeedsQuery,
useSearchPopularFeedsMutation,
} from 'state/queries/feed'
import {SearchInput} from 'view/com/util/forms/SearchInput'
import {List} from 'view/com/util/List' import {List} from 'view/com/util/List'
import {useWizardState} from '#/screens/StarterPack/Wizard/State' import {useWizardState} from '#/screens/StarterPack/Wizard/State'
import {atoms as a} from '#/alf' import {atoms as a} from '#/alf'
import {WizardFeedCard} from '#/components/StarterPack/Wizard/WizardFeedCard' import {WizardFeedCard} from '#/components/StarterPack/Wizard/WizardFeedCard'
import {WizardListEmpty} from '#/components/StarterPack/Wizard/WizardListEmpty'
function keyExtractor(item: GeneratorView) { function keyExtractor(item: GeneratorView) {
return item.uri return item.uri
@@ -14,18 +19,54 @@ function keyExtractor(item: GeneratorView) {
export function StepFeeds() { export function StepFeeds() {
const [state, dispatch] = useWizardState() const [state, dispatch] = useWizardState()
const [query, setQuery] = useState('')
const {data: popularFeedsPages, fetchNextPage} = useGetPopularFeedsQuery()
const popularFeeds =
popularFeedsPages?.pages.flatMap(page => page.feeds) || []
const {
data: searchedFeeds,
mutate: search,
reset: resetSearch,
} = useSearchPopularFeedsMutation()
const debouncedSearch = React.useMemo(
() => debounce(q => search(q), 500), // debounce for 500ms
[search],
)
const onChangeQuery = (text: string) => {
setQuery(text)
if (text.length > 1) {
debouncedSearch(text)
} else {
resetSearch()
}
}
const renderItem = ({item}: ListRenderItemInfo<GeneratorView>) => { const renderItem = ({item}: ListRenderItemInfo<GeneratorView>) => {
return <WizardFeedCard generator={item} state={state} dispatch={dispatch} /> return <WizardFeedCard generator={item} state={state} dispatch={dispatch} />
} }
return ( return (
<List <>
data={state.feeds} <View style={[a.my_sm, a.px_md, {height: 40}]}>
renderItem={renderItem} <SearchInput
keyExtractor={keyExtractor} query={query}
style={[a.flex_1]} onChangeQuery={onChangeQuery}
ListEmptyComponent={<WizardListEmpty type="feeds" />} onPressCancelSearch={() => setQuery('')}
/> onSubmitQuery={() => {}}
/>
</View>
<List
data={query ? searchedFeeds : popularFeeds}
renderItem={renderItem}
keyExtractor={keyExtractor}
style={[a.flex_1]}
onEndReached={!query ? () => fetchNextPage() : undefined}
/>
</>
) )
} }
@@ -1,5 +1,6 @@
import React, {useState} from 'react' import React, {useState} from 'react'
import {ListRenderItemInfo, View} from 'react-native' import {ListRenderItemInfo, View} from 'react-native'
import {KeyboardAwareScrollView} from 'react-native-keyboard-controller'
import {AppBskyActorDefs} from '@atproto/api' import {AppBskyActorDefs} from '@atproto/api'
import {useActorAutocompleteQuery} from 'state/queries/actor-autocomplete' import {useActorAutocompleteQuery} from 'state/queries/actor-autocomplete'
@@ -54,6 +55,7 @@ export function StepProfiles() {
renderItem={renderItem} renderItem={renderItem}
keyExtractor={keyExtractor} keyExtractor={keyExtractor}
onEndReached={!query ? () => fetchNextPage() : undefined} onEndReached={!query ? () => fetchNextPage() : undefined}
renderScrollComponent={props => <KeyboardAwareScrollView {...props} />}
/> />
</> </>
) )
+13 -12
View File
@@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import {Keyboard, View} from 'react-native' import {Keyboard, View} from 'react-native'
import {KeyboardAwareScrollView} from 'react-native-keyboard-controller' import {KeyboardAwareScrollView} from 'react-native-keyboard-controller'
import {AppBskyActorDefs, AppBskyFeedDefs} from '@atproto/api' import {AppBskyActorDefs} from '@atproto/api'
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
import {msg, Plural, Trans} from '@lingui/macro' import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
@@ -186,20 +186,21 @@ function WizardInner() {
<StepView /> <StepView />
</Container> </Container>
{state.currentStep === 'Details' && ( {state.currentStep === 'Details' ? (
<Button <Button
label={uiStrings.nextBtn} label={uiStrings.nextBtn}
variant="solid" variant="solid"
color="primary" color="primary"
size="medium" size="medium"
style={[a.mx_xl, a.my_5xl]} style={[a.mx_xl, a.my_5xl]}
onPress={onNext}> onPress={onNext}
disabled={!state.canNext}>
<ButtonText>{uiStrings.nextBtn}</ButtonText> <ButtonText>{uiStrings.nextBtn}</ButtonText>
</Button> </Button>
) : (
<Footer onNext={onNext} nextBtnText={uiStrings.nextBtn} />
)} )}
<Footer onNext={onNext} nextBtnText={uiStrings.nextBtn} />
{(state.currentStep === 'Profiles' || state.currentStep === 'Feeds') && ( {(state.currentStep === 'Profiles' || state.currentStep === 'Feeds') && (
<WizardAddDialog <WizardAddDialog
control={addDialogControl} control={addDialogControl}
@@ -274,9 +275,9 @@ function Footer({
}, },
]}> ]}>
<View style={[a.flex_row, a.gap_xs]}> <View style={[a.flex_row, a.gap_xs]}>
{items.slice(0, 5).map(p => ( {items.slice(0, 5).map((p, index) => (
<UserAvatar <UserAvatar
key={p.did} key={index}
avatar={p.avatar} avatar={p.avatar}
size={28} size={28}
type={state.currentStep === 'Profiles' ? 'user' : 'algo'} type={state.currentStep === 'Profiles' ? 'user' : 'algo'}
@@ -363,11 +364,11 @@ function Footer({
} }
function getName(item: AppBskyActorDefs.ProfileViewBasic | GeneratorView) { function getName(item: AppBskyActorDefs.ProfileViewBasic | GeneratorView) {
if (AppBskyActorDefs.isProfileView(item)) { // TODO hack for now since these are not full profiles and wont validate
return enforceLen(item.displayName || item.handle, 16) if (typeof item.displayName === 'string') {
} return enforceLen(item.displayName, 16, true)
if (AppBskyFeedDefs.isGeneratorView(item)) { } else if (typeof item.handle === 'string') {
return enforceLen(item.displayName, 16) return enforceLen(item.handle, 16, true)
} }
return '' return ''
} }