diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/build-flags.ts | 1 | ||||
-rw-r--r-- | src/view/com/auth/Onboarding.tsx | 51 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/RecommendedFeeds.tsx | 211 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/RecommendedFeedsItem.tsx | 172 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/RecommendedFollows.tsx | 272 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/RecommendedFollowsItem.tsx | 202 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/Welcome.tsx | 10 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/WelcomeDesktop.tsx | 126 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/WelcomeMobile.tsx | 136 | ||||
-rw-r--r-- | src/view/shell/createNativeStackNavigatorWithAuth.tsx | 23 |
10 files changed, 8 insertions, 1196 deletions
diff --git a/src/lib/build-flags.ts b/src/lib/build-flags.ts index f85cbd9f8..cf05114e0 100644 --- a/src/lib/build-flags.ts +++ b/src/lib/build-flags.ts @@ -1,3 +1,2 @@ export const LOGIN_INCLUDE_DEV_SERVERS = true export const PWI_ENABLED = true -export const NEW_ONBOARDING_ENABLED = true diff --git a/src/view/com/auth/Onboarding.tsx b/src/view/com/auth/Onboarding.tsx deleted file mode 100644 index bdb7f27c8..000000000 --- a/src/view/com/auth/Onboarding.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react' -import {SafeAreaView, Platform} from 'react-native' -import {ErrorBoundary} from 'view/com/util/ErrorBoundary' -import {s} from 'lib/styles' -import {usePalette} from 'lib/hooks/usePalette' -import {Welcome} from './onboarding/Welcome' -import {RecommendedFeeds} from './onboarding/RecommendedFeeds' -import {RecommendedFollows} from './onboarding/RecommendedFollows' -import {useSetMinimalShellMode} from '#/state/shell/minimal-mode' -import {useOnboardingState, useOnboardingDispatch} from '#/state/shell' - -export function Onboarding() { - const pal = usePalette('default') - const setMinimalShellMode = useSetMinimalShellMode() - const onboardingState = useOnboardingState() - const onboardingDispatch = useOnboardingDispatch() - - React.useEffect(() => { - setMinimalShellMode(true) - }, [setMinimalShellMode]) - - const next = () => onboardingDispatch({type: 'next'}) - const skip = () => onboardingDispatch({type: 'skip'}) - - return ( - <SafeAreaView - testID="onboardingView" - style={[ - s.hContentRegion, - pal.view, - // @ts-ignore web only -esb - Platform.select({ - web: { - height: '100vh', - }, - }), - ]}> - <ErrorBoundary> - {onboardingState.step === 'Welcome' && ( - <Welcome skip={skip} next={next} /> - )} - {onboardingState.step === 'RecommendedFeeds' && ( - <RecommendedFeeds next={next} /> - )} - {onboardingState.step === 'RecommendedFollows' && ( - <RecommendedFollows next={next} /> - )} - </ErrorBoundary> - </SafeAreaView> - ) -} diff --git a/src/view/com/auth/onboarding/RecommendedFeeds.tsx b/src/view/com/auth/onboarding/RecommendedFeeds.tsx deleted file mode 100644 index 95f8502f8..000000000 --- a/src/view/com/auth/onboarding/RecommendedFeeds.tsx +++ /dev/null @@ -1,211 +0,0 @@ -import React from 'react' -import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {useSuggestedFeedsQuery} from '#/state/queries/suggested-feeds' -import {usePalette} from 'lib/hooks/usePalette' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {ErrorMessage} from 'view/com/util/error/ErrorMessage' -import {Button} from 'view/com/util/forms/Button' -import {Mobile, TabletOrDesktop} from 'view/com/util/layouts/Breakpoints' -import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout' -import {Text} from 'view/com/util/text/Text' -import {ViewHeader} from 'view/com/util/ViewHeader' -import {RecommendedFeedsItem} from './RecommendedFeedsItem' - -type Props = { - next: () => void -} -export function RecommendedFeeds({next}: Props) { - const pal = usePalette('default') - const {_} = useLingui() - const {isTabletOrMobile} = useWebMediaQueries() - const {isLoading, data} = useSuggestedFeedsQuery() - - const hasFeeds = data && data.pages[0].feeds.length - - const title = ( - <> - <Trans> - <Text - style={[ - pal.textLight, - tdStyles.title1, - isTabletOrMobile && tdStyles.title1Small, - ]}> - Choose your - </Text> - <Text - style={[ - pal.link, - tdStyles.title2, - isTabletOrMobile && tdStyles.title2Small, - ]}> - Recommended - </Text> - <Text - style={[ - pal.link, - tdStyles.title2, - isTabletOrMobile && tdStyles.title2Small, - ]}> - Feeds - </Text> - </Trans> - <Text type="2xl-medium" style={[pal.textLight, tdStyles.description]}> - <Trans> - Feeds are created by users to curate content. Choose some feeds that - you find interesting. - </Trans> - </Text> - <View - style={{ - flexDirection: 'row', - justifyContent: 'flex-end', - marginTop: 20, - }}> - <Button onPress={next} testID="continueBtn"> - <View - style={{ - flexDirection: 'row', - alignItems: 'center', - paddingLeft: 2, - gap: 6, - }}> - <Text - type="2xl-medium" - style={{color: '#fff', position: 'relative', top: -1}}> - <Trans>Next</Trans> - </Text> - <FontAwesomeIcon icon="angle-right" color="#fff" size={14} /> - </View> - </Button> - </View> - </> - ) - - return ( - <> - <TabletOrDesktop> - <TitleColumnLayout - testID="recommendedFeedsOnboarding" - title={title} - horizontal - titleStyle={isTabletOrMobile ? undefined : {minWidth: 470}} - contentStyle={{paddingHorizontal: 0}}> - {hasFeeds ? ( - <FlatList - data={data.pages[0].feeds} - renderItem={({item}) => <RecommendedFeedsItem item={item} />} - keyExtractor={item => item.uri} - style={{flex: 1}} - /> - ) : isLoading ? ( - <View> - <ActivityIndicator size="large" /> - </View> - ) : ( - <ErrorMessage message={_(msg`Failed to load recommended feeds`)} /> - )} - </TitleColumnLayout> - </TabletOrDesktop> - <Mobile> - <View style={[mStyles.container]} testID="recommendedFeedsOnboarding"> - <ViewHeader - title={_(msg`Recommended Feeds`)} - showBackButton={false} - showOnDesktop - /> - <Text type="lg-medium" style={[pal.text, mStyles.header]}> - <Trans> - Check out some recommended feeds. Tap + to add them to your list - of pinned feeds. - </Trans> - </Text> - - {hasFeeds ? ( - <FlatList - data={data.pages[0].feeds} - renderItem={({item}) => <RecommendedFeedsItem item={item} />} - keyExtractor={item => item.uri} - style={{flex: 1}} - showsVerticalScrollIndicator={false} - /> - ) : isLoading ? ( - <View style={{flex: 1}}> - <ActivityIndicator size="large" /> - </View> - ) : ( - <View style={{flex: 1}}> - <ErrorMessage - message={_(msg`Failed to load recommended feeds`)} - /> - </View> - )} - - <Button - onPress={next} - label={_(msg`Continue`)} - testID="continueBtn" - style={mStyles.button} - labelStyle={mStyles.buttonText} - /> - </View> - </Mobile> - </> - ) -} - -const tdStyles = StyleSheet.create({ - container: { - flex: 1, - marginHorizontal: 16, - justifyContent: 'space-between', - }, - title1: { - fontSize: 36, - fontWeight: '800', - textAlign: 'right', - }, - title1Small: { - fontSize: 24, - }, - title2: { - fontSize: 58, - fontWeight: '800', - textAlign: 'right', - }, - title2Small: { - fontSize: 36, - }, - description: { - maxWidth: 400, - marginTop: 10, - marginLeft: 'auto', - textAlign: 'right', - }, -}) - -const mStyles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'space-between', - }, - header: { - marginBottom: 16, - marginHorizontal: 16, - }, - button: { - marginBottom: 16, - marginHorizontal: 16, - marginTop: 16, - alignItems: 'center', - }, - buttonText: { - textAlign: 'center', - fontSize: 18, - paddingVertical: 4, - }, -}) diff --git a/src/view/com/auth/onboarding/RecommendedFeedsItem.tsx b/src/view/com/auth/onboarding/RecommendedFeedsItem.tsx deleted file mode 100644 index ea3e1f725..000000000 --- a/src/view/com/auth/onboarding/RecommendedFeedsItem.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import React from 'react' -import {View} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {AppBskyFeedDefs, RichText as BskRichText} from '@atproto/api' -import {Text} from 'view/com/util/text/Text' -import {RichText} from 'view/com/util/text/RichText' -import {Button} from 'view/com/util/forms/Button' -import {UserAvatar} from 'view/com/util/UserAvatar' -import * as Toast from 'view/com/util/Toast' -import {HeartIcon} from 'lib/icons' -import {usePalette} from 'lib/hooks/usePalette' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {sanitizeHandle} from 'lib/strings/handles' -import { - usePreferencesQuery, - usePinFeedMutation, - useRemoveFeedMutation, -} from '#/state/queries/preferences' -import {logger} from '#/logger' -import {useAnalytics} from '#/lib/analytics/analytics' -import {Trans, msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -export function RecommendedFeedsItem({ - item, -}: { - item: AppBskyFeedDefs.GeneratorView -}) { - const {isMobile} = useWebMediaQueries() - const pal = usePalette('default') - const {_} = useLingui() - const {data: preferences} = usePreferencesQuery() - const { - mutateAsync: pinFeed, - variables: pinnedFeed, - reset: resetPinFeed, - } = usePinFeedMutation() - const { - mutateAsync: removeFeed, - variables: removedFeed, - reset: resetRemoveFeed, - } = useRemoveFeedMutation() - const {track} = useAnalytics() - - if (!item || !preferences) return null - - const isPinned = - !removedFeed?.uri && - (pinnedFeed?.uri || preferences.feeds.saved.includes(item.uri)) - - const onToggle = async () => { - if (isPinned) { - try { - await removeFeed({uri: item.uri}) - resetRemoveFeed() - } catch (e) { - Toast.show(_(msg`There was an issue contacting your server`)) - logger.error('Failed to unsave feed', {message: e}) - } - } else { - try { - await pinFeed({uri: item.uri}) - resetPinFeed() - track('Onboarding:CustomFeedAdded') - } catch (e) { - Toast.show(_(msg`There was an issue contacting your server`)) - logger.error('Failed to pin feed', {message: e}) - } - } - } - - return ( - <View testID={`feed-${item.displayName}`}> - <View - style={[ - pal.border, - { - flex: isMobile ? 1 : undefined, - flexDirection: 'row', - gap: 18, - maxWidth: isMobile ? undefined : 670, - borderRightWidth: isMobile ? undefined : 1, - paddingHorizontal: 24, - paddingVertical: isMobile ? 12 : 24, - borderTopWidth: 1, - }, - ]}> - <View style={{marginTop: 2}}> - <UserAvatar type="algo" size={42} avatar={item.avatar} /> - </View> - <View style={{flex: isMobile ? 1 : undefined}}> - <Text - type="2xl-bold" - numberOfLines={1} - style={[pal.text, {fontSize: 19}]}> - {item.displayName} - </Text> - - <Text style={[pal.textLight, {marginBottom: 8}]} numberOfLines={1}> - <Trans>by {sanitizeHandle(item.creator.handle, '@')}</Trans> - </Text> - - {item.description ? ( - <RichText - type="xl" - style={[ - pal.text, - { - flex: isMobile ? 1 : undefined, - maxWidth: 550, - marginBottom: 18, - }, - ]} - richText={new BskRichText({text: item.description || ''})} - numberOfLines={6} - /> - ) : null} - - <View style={{flexDirection: 'row', alignItems: 'center', gap: 12}}> - <Button - type="inverted" - style={{paddingVertical: 6}} - onPress={onToggle}> - <View - style={{ - flexDirection: 'row', - alignItems: 'center', - paddingRight: 2, - gap: 6, - }}> - {isPinned ? ( - <> - <FontAwesomeIcon - icon="check" - size={16} - color={pal.colors.textInverted} - /> - <Text type="lg-medium" style={pal.textInverted}> - <Trans>Added</Trans> - </Text> - </> - ) : ( - <> - <FontAwesomeIcon - icon="plus" - size={16} - color={pal.colors.textInverted} - /> - <Text type="lg-medium" style={pal.textInverted}> - <Trans>Add</Trans> - </Text> - </> - )} - </View> - </Button> - - <View style={{flexDirection: 'row', gap: 4}}> - <HeartIcon - size={16} - strokeWidth={2.5} - style={[pal.textLight, {position: 'relative', top: 2}]} - /> - <Text type="lg-medium" style={[pal.text, pal.textLight]}> - {item.likeCount || 0} - </Text> - </View> - </View> - </View> - </View> - </View> - ) -} diff --git a/src/view/com/auth/onboarding/RecommendedFollows.tsx b/src/view/com/auth/onboarding/RecommendedFollows.tsx deleted file mode 100644 index a840f949e..000000000 --- a/src/view/com/auth/onboarding/RecommendedFollows.tsx +++ /dev/null @@ -1,272 +0,0 @@ -import React from 'react' -import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' -import {AppBskyActorDefs, moderateProfile} from '@atproto/api' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {logger} from '#/logger' -import {useModerationOpts} from '#/state/queries/preferences' -import {useSuggestedFollowsQuery} from '#/state/queries/suggested-follows' -import {useGetSuggestedFollowersByActor} from '#/state/queries/suggested-follows' -import {usePalette} from 'lib/hooks/usePalette' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {Button} from 'view/com/util/forms/Button' -import {Mobile, TabletOrDesktop} from 'view/com/util/layouts/Breakpoints' -import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout' -import {Text} from 'view/com/util/text/Text' -import {ViewHeader} from 'view/com/util/ViewHeader' -import {RecommendedFollowsItem} from './RecommendedFollowsItem' - -type Props = { - next: () => void -} -export function RecommendedFollows({next}: Props) { - const pal = usePalette('default') - const {_} = useLingui() - const {isTabletOrMobile} = useWebMediaQueries() - const {data: suggestedFollows} = useSuggestedFollowsQuery() - const getSuggestedFollowsByActor = useGetSuggestedFollowersByActor() - const [additionalSuggestions, setAdditionalSuggestions] = React.useState<{ - [did: string]: AppBskyActorDefs.ProfileView[] - }>({}) - const existingDids = React.useRef<string[]>([]) - const moderationOpts = useModerationOpts() - - const title = ( - <> - <Trans> - <Text - style={[ - pal.textLight, - tdStyles.title1, - isTabletOrMobile && tdStyles.title1Small, - ]}> - Follow some - </Text> - <Text - style={[ - pal.link, - tdStyles.title2, - isTabletOrMobile && tdStyles.title2Small, - ]}> - Recommended - </Text> - <Text - style={[ - pal.link, - tdStyles.title2, - isTabletOrMobile && tdStyles.title2Small, - ]}> - Users - </Text> - </Trans> - <Text type="2xl-medium" style={[pal.textLight, tdStyles.description]}> - <Trans> - Follow some users to get started. We can recommend you more users - based on who you find interesting. - </Trans> - </Text> - <View - style={{ - flexDirection: 'row', - justifyContent: 'flex-end', - marginTop: 20, - }}> - <Button onPress={next} testID="continueBtn"> - <View - style={{ - flexDirection: 'row', - alignItems: 'center', - paddingLeft: 2, - gap: 6, - }}> - <Text - type="2xl-medium" - style={{color: '#fff', position: 'relative', top: -1}}> - <Trans context="action">Done</Trans> - </Text> - <FontAwesomeIcon icon="angle-right" color="#fff" size={14} /> - </View> - </Button> - </View> - </> - ) - - const suggestions = React.useMemo(() => { - if (!suggestedFollows) return [] - - const additional = Object.entries(additionalSuggestions) - const items = suggestedFollows.pages.flatMap(page => page.actors) - - outer: while (additional.length) { - const additionalAccount = additional.shift() - - if (!additionalAccount) break - - const [followedUser, relatedAccounts] = additionalAccount - - for (let i = 0; i < items.length; i++) { - if (items[i].did === followedUser) { - items.splice(i + 1, 0, ...relatedAccounts) - continue outer - } - } - } - - existingDids.current = items.map(i => i.did) - - return items - }, [suggestedFollows, additionalSuggestions]) - - const onFollowStateChange = React.useCallback( - async ({following, did}: {following: boolean; did: string}) => { - if (following) { - try { - const {suggestions: results} = await getSuggestedFollowsByActor(did) - - if (results.length) { - const deduped = results.filter( - r => !existingDids.current.find(did => did === r.did), - ) - setAdditionalSuggestions(s => ({ - ...s, - [did]: deduped.slice(0, 3), - })) - } - } catch (e) { - logger.error('RecommendedFollows: failed to get suggestions', { - message: e, - }) - } - } - - // not handling the unfollow case - }, - [existingDids, getSuggestedFollowsByActor, setAdditionalSuggestions], - ) - - return ( - <> - <TabletOrDesktop> - <TitleColumnLayout - testID="recommendedFollowsOnboarding" - title={title} - horizontal - titleStyle={isTabletOrMobile ? undefined : {minWidth: 470}} - contentStyle={{paddingHorizontal: 0}}> - {!suggestedFollows || !moderationOpts ? ( - <ActivityIndicator size="large" /> - ) : ( - <FlatList - data={suggestions} - renderItem={({item}) => ( - <RecommendedFollowsItem - profile={item} - onFollowStateChange={onFollowStateChange} - moderation={moderateProfile(item, moderationOpts)} - /> - )} - keyExtractor={item => item.did} - style={{flex: 1}} - /> - )} - </TitleColumnLayout> - </TabletOrDesktop> - - <Mobile> - <View style={[mStyles.container]} testID="recommendedFollowsOnboarding"> - <View> - <ViewHeader - title={_(msg`Recommended Users`)} - showBackButton={false} - showOnDesktop - /> - <Text type="lg-medium" style={[pal.text, mStyles.header]}> - <Trans> - Check out some recommended users. Follow them to see similar - users. - </Trans> - </Text> - </View> - {!suggestedFollows || !moderationOpts ? ( - <ActivityIndicator size="large" /> - ) : ( - <FlatList - data={suggestions} - renderItem={({item}) => ( - <RecommendedFollowsItem - profile={item} - onFollowStateChange={onFollowStateChange} - moderation={moderateProfile(item, moderationOpts)} - /> - )} - keyExtractor={item => item.did} - style={{flex: 1}} - showsVerticalScrollIndicator={false} - /> - )} - <Button - onPress={next} - label={_(msg`Continue`)} - testID="continueBtn" - style={mStyles.button} - labelStyle={mStyles.buttonText} - /> - </View> - </Mobile> - </> - ) -} - -const tdStyles = StyleSheet.create({ - container: { - flex: 1, - marginHorizontal: 16, - justifyContent: 'space-between', - }, - title1: { - fontSize: 36, - fontWeight: '800', - textAlign: 'right', - }, - title1Small: { - fontSize: 24, - }, - title2: { - fontSize: 58, - fontWeight: '800', - textAlign: 'right', - }, - title2Small: { - fontSize: 36, - }, - description: { - maxWidth: 400, - marginTop: 10, - marginLeft: 'auto', - textAlign: 'right', - }, -}) - -const mStyles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'space-between', - }, - header: { - marginBottom: 16, - marginHorizontal: 16, - }, - button: { - marginBottom: 16, - marginHorizontal: 16, - marginTop: 16, - alignItems: 'center', - }, - buttonText: { - textAlign: 'center', - fontSize: 18, - paddingVertical: 4, - }, -}) diff --git a/src/view/com/auth/onboarding/RecommendedFollowsItem.tsx b/src/view/com/auth/onboarding/RecommendedFollowsItem.tsx deleted file mode 100644 index dba3f8c56..000000000 --- a/src/view/com/auth/onboarding/RecommendedFollowsItem.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import React from 'react' -import {View, StyleSheet, ActivityIndicator} from 'react-native' -import {ModerationDecision, AppBskyActorDefs} from '@atproto/api' -import {Button} from '#/view/com/util/forms/Button' -import {usePalette} from 'lib/hooks/usePalette' -import {sanitizeDisplayName} from 'lib/strings/display-names' -import {sanitizeHandle} from 'lib/strings/handles' -import {s} from 'lib/styles' -import {UserAvatar} from 'view/com/util/UserAvatar' -import {Text} from 'view/com/util/text/Text' -import Animated, {FadeInRight} from 'react-native-reanimated' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {useAnalytics} from 'lib/analytics/analytics' -import {useLingui} from '@lingui/react' -import {Trans, msg} from '@lingui/macro' -import {Shadow, useProfileShadow} from '#/state/cache/profile-shadow' -import {useProfileFollowMutationQueue} from '#/state/queries/profile' -import {logger} from '#/logger' - -type Props = { - profile: AppBskyActorDefs.ProfileViewBasic - moderation: ModerationDecision - onFollowStateChange: (props: { - did: string - following: boolean - }) => Promise<void> -} - -export function RecommendedFollowsItem({ - profile, - moderation, - onFollowStateChange, -}: React.PropsWithChildren<Props>) { - const pal = usePalette('default') - const {isMobile} = useWebMediaQueries() - const shadowedProfile = useProfileShadow(profile) - - return ( - <Animated.View - entering={FadeInRight} - style={[ - styles.cardContainer, - pal.view, - pal.border, - { - maxWidth: isMobile ? undefined : 670, - borderRightWidth: isMobile ? undefined : 1, - }, - ]}> - <ProfileCard - key={profile.did} - profile={shadowedProfile} - onFollowStateChange={onFollowStateChange} - moderation={moderation} - /> - </Animated.View> - ) -} - -function ProfileCard({ - profile, - onFollowStateChange, - moderation, -}: { - profile: Shadow<AppBskyActorDefs.ProfileViewBasic> - moderation: ModerationDecision - onFollowStateChange: (props: { - did: string - following: boolean - }) => Promise<void> -}) { - const {track} = useAnalytics() - const pal = usePalette('default') - const {_} = useLingui() - const [addingMoreSuggestions, setAddingMoreSuggestions] = - React.useState(false) - const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue( - profile, - 'RecommendedFollowsItem', - ) - - const onToggleFollow = React.useCallback(async () => { - try { - if (profile.viewer?.following) { - await queueUnfollow() - } else { - setAddingMoreSuggestions(true) - await queueFollow() - await onFollowStateChange({did: profile.did, following: true}) - setAddingMoreSuggestions(false) - track('Onboarding:SuggestedFollowFollowed') - } - } catch (e: any) { - if (e?.name !== 'AbortError') { - logger.error('RecommendedFollows: failed to toggle following', { - message: e, - }) - } - } finally { - setAddingMoreSuggestions(false) - } - }, [ - profile, - queueFollow, - queueUnfollow, - setAddingMoreSuggestions, - track, - onFollowStateChange, - ]) - - return ( - <View style={styles.card}> - <View style={styles.layout}> - <View style={styles.layoutAvi}> - <UserAvatar - size={40} - avatar={profile.avatar} - moderation={moderation.ui('avatar')} - /> - </View> - <View style={styles.layoutContent}> - <Text - type="2xl-bold" - style={[s.bold, pal.text]} - numberOfLines={1} - lineHeight={1.2}> - {sanitizeDisplayName( - profile.displayName || sanitizeHandle(profile.handle), - moderation.ui('displayName'), - )} - </Text> - <Text type="xl" style={[pal.textLight]} numberOfLines={1}> - {sanitizeHandle(profile.handle, '@')} - </Text> - </View> - - <Button - type={profile.viewer?.following ? 'default' : 'inverted'} - labelStyle={styles.followButton} - onPress={onToggleFollow} - label={profile.viewer?.following ? _(msg`Unfollow`) : _(msg`Follow`)} - /> - </View> - {profile.description ? ( - <View style={styles.details}> - <Text type="lg" style={pal.text} numberOfLines={4}> - {profile.description as string} - </Text> - </View> - ) : undefined} - {addingMoreSuggestions ? ( - <View style={styles.addingMoreContainer}> - <ActivityIndicator size="small" color={pal.colors.text} /> - <Text style={[pal.text]}> - <Trans>Finding similar accounts...</Trans> - </Text> - </View> - ) : null} - </View> - ) -} - -const styles = StyleSheet.create({ - cardContainer: { - borderTopWidth: 1, - }, - card: { - paddingHorizontal: 10, - }, - layout: { - flexDirection: 'row', - alignItems: 'center', - }, - layoutAvi: { - width: 54, - paddingLeft: 4, - paddingTop: 8, - paddingBottom: 10, - }, - layoutContent: { - flex: 1, - paddingRight: 10, - paddingTop: 10, - paddingBottom: 10, - }, - details: { - paddingLeft: 54, - paddingRight: 10, - paddingBottom: 10, - }, - addingMoreContainer: { - flexDirection: 'row', - alignItems: 'center', - paddingLeft: 54, - paddingTop: 4, - paddingBottom: 12, - gap: 4, - }, - followButton: { - fontSize: 16, - }, -}) diff --git a/src/view/com/auth/onboarding/Welcome.tsx b/src/view/com/auth/onboarding/Welcome.tsx deleted file mode 100644 index b44b58f84..000000000 --- a/src/view/com/auth/onboarding/Welcome.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import 'react' -import {withBreakpoints} from 'view/com/util/layouts/withBreakpoints' -import {WelcomeDesktop} from './WelcomeDesktop' -import {WelcomeMobile} from './WelcomeMobile' - -export const Welcome = withBreakpoints( - WelcomeMobile, - WelcomeDesktop, - WelcomeDesktop, -) diff --git a/src/view/com/auth/onboarding/WelcomeDesktop.tsx b/src/view/com/auth/onboarding/WelcomeDesktop.tsx deleted file mode 100644 index fdb31197c..000000000 --- a/src/view/com/auth/onboarding/WelcomeDesktop.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import React from 'react' -import {StyleSheet, View} from 'react-native' -import {useMediaQuery} from 'react-responsive' -import {Text} from 'view/com/util/text/Text' -import {s} from 'lib/styles' -import {usePalette} from 'lib/hooks/usePalette' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {TitleColumnLayout} from 'view/com/util/layouts/TitleColumnLayout' -import {Button} from 'view/com/util/forms/Button' -import {Trans} from '@lingui/macro' - -type Props = { - next: () => void - skip: () => void -} - -export function WelcomeDesktop({next}: Props) { - const pal = usePalette('default') - const horizontal = useMediaQuery({minWidth: 1300}) - const title = ( - <Trans> - <Text - style={[ - pal.textLight, - { - fontSize: 36, - fontWeight: '800', - textAlign: horizontal ? 'right' : 'left', - }, - ]}> - Welcome to - </Text> - <Text - style={[ - pal.link, - { - fontSize: 72, - fontWeight: '800', - textAlign: horizontal ? 'right' : 'left', - }, - ]}> - Bluesky - </Text> - </Trans> - ) - return ( - <TitleColumnLayout - testID="welcomeOnboarding" - title={title} - horizontal={horizontal} - titleStyle={horizontal ? {paddingBottom: 160} : undefined}> - <View style={[styles.row]}> - <FontAwesomeIcon icon={'globe'} size={36} color={pal.colors.link} /> - <View style={[styles.rowText]}> - <Text type="xl-bold" style={[pal.text]}> - <Trans>Bluesky is public.</Trans> - </Text> - <Text type="xl" style={[pal.text, s.pt2]}> - <Trans> - Your posts, likes, and blocks are public. Mutes are private. - </Trans> - </Text> - </View> - </View> - <View style={[styles.row]}> - <FontAwesomeIcon icon={'at'} size={36} color={pal.colors.link} /> - <View style={[styles.rowText]}> - <Text type="xl-bold" style={[pal.text]}> - <Trans>Bluesky is open.</Trans> - </Text> - <Text type="xl" style={[pal.text, s.pt2]}> - <Trans>Never lose access to your followers and data.</Trans> - </Text> - </View> - </View> - <View style={[styles.row]}> - <FontAwesomeIcon icon={'gear'} size={36} color={pal.colors.link} /> - <View style={[styles.rowText]}> - <Text type="xl-bold" style={[pal.text]}> - <Trans>Bluesky is flexible.</Trans> - </Text> - <Text type="xl" style={[pal.text, s.pt2]}> - <Trans> - Choose the algorithms that power your experience with custom - feeds. - </Trans> - </Text> - </View> - </View> - <View style={styles.spacer} /> - <View style={{flexDirection: 'row'}}> - <Button onPress={next} testID="continueBtn"> - <View - style={{ - flexDirection: 'row', - alignItems: 'center', - paddingLeft: 2, - gap: 6, - }}> - <Text - type="2xl-medium" - style={{color: '#fff', position: 'relative', top: -1}}> - <Trans context="action">Next</Trans> - </Text> - <FontAwesomeIcon icon="angle-right" color="#fff" size={14} /> - </View> - </Button> - </View> - </TitleColumnLayout> - ) -} - -const styles = StyleSheet.create({ - row: { - flexDirection: 'row', - columnGap: 20, - alignItems: 'center', - marginVertical: 20, - }, - rowText: { - flex: 1, - }, - spacer: { - height: 20, - }, -}) diff --git a/src/view/com/auth/onboarding/WelcomeMobile.tsx b/src/view/com/auth/onboarding/WelcomeMobile.tsx deleted file mode 100644 index b8659d56c..000000000 --- a/src/view/com/auth/onboarding/WelcomeMobile.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import React from 'react' -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' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {Button} from 'view/com/util/forms/Button' -import {ViewHeader} from 'view/com/util/ViewHeader' -import {useLingui} from '@lingui/react' -import {Trans, msg} from '@lingui/macro' - -type Props = { - next: () => void - skip: () => void -} - -export function WelcomeMobile({next, skip}: Props) { - const pal = usePalette('default') - const {_} = useLingui() - - return ( - <View style={[styles.container]} testID="welcomeOnboarding"> - <ViewHeader - showOnDesktop - showBorder={false} - showBackButton={false} - title="" - renderButton={() => { - return ( - <Pressable - accessibilityRole="button" - style={[s.flexRow, s.alignCenter]} - onPress={skip}> - <Text style={[pal.link]}> - <Trans>Skip</Trans> - </Text> - <FontAwesomeIcon - icon={'chevron-right'} - size={14} - color={pal.colors.link} - /> - </Pressable> - ) - }} - /> - <View> - <Text style={[pal.text, styles.title]}> - <Trans> - Welcome to{' '} - <Text style={[pal.text, pal.link, styles.title]}>Bluesky</Text> - </Trans> - </Text> - <View style={styles.spacer} /> - <View style={[styles.row]}> - <FontAwesomeIcon icon={'globe'} size={36} color={pal.colors.link} /> - <View style={[styles.rowText]}> - <Text type="lg-bold" style={[pal.text]}> - <Trans>Bluesky is public.</Trans> - </Text> - <Text type="lg-thin" style={[pal.text, s.pt2]}> - <Trans> - Your posts, likes, and blocks are public. Mutes are private. - </Trans> - </Text> - </View> - </View> - <View style={[styles.row]}> - <FontAwesomeIcon icon={'at'} size={36} color={pal.colors.link} /> - <View style={[styles.rowText]}> - <Text type="lg-bold" style={[pal.text]}> - <Trans>Bluesky is open.</Trans> - </Text> - <Text type="lg-thin" style={[pal.text, s.pt2]}> - <Trans>Never lose access to your followers and data.</Trans> - </Text> - </View> - </View> - <View style={[styles.row]}> - <FontAwesomeIcon icon={'gear'} size={36} color={pal.colors.link} /> - <View style={[styles.rowText]}> - <Text type="lg-bold" style={[pal.text]}> - <Trans>Bluesky is flexible.</Trans> - </Text> - <Text type="lg-thin" style={[pal.text, s.pt2]}> - <Trans> - Choose the algorithms that power your experience with custom - feeds. - </Trans> - </Text> - </View> - </View> - </View> - - <Button - onPress={next} - label={_(msg`Continue`)} - testID="continueBtn" - style={[styles.buttonContainer]} - labelStyle={styles.buttonText} - /> - </View> - ) -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - marginBottom: 60, - marginHorizontal: 16, - justifyContent: 'space-between', - }, - title: { - fontSize: 42, - fontWeight: '800', - }, - row: { - flexDirection: 'row', - columnGap: 20, - alignItems: 'center', - marginVertical: 20, - }, - rowText: { - flex: 1, - }, - spacer: { - height: 20, - }, - buttonContainer: { - alignItems: 'center', - }, - buttonText: { - textAlign: 'center', - fontSize: 18, - marginVertical: 4, - }, -}) diff --git a/src/view/shell/createNativeStackNavigatorWithAuth.tsx b/src/view/shell/createNativeStackNavigatorWithAuth.tsx index 938213c31..882fdbe6e 100644 --- a/src/view/shell/createNativeStackNavigatorWithAuth.tsx +++ b/src/view/shell/createNativeStackNavigatorWithAuth.tsx @@ -1,11 +1,8 @@ import * as React from 'react' import {View} from 'react-native' -import {PWI_ENABLED, NEW_ONBOARDING_ENABLED} from '#/lib/build-flags' - // Based on @react-navigation/native-stack/src/createNativeStackNavigator.ts // MIT License // Copyright (c) 2017 React Navigation Contributors - import { createNavigatorFactory, EventArg, @@ -21,24 +18,24 @@ import type { NativeStackNavigationEventMap, NativeStackNavigationOptions, } from '@react-navigation/native-stack' -import type {NativeStackNavigatorProps} from '@react-navigation/native-stack/src/types' import {NativeStackView} from '@react-navigation/native-stack' +import type {NativeStackNavigatorProps} from '@react-navigation/native-stack/src/types' -import {BottomBarWeb} from './bottom-bar/BottomBarWeb' -import {DesktopLeftNav} from './desktop/LeftNav' -import {DesktopRightNav} from './desktop/RightNav' +import {PWI_ENABLED} from '#/lib/build-flags' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' +import {useSession} from '#/state/session' import {useOnboardingState} from '#/state/shell' import { useLoggedOutView, useLoggedOutViewControls, } from '#/state/shell/logged-out' -import {useSession} from '#/state/session' import {isWeb} from 'platform/detection' import {Deactivated} from '#/screens/Deactivated' +import {Onboarding} from '#/screens/Onboarding' import {LoggedOut} from '../com/auth/LoggedOut' -import {Onboarding} from '../com/auth/Onboarding' -import {Onboarding as NewOnboarding} from '#/screens/Onboarding' +import {BottomBarWeb} from './bottom-bar/BottomBarWeb' +import {DesktopLeftNav} from './desktop/LeftNav' +import {DesktopRightNav} from './desktop/RightNav' type NativeStackNavigationOptionsWithAuth = NativeStackNavigationOptions & { requireAuth?: boolean @@ -112,11 +109,7 @@ function NativeStackNavigator({ return <LoggedOut onDismiss={() => setShowLoggedOut(false)} /> } if (onboardingState.isActive) { - if (NEW_ONBOARDING_ENABLED) { - return <NewOnboarding /> - } else { - return <Onboarding /> - } + return <Onboarding /> } const newDescriptors: typeof descriptors = {} for (let key in descriptors) { |