add for feeds
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
import React from 'react'
|
||||
import {ListRenderItemInfo} from 'react-native'
|
||||
import React, {useState} from 'react'
|
||||
import {ListRenderItemInfo, View} from 'react-native'
|
||||
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 {useWizardState} from '#/screens/StarterPack/Wizard/State'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {WizardFeedCard} from '#/components/StarterPack/Wizard/WizardFeedCard'
|
||||
import {WizardListEmpty} from '#/components/StarterPack/Wizard/WizardListEmpty'
|
||||
|
||||
function keyExtractor(item: GeneratorView) {
|
||||
return item.uri
|
||||
@@ -14,18 +19,54 @@ function keyExtractor(item: GeneratorView) {
|
||||
|
||||
export function StepFeeds() {
|
||||
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>) => {
|
||||
return <WizardFeedCard generator={item} state={state} dispatch={dispatch} />
|
||||
}
|
||||
|
||||
return (
|
||||
<List
|
||||
data={state.feeds}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={keyExtractor}
|
||||
style={[a.flex_1]}
|
||||
ListEmptyComponent={<WizardListEmpty type="feeds" />}
|
||||
/>
|
||||
<>
|
||||
<View style={[a.my_sm, a.px_md, {height: 40}]}>
|
||||
<SearchInput
|
||||
query={query}
|
||||
onChangeQuery={onChangeQuery}
|
||||
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 {ListRenderItemInfo, View} from 'react-native'
|
||||
import {KeyboardAwareScrollView} from 'react-native-keyboard-controller'
|
||||
import {AppBskyActorDefs} from '@atproto/api'
|
||||
|
||||
import {useActorAutocompleteQuery} from 'state/queries/actor-autocomplete'
|
||||
@@ -54,6 +55,7 @@ export function StepProfiles() {
|
||||
renderItem={renderItem}
|
||||
keyExtractor={keyExtractor}
|
||||
onEndReached={!query ? () => fetchNextPage() : undefined}
|
||||
renderScrollComponent={props => <KeyboardAwareScrollView {...props} />}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import {Keyboard, View} from 'react-native'
|
||||
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 {msg, Plural, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -186,20 +186,21 @@ function WizardInner() {
|
||||
<StepView />
|
||||
</Container>
|
||||
|
||||
{state.currentStep === 'Details' && (
|
||||
{state.currentStep === 'Details' ? (
|
||||
<Button
|
||||
label={uiStrings.nextBtn}
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="medium"
|
||||
style={[a.mx_xl, a.my_5xl]}
|
||||
onPress={onNext}>
|
||||
onPress={onNext}
|
||||
disabled={!state.canNext}>
|
||||
<ButtonText>{uiStrings.nextBtn}</ButtonText>
|
||||
</Button>
|
||||
) : (
|
||||
<Footer onNext={onNext} nextBtnText={uiStrings.nextBtn} />
|
||||
)}
|
||||
|
||||
<Footer onNext={onNext} nextBtnText={uiStrings.nextBtn} />
|
||||
|
||||
{(state.currentStep === 'Profiles' || state.currentStep === 'Feeds') && (
|
||||
<WizardAddDialog
|
||||
control={addDialogControl}
|
||||
@@ -274,9 +275,9 @@ function Footer({
|
||||
},
|
||||
]}>
|
||||
<View style={[a.flex_row, a.gap_xs]}>
|
||||
{items.slice(0, 5).map(p => (
|
||||
{items.slice(0, 5).map((p, index) => (
|
||||
<UserAvatar
|
||||
key={p.did}
|
||||
key={index}
|
||||
avatar={p.avatar}
|
||||
size={28}
|
||||
type={state.currentStep === 'Profiles' ? 'user' : 'algo'}
|
||||
@@ -363,11 +364,11 @@ function Footer({
|
||||
}
|
||||
|
||||
function getName(item: AppBskyActorDefs.ProfileViewBasic | GeneratorView) {
|
||||
if (AppBskyActorDefs.isProfileView(item)) {
|
||||
return enforceLen(item.displayName || item.handle, 16)
|
||||
}
|
||||
if (AppBskyFeedDefs.isGeneratorView(item)) {
|
||||
return enforceLen(item.displayName, 16)
|
||||
// TODO hack for now since these are not full profiles and wont validate
|
||||
if (typeof item.displayName === 'string') {
|
||||
return enforceLen(item.displayName, 16, true)
|
||||
} else if (typeof item.handle === 'string') {
|
||||
return enforceLen(item.handle, 16, true)
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user