diff options
author | Ansh Nanda <anshnanda10@gmail.com> | 2023-08-28 15:41:02 -0700 |
---|---|---|
committer | Ansh Nanda <anshnanda10@gmail.com> | 2023-08-28 15:41:02 -0700 |
commit | 3f1b313fa4abd966367327aa352567ecf8d52f2d (patch) | |
tree | 742c6af9b1c8ac9630cce1a1eb8bcbc6f4253236 /src | |
parent | c4cf288296927a2b39a11af83856dacb8dfad636 (diff) | |
download | voidsky-3f1b313fa4abd966367327aa352567ecf8d52f2d.tar.zst |
add custom feed discovery to onboarding
Diffstat (limited to 'src')
-rw-r--r-- | src/Navigation.tsx | 34 | ||||
-rw-r--r-- | src/lib/analytics/types.ts | 1 | ||||
-rw-r--r-- | src/state/models/discovery/onboarding.ts | 29 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/RecommendedFeeds.tsx | 160 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/Welcome.tsx | 38 | ||||
-rw-r--r-- | src/view/index.ts | 2 |
6 files changed, 225 insertions, 39 deletions
diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 6ea92e1d4..058a15fa2 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -67,7 +67,7 @@ import {getRoutingInstrumentation} from 'lib/sentry' import {bskyTitle} from 'lib/strings/headings' import {JSX} from 'react/jsx-runtime' import {timeout} from 'lib/async/timeout' -import {Welcome} from 'view/com/auth/onboarding/Welcome' +import {Welcome, WelcomeHeaderRight} from 'view/com/auth/onboarding/Welcome' import {RecommendedFeeds} from 'view/com/auth/onboarding/RecommendedFeeds' const navigationRef = createNavigationContainerRef<AllNavigatorParams>() @@ -221,18 +221,26 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) { component={SavedFeeds} options={{title: title('Edit My Feeds')}} /> - <Stack.Group - screenOptions={{ - animation: 'slide_from_bottom', - presentation: 'modal', - }}> - <Stack.Screen - name="Welcome" - component={Welcome} - options={{title: title('Welcome')}} - /> - <Stack.Screen name="RecommendedFeeds" component={RecommendedFeeds} /> - </Stack.Group> + <Stack.Screen + name="Welcome" + component={Welcome} + options={{ + title: title('Welcome'), + presentation: 'card', + headerShown: true, + headerTransparent: true, + headerTitle: '', + headerBackVisible: false, + headerRight: props => <WelcomeHeaderRight {...props} />, + }} + /> + <Stack.Screen + name="RecommendedFeeds" + component={RecommendedFeeds} + options={{ + title: title('Recommended Feeds'), + }} + /> </> ) } diff --git a/src/lib/analytics/types.ts b/src/lib/analytics/types.ts index f876c6d53..d56e1b615 100644 --- a/src/lib/analytics/types.ts +++ b/src/lib/analytics/types.ts @@ -122,6 +122,7 @@ interface TrackPropertiesMap { // ONBOARDING events 'Onboarding:Begin': {} 'Onboarding:Complete': {} + 'Onboarding:Skipped': {} } interface ScreenPropertiesMap { diff --git a/src/state/models/discovery/onboarding.ts b/src/state/models/discovery/onboarding.ts index 8e7a0a7b9..52521f578 100644 --- a/src/state/models/discovery/onboarding.ts +++ b/src/state/models/discovery/onboarding.ts @@ -1,12 +1,12 @@ import {makeAutoObservable} from 'mobx' import {RootStoreModel} from '../root-store' -import {NavigationProp} from 'lib/routes/types' import {hasProp} from 'lib/type-guards' +import {track} from 'lib/analytics/analytics' export const OnboardingScreenSteps = { Welcome: 'Welcome', RecommendedFeeds: 'RecommendedFeeds', - Complete: 'Complete', + Home: 'Home', } as const type OnboardingStep = @@ -34,6 +34,7 @@ export class OnboardingModel { typeof v.step === 'string' && OnboardingStepsArray.includes(v.step as OnboardingStep) ) { + console.log('hydrating onboarding', v.step) this.step = v.step as OnboardingStep } } @@ -41,31 +42,33 @@ export class OnboardingModel { this.reset() } - nextScreenName() { - if (this.step === 'Welcome') { + nextScreenName(currentScreenName?: OnboardingStep) { + if (currentScreenName === 'Welcome' || this.step === 'Welcome') { this.step = 'RecommendedFeeds' return this.step - } else if (this.step === 'RecommendedFeeds') { - this.step = 'Complete' + } else if ( + this.step === 'RecommendedFeeds' || + currentScreenName === 'RecommendedFeeds' + ) { + this.step = 'Home' return this.step - } else if (this.step === 'Complete') { - return 'Home' } else { // if we get here, we're in an invalid state, let's just go Home return 'Home' } } - complete(navigation: NavigationProp) { - navigation.navigate('Home') - } - reset() { this.step = 'Welcome' } + skip() { + track('Onboarding:Skipped') + this.step = 'Home' + } + get isComplete() { - return this.step === 'Complete' + return this.step === 'Home' } get isRemaining() { diff --git a/src/view/com/auth/onboarding/RecommendedFeeds.tsx b/src/view/com/auth/onboarding/RecommendedFeeds.tsx index 1936f4234..88fb200c6 100644 --- a/src/view/com/auth/onboarding/RecommendedFeeds.tsx +++ b/src/view/com/auth/onboarding/RecommendedFeeds.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {StyleSheet, View} from 'react-native' +import {FlatList, StyleSheet, View} from 'react-native' import {Text} from 'view/com/util/text/Text' import {usePalette} from 'lib/hooks/usePalette' import {Button} from 'view/com/util/forms/Button' @@ -7,6 +7,117 @@ import {NativeStackScreenProps} from '@react-navigation/native-stack' import {HomeTabNavigatorParams} from 'lib/routes/types' import {useStores} from 'state/index' import {observer} from 'mobx-react-lite' +import {CustomFeed} from 'view/com/feeds/CustomFeed' +import {useCustomFeed} from 'lib/hooks/useCustomFeed' +import {makeRecordUri} from 'lib/strings/url-helpers' +import {ViewHeader} from 'view/com/util/ViewHeader' + +const TEMPORARY_RECOMMENDED_FEEDS = [ + { + did: 'did:plc:hsqwcidfez66lwm3gxhfv5in', + rkey: 'aaaf2pqeodmpy', + }, + { + did: 'did:plc:gekdk2nd47gkk3utfz2xf7cn', + rkey: 'aaap4tbjcfe5y', + }, + { + did: 'did:plc:5rw2on4i56btlcajojaxwcat', + rkey: 'aaao6g552b33o', + }, + { + did: 'did:plc:jfhpnnst6flqway4eaeqzj2a', + rkey: 'for-science', + }, + { + did: 'did:plc:7q4nnnxawajbfaq7to5dpbsy', + rkey: 'bsky-news', + }, + { + did: 'did:plc:jcoy7v3a2t4rcfdh6i4kza25', + rkey: 'astro', + }, + { + did: 'did:plc:tenurhgjptubkk5zf5qhi3og', + rkey: 'h-nba', + }, + { + did: 'did:plc:vpkhqolt662uhesyj6nxm7ys', + rkey: 'devfeed', + }, + { + did: 'did:plc:cndfx4udwgvpjaakvxvh7wm5', + rkey: 'flipboard-tech', + }, + { + did: 'did:plc:w4xbfzo7kqfes5zb7r6qv3rw', + rkey: 'blacksky', + }, + { + did: 'did:plc:lptjvw6ut224kwrj7ub3sqbe', + rkey: 'aaaotfjzjplna', + }, + { + did: 'did:plc:gkvpokm7ec5j5yxls6xk4e3z', + rkey: 'formula-one', + }, + { + did: 'did:plc:q6gjnaw2blty4crticxkmujt', + rkey: 'positivifeed', + }, + { + did: 'did:plc:l72uci4styb4jucsgcrrj5ap', + rkey: 'aaao5dzfm36u4', + }, + { + did: 'did:plc:k3jkadxv5kkjgs6boyon7m6n', + rkey: 'aaaavlyvqzst2', + }, + { + did: 'did:plc:nkahctfdi6bxk72umytfwghw', + rkey: 'aaado2uvfsc6w', + }, + { + did: 'did:plc:epihigio3d7un7u3gpqiy5gv', + rkey: 'aaaekwsc7zsvs', + }, + { + did: 'did:plc:qiknc4t5rq7yngvz7g4aezq7', + rkey: 'aaaejxlobe474', + }, + { + did: 'did:plc:mlq4aycufcuolr7ax6sezpc4', + rkey: 'aaaoudweck6uy', + }, + { + did: 'did:plc:rcez5hcvq3vzlu5x7xrjyccg', + rkey: 'aaadzjxbcddzi', + }, + { + did: 'did:plc:lnxbuzaenlwjrncx6sc4cfdr', + rkey: 'aaab2vesjtszc', + }, + { + did: 'did:plc:x3cya3wkt4n6u4ihmvpsc5if', + rkey: 'aaacynbxwimok', + }, + { + did: 'did:plc:abv47bjgzjgoh3yrygwoi36x', + rkey: 'aaagt6amuur5e', + }, + { + did: 'did:plc:ffkgesg3jsv2j7aagkzrtcvt', + rkey: 'aaacjerk7gwek', + }, + { + did: 'did:plc:geoqe3qls5mwezckxxsewys2', + rkey: 'aaai43yetqshu', + }, + { + did: 'did:plc:2wqomm3tjqbgktbrfwgvrw34', + rkey: 'authors', + }, +] type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'RecommendedFeeds'> export const RecommendedFeeds = observer(({navigation}: Props) => { @@ -14,41 +125,68 @@ export const RecommendedFeeds = observer(({navigation}: Props) => { const store = useStores() const next = () => { - const nextScreenName = store.onboarding.nextScreenName() + const nextScreenName = store.onboarding.nextScreenName('RecommendedFeeds') if (nextScreenName) { navigation.navigate(nextScreenName) } } return ( - <View style={[styles.container]}> - <View testID="recommendedFeedsScreen"> - <Text type="lg-bold" style={[pal.text]}> - Check out some recommended feeds. Click + to add them to your list of - pinned feeds. - </Text> - </View> + <View style={[styles.container]} testID="recommendedFeedsScreen"> + <ViewHeader title="Recommended Feeds" canGoBack /> + <Text type="lg-medium" style={[pal.text, styles.header]}> + Check out some recommended feeds. Click + to add them to your list of + pinned feeds. + </Text> + + <FlatList + data={TEMPORARY_RECOMMENDED_FEEDS} + renderItem={({item}) => <Item item={item} />} + keyExtractor={item => item.did + item.rkey} + style={{flex: 1}} + /> <Button onPress={next} label="Continue" testID="continueBtn" + style={styles.button} labelStyle={styles.buttonText} /> </View> ) }) +type ItemProps = { + did: string + rkey: string +} + +const Item = ({item}: {item: ItemProps}) => { + const uri = makeRecordUri(item.did, 'app.bsky.feed.generator', item.rkey) + const data = useCustomFeed(uri) + if (!data) return null + return ( + <CustomFeed item={data} key={uri} showDescription showLikes showSaveBtn /> + ) +} + const styles = StyleSheet.create({ container: { flex: 1, - marginVertical: 60, marginHorizontal: 16, justifyContent: 'space-between', }, + header: { + marginBottom: 16, + }, + button: { + marginBottom: 48, + marginTop: 16, + }, buttonText: { textAlign: 'center', fontSize: 18, - marginVertical: 4, + paddingVertical: 4, }, }) diff --git a/src/view/com/auth/onboarding/Welcome.tsx b/src/view/com/auth/onboarding/Welcome.tsx index 5b663fe16..cb3a2307a 100644 --- a/src/view/com/auth/onboarding/Welcome.tsx +++ b/src/view/com/auth/onboarding/Welcome.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {StyleSheet, View} from 'react-native' +import {Pressable, StyleSheet, View} from 'react-native' import {Text} from 'view/com/util/text/Text' import {s} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' @@ -9,14 +9,23 @@ import {NativeStackScreenProps} from '@react-navigation/native-stack' import {HomeTabNavigatorParams} from 'lib/routes/types' import {useStores} from 'state/index' import {observer} from 'mobx-react-lite' +import {HeaderButtonProps} from '@react-navigation/native-stack/lib/typescript/src/types' +import {NavigationProp, useNavigation} from '@react-navigation/native' type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Welcome'> export const Welcome = observer(({navigation}: Props) => { const pal = usePalette('default') const store = useStores() + // make sure bottom nav is hidden + React.useEffect(() => { + if (!store.shell.minimalShellMode) { + store.shell.setMinimalShellMode(true) + } + }, [store.shell.minimalShellMode, store]) + const next = () => { - const nextScreenName = store.onboarding.nextScreenName() + const nextScreenName = store.onboarding.nextScreenName('Welcome') if (nextScreenName) { navigation.navigate(nextScreenName) } @@ -76,6 +85,31 @@ export const Welcome = observer(({navigation}: Props) => { ) }) +export const WelcomeHeaderRight = (props: HeaderButtonProps) => { + const {canGoBack} = props + const pal = usePalette('default') + const navigation = useNavigation<NavigationProp<HomeTabNavigatorParams>>() + const store = useStores() + return ( + <Pressable + accessibilityRole="button" + style={[s.flexRow, s.alignCenter]} + onPress={() => { + if (canGoBack) { + store.onboarding.skip() + navigation.goBack() + } + }}> + <Text style={[pal.link]}>Skip</Text> + <FontAwesomeIcon + icon={'chevron-right'} + size={14} + color={pal.colors.link} + /> + </Pressable> + ) +} + const styles = StyleSheet.create({ container: { flex: 1, diff --git a/src/view/index.ts b/src/view/index.ts index 1c3dc3937..2e4c08ec7 100644 --- a/src/view/index.ts +++ b/src/view/index.ts @@ -92,6 +92,7 @@ import {faPlay} from '@fortawesome/free-solid-svg-icons/faPlay' import {faPause} from '@fortawesome/free-solid-svg-icons/faPause' import {faThumbtack} from '@fortawesome/free-solid-svg-icons/faThumbtack' import {faList} from '@fortawesome/free-solid-svg-icons/faList' +import {faChevronRight} from '@fortawesome/free-solid-svg-icons/faChevronRight' export function setup() { library.add( @@ -187,5 +188,6 @@ export function setup() { faPlay, faPause, faList, + faChevronRight, ) } |