diff --git a/src/screens/Feeds/Wizard/State.tsx b/src/screens/Feeds/Wizard/State.tsx
index f65933fbb0..8e25229b3f 100644
--- a/src/screens/Feeds/Wizard/State.tsx
+++ b/src/screens/Feeds/Wizard/State.tsx
@@ -5,13 +5,10 @@ import {
AppBskyGraphStarterpack,
} from '@atproto/api'
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
-import {msg} from '@lingui/macro'
-import {STARTER_PACK_MAX_SIZE} from '#/lib/constants'
import {useSession} from '#/state/session'
-import * as Toast from '#/view/com/util/Toast'
-const steps = ['Details', 'Profiles', 'Feeds'] as const
+const steps = ['Details'] as const
type Step = (typeof steps)[number]
type Action =
@@ -20,10 +17,6 @@ type Action =
| {type: 'SetCanNext'; canNext: boolean}
| {type: 'SetName'; name: string}
| {type: 'SetDescription'; description: string}
- | {type: 'AddProfile'; profile: AppBskyActorDefs.ProfileViewBasic}
- | {type: 'RemoveProfile'; profileDid: string}
- | {type: 'AddFeed'; feed: GeneratorView}
- | {type: 'RemoveFeed'; feedUri: string}
| {type: 'SetProcessing'; processing: boolean}
| {type: 'SetError'; error: string}
@@ -52,7 +45,7 @@ function reducer(state: State, action: Action): State {
// -- Navigation
const currentIndex = steps.indexOf(state.currentStep)
- if (action.type === 'Next' && state.currentStep !== 'Feeds') {
+ if (action.type === 'Next') {
updatedState = {
...state,
currentStep: steps[currentIndex + 1],
@@ -73,38 +66,6 @@ function reducer(state: State, action: Action): State {
case 'SetDescription':
updatedState = {...state, description: action.description}
break
- case 'AddProfile':
- if (state.profiles.length > STARTER_PACK_MAX_SIZE) {
- Toast.show(
- msg`You may only add up to ${STARTER_PACK_MAX_SIZE} profiles`
- .message ?? '',
- 'info',
- )
- } else {
- updatedState = {...state, profiles: [...state.profiles, action.profile]}
- }
- break
- case 'RemoveProfile':
- updatedState = {
- ...state,
- profiles: state.profiles.filter(
- profile => profile.did !== action.profileDid,
- ),
- }
- break
- case 'AddFeed':
- if (state.feeds.length >= 3) {
- Toast.show(msg`You may only add up to 3 feeds`.message ?? '', 'info')
- } else {
- updatedState = {...state, feeds: [...state.feeds, action.feed]}
- }
- break
- case 'RemoveFeed':
- updatedState = {
- ...state,
- feeds: state.feeds.filter(f => f.uri !== action.feedUri),
- }
- break
case 'SetProcessing':
updatedState = {...state, processing: action.processing}
break
diff --git a/src/screens/Feeds/Wizard/StepDetails.tsx b/src/screens/Feeds/Wizard/StepDetails.tsx
index 4ee2cada97..11a3db9fda 100644
--- a/src/screens/Feeds/Wizard/StepDetails.tsx
+++ b/src/screens/Feeds/Wizard/StepDetails.tsx
@@ -29,24 +29,22 @@ export function StepDetails() {
- Invites, but personal
+ Your own feed
-
- Invite your friends to follow your favorite feeds and people
-
+ Curate your and other people's posts into a feed
- What do you want to call your starter pack?
+ What do you want to call your feed?
dispatch({type: 'SetName', name: text})}
@@ -67,7 +65,7 @@ export function StepDetails() {
label={_(
msg`${
currentProfile?.displayName || currentProfile?.handle
- }'s favorite feeds and people - join me!`,
+ }'s favorite posts`,
)}
value={state.description}
onChangeText={text =>
diff --git a/src/screens/Feeds/Wizard/StepFeeds.tsx b/src/screens/Feeds/Wizard/StepFeeds.tsx
deleted file mode 100644
index 0cf6ab2312..0000000000
--- a/src/screens/Feeds/Wizard/StepFeeds.tsx
+++ /dev/null
@@ -1,126 +0,0 @@
-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 {DISCOVER_FEED_URI} from '#/lib/constants'
-import {useA11y} from '#/state/a11y'
-import {
- useGetPopularFeedsQuery,
- usePopularFeedsSearch,
- useSavedFeeds,
-} from '#/state/queries/feed'
-import {List} from '#/view/com/util/List'
-import {useWizardState} from '#/screens/StarterPack/Wizard/State'
-import {atoms as a, useTheme} from '#/alf'
-import {SearchInput} from '#/components/forms/SearchInput'
-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, isFetchedAfterMount: isFetchedSavedFeeds} =
- 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,
- isLoading: isLoadingPopularFeeds,
- } = useGetPopularFeedsQuery({
- limit: 30,
- })
- const popularFeeds = popularFeedsPages?.pages.flatMap(p => p.feeds) ?? []
-
- // If we have saved feeds already loaded, display them immediately
- // Then, when popular feeds have loaded we can concat them to the saved feeds
- const suggestedFeeds =
- savedFeeds || isFetchedSavedFeeds
- ? popularFeeds
- ? savedFeeds.concat(
- popularFeeds.filter(f => !savedFeeds.some(sf => sf.uri === f.uri)),
- )
- : savedFeeds
- : undefined
-
- const {data: searchedFeeds, isFetching: isFetchingSearchedFeeds} =
- usePopularFeedsSearch({query: throttledQuery})
-
- const isLoading =
- !isFetchedSavedFeeds || isLoadingPopularFeeds || isFetchingSearchedFeeds
-
- const renderItem = ({
- item,
- }: ListRenderItemInfo) => {
- return (
-
- )
- }
-
- return (
-
-
-
- setQuery(t)}
- onClearText={() => setQuery('')}
- />
-
-
- fetchNextPage() : undefined
- }
- onEndReachedThreshold={2}
- renderScrollComponent={props => }
- keyboardShouldPersistTaps="handled"
- disableFullWindowScroll={true}
- sideBorders={false}
- style={{flex: 1}}
- ListEmptyComponent={
-
- {isLoading ? (
-
- ) : (
-
- No feeds found. Try searching for something else.
-
- )}
-
- }
- />
-
- )
-}
diff --git a/src/screens/Feeds/Wizard/StepProfiles.tsx b/src/screens/Feeds/Wizard/StepProfiles.tsx
deleted file mode 100644
index 054a6a63e2..0000000000
--- a/src/screens/Feeds/Wizard/StepProfiles.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-import React, {useState} from 'react'
-import {ListRenderItemInfo, View} from 'react-native'
-import {KeyboardAwareScrollView} from 'react-native-keyboard-controller'
-import {AppBskyActorDefs, ModerationOpts} from '@atproto/api'
-import {Trans} from '@lingui/macro'
-
-import {isNative} from '#/platform/detection'
-import {useA11y} from '#/state/a11y'
-import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
-import {useActorSearchPaginated} from '#/state/queries/actor-search'
-import {List} from '#/view/com/util/List'
-import {useWizardState} from '#/screens/StarterPack/Wizard/State'
-import {atoms as a, useTheme} from '#/alf'
-import {SearchInput} from '#/components/forms/SearchInput'
-import {Loader} from '#/components/Loader'
-import {ScreenTransition} from '#/components/StarterPack/Wizard/ScreenTransition'
-import {WizardProfileCard} from '#/components/StarterPack/Wizard/WizardListCard'
-import {Text} from '#/components/Typography'
-
-function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic) {
- return item?.did ?? ''
-}
-
-export function StepProfiles({
- moderationOpts,
-}: {
- moderationOpts: ModerationOpts
-}) {
- const t = useTheme()
- const [state, dispatch] = useWizardState()
- const [query, setQuery] = useState('')
- const {screenReaderEnabled} = useA11y()
-
- const {
- data: topPages,
- fetchNextPage,
- isLoading: isLoadingTopPages,
- } = useActorSearchPaginated({
- query: encodeURIComponent('*'),
- })
- const topFollowers = topPages?.pages
- .flatMap(p => p.actors)
- .filter(p => !p.associated?.labeler)
-
- const {data: resultsUnfiltered, isFetching: isFetchingResults} =
- useActorAutocompleteQuery(query, true, 12)
- const results = resultsUnfiltered?.filter(p => !p.associated?.labeler)
-
- const isLoading = isLoadingTopPages || isFetchingResults
-
- const renderItem = ({
- item,
- }: ListRenderItemInfo) => {
- return (
-
- )
- }
-
- return (
-
-
-
- setQuery('')}
- />
-
-
- }
- keyboardShouldPersistTaps="handled"
- disableFullWindowScroll={true}
- sideBorders={false}
- style={[a.flex_1]}
- onEndReached={
- !query && !screenReaderEnabled ? () => fetchNextPage() : undefined
- }
- onEndReachedThreshold={isNative ? 2 : 0.25}
- ListEmptyComponent={
-
- {isLoading ? (
-
- ) : (
-
- Nobody was found. Try searching for someone else.
-
- )}
-
- }
- />
-
- )
-}
diff --git a/src/screens/Feeds/Wizard/index.tsx b/src/screens/Feeds/Wizard/index.tsx
index d7948cec0d..ad37f8855f 100644
--- a/src/screens/Feeds/Wizard/index.tsx
+++ b/src/screens/Feeds/Wizard/index.tsx
@@ -1,37 +1,27 @@
import React from 'react'
-import {Keyboard, TouchableOpacity, View} from 'react-native'
+import {TouchableOpacity, View} from 'react-native'
import {
KeyboardAwareScrollView,
useKeyboardController,
} from 'react-native-keyboard-controller'
-import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {Image} from 'expo-image'
-import {
- AppBskyActorDefs,
- AppBskyGraphDefs,
- AtUri,
- ModerationOpts,
-} from '@atproto/api'
-import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
+import {AppBskyGraphDefs, AtUri} from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {msg, Plural, Trans} from '@lingui/macro'
+import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {NativeStackScreenProps} from '@react-navigation/native-stack'
-import {HITSLOP_10, STARTER_PACK_MAX_SIZE} from '#/lib/constants'
+import {HITSLOP_10} from '#/lib/constants'
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
import {logEvent} from '#/lib/statsig/statsig'
-import {sanitizeDisplayName} from '#/lib/strings/display-names'
-import {sanitizeHandle} from '#/lib/strings/handles'
-import {enforceLen} from '#/lib/strings/helpers'
import {
getStarterPackOgCard,
parseStarterPackUri,
} from '#/lib/strings/starter-pack'
import {logger} from '#/logger'
-import {isAndroid, isNative, isWeb} from '#/platform/detection'
+import {isAndroid, isWeb} from '#/platform/detection'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useAllListMembersQuery} from '#/state/queries/list-members'
import {useProfileQuery} from '#/state/queries/profile'
@@ -43,21 +33,15 @@ import {
import {useSession} from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell'
import * as Toast from '#/view/com/util/Toast'
-import {UserAvatar} from '#/view/com/util/UserAvatar'
import {CenteredView} from '#/view/com/util/Views'
import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
-import {useDialogControl} from '#/components/Dialog'
import * as Layout from '#/components/Layout'
import {ListMaybePlaceholder} from '#/components/Lists'
-import {Loader} from '#/components/Loader'
-import {WizardEditListDialog} from '#/components/StarterPack/Wizard/WizardEditListDialog'
import {Text} from '#/components/Typography'
import {useWizardState, WizardStep} from './State'
import {Provider} from './State'
import {StepDetails} from './StepDetails'
-import {StepFeeds} from './StepFeeds'
-import {StepProfiles} from './StepProfiles'
export function Wizard({
route,
@@ -123,8 +107,6 @@ export function Wizard({
@@ -134,13 +116,9 @@ export function Wizard({
function WizardInner({
currentStarterPack,
currentListItems,
- profile,
- moderationOpts,
}: {
currentStarterPack?: AppBskyGraphDefs.StarterPackView
currentListItems?: AppBskyGraphDefs.ListItemView[]
- profile: AppBskyActorDefs.ProfileViewBasic
- moderationOpts: ModerationOpts
}) {
const navigation = useNavigation()
const {_} = useLingui()
@@ -183,16 +161,8 @@ function WizardInner({
{header: string; nextBtn: string; subtitle?: string}
> = {
Details: {
- header: _(msg`Starter Pack`),
- nextBtn: _(msg`Next`),
- },
- Profiles: {
- header: _(msg`Choose People`),
- nextBtn: _(msg`Next`),
- },
- Feeds: {
- header: _(msg`Choose Feeds`),
- nextBtn: state.feeds.length === 0 ? _(msg`Skip`) : _(msg`Finish`),
+ header: _(msg`Create a Feed`),
+ nextBtn: _(msg`Finish`),
},
}
const currUiStrings = wizardUiStrings[state.currentStep]
@@ -263,22 +233,6 @@ function WizardInner({
}
}
- const onNext = () => {
- if (state.currentStep === 'Feeds') {
- submit()
- return
- }
-
- const keyboardVisible = Keyboard.isVisible()
- Keyboard.dismiss()
- setTimeout(
- () => {
- dispatch({type: 'Next'})
- },
- keyboardVisible ? 16 : 0,
- )
- }
-
return (
-
- {state.currentStep === 'Details' ? (
-
- ) : state.currentStep === 'Profiles' ? (
-
- ) : state.currentStep === 'Feeds' ? (
-
- ) : null}
+
+ {state.currentStep === 'Details' ? : null}
-
- {state.currentStep !== 'Details' && (
-
- )}
)
}
-function Container({children}: {children: React.ReactNode}) {
+function Container({
+ children,
+ onFinish,
+}: {
+ children: React.ReactNode
+ onFinish: () => void
+}) {
const {_} = useLingui()
- const [state, dispatch] = useWizardState()
-
- if (state.currentStep === 'Profiles' || state.currentStep === 'Feeds') {
- return {children}
- }
+ const [state] = useWizardState()
return (
>
@@ -374,235 +315,3 @@ function Container({children}: {children: React.ReactNode}) {
)
}
-
-function Footer({
- onNext,
- nextBtnText,
- moderationOpts,
- profile,
-}: {
- onNext: () => void
- nextBtnText: string
- moderationOpts: ModerationOpts
- profile: AppBskyActorDefs.ProfileViewBasic
-}) {
- const {_} = useLingui()
- const t = useTheme()
- const [state, dispatch] = useWizardState()
- const editDialogControl = useDialogControl()
- const {bottom: bottomInset} = useSafeAreaInsets()
-
- const items =
- state.currentStep === 'Profiles'
- ? [profile, ...state.profiles]
- : state.feeds
-
- const isEditEnabled =
- (state.currentStep === 'Profiles' && items.length > 1) ||
- (state.currentStep === 'Feeds' && items.length > 0)
-
- const minimumItems = state.currentStep === 'Profiles' ? 8 : 0
-
- const textStyles = [a.text_md]
-
- return (
-
- {items.length > minimumItems && (
-
-
- {items.length}/
- {state.currentStep === 'Profiles' ? STARTER_PACK_MAX_SIZE : 3}
-
-
- )}
-
-
- {items.slice(0, 6).map((p, index) => (
-
- ))}
-
-
- {
- state.currentStep === 'Profiles' ? (
-
- {
- items.length < 2 ? (
-
- It's just you right now! Add more people to your starter pack
- by searching above.
-
- ) : items.length === 2 ? (
-
- You and
-
-
- {getName(items[1] /* [0] is self, skip it */)}{' '}
-
- are included in your starter pack
-
- ) : items.length > 2 ? (
-
-
- {getName(items[1] /* [0] is self, skip it */)},{' '}
-
-
- {getName(items[2])},{' '}
-
- and{' '}
- {' '}
- are included in your starter pack
-
- ) : null /* Should not happen. */
- }
-
- ) : state.currentStep === 'Feeds' ? (
- items.length === 0 ? (
-
-
- Add some feeds to your starter pack!
-
-
-
- Search for feeds that you want to suggest to others.
-
-
-
- ) : (
-
- {
- items.length === 1 ? (
-
-
- {getName(items[0])}
- {' '}
- is included in your starter pack
-
- ) : items.length === 2 ? (
-
-
- {getName(items[0])}
- {' '}
- and
-
-
- {getName(items[1])}{' '}
-
- are included in your starter pack
-
- ) : items.length > 2 ? (
-
-
- {getName(items[0])},{' '}
-
-
- {getName(items[1])},{' '}
-
- and{' '}
- {' '}
- are included in your starter pack
-
- ) : null /* Should not happen. */
- }
-
- )
- ) : null /* Should not happen. */
- }
-
-
- {isEditEnabled ? (
-
- ) : (
-
- )}
- {state.currentStep === 'Profiles' && items.length < 8 ? (
- <>
-
- Add {8 - items.length} more to continue
-
-
- >
- ) : (
-
- )}
-
-
-
-
- )
-}
-
-function getName(item: AppBskyActorDefs.ProfileViewBasic | GeneratorView) {
- if (typeof item.displayName === 'string') {
- return enforceLen(sanitizeDisplayName(item.displayName), 28, true)
- } else if (typeof item.handle === 'string') {
- return enforceLen(sanitizeHandle(item.handle), 28, true)
- }
- return ''
-}