diff options
Diffstat (limited to 'src/view/com')
-rw-r--r-- | src/view/com/auth/LoggedOut.tsx | 42 | ||||
-rw-r--r-- | src/view/com/feeds/FeedSourceCard.tsx | 3 | ||||
-rw-r--r-- | src/view/com/notifications/FeedItem.tsx | 87 | ||||
-rw-r--r-- | src/view/com/profile/FollowButton.tsx | 11 | ||||
-rw-r--r-- | src/view/com/profile/ProfileCard.tsx | 6 | ||||
-rw-r--r-- | src/view/com/profile/ProfileSubpageHeader.tsx | 10 |
6 files changed, 126 insertions, 33 deletions
diff --git a/src/view/com/auth/LoggedOut.tsx b/src/view/com/auth/LoggedOut.tsx index c8c81dd77..29127ec45 100644 --- a/src/view/com/auth/LoggedOut.tsx +++ b/src/view/com/auth/LoggedOut.tsx @@ -7,7 +7,6 @@ import {useNavigation} from '@react-navigation/native' import {useAnalytics} from '#/lib/analytics/analytics' import {usePalette} from '#/lib/hooks/usePalette' -import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {logEvent} from '#/lib/statsig/statsig' import {s} from '#/lib/styles' import {isIOS, isNative} from '#/platform/detection' @@ -22,13 +21,16 @@ import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {Text} from '#/view/com/util/text/Text' import {Login} from '#/screens/Login' import {Signup} from '#/screens/Signup' +import {LandingScreen} from '#/screens/StarterPack/StarterPackLandingScreen' import {SplashScreen} from './SplashScreen' enum ScreenState { S_LoginOrCreateAccount, S_Login, S_CreateAccount, + S_StarterPack, } +export {ScreenState as LoggedOutScreenState} export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { const {hasSession} = useSession() @@ -37,18 +39,21 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { const setMinimalShellMode = useSetMinimalShellMode() const {screen} = useAnalytics() const {requestedAccountSwitchTo} = useLoggedOutView() - const [screenState, setScreenState] = React.useState<ScreenState>( - requestedAccountSwitchTo - ? requestedAccountSwitchTo === 'new' - ? ScreenState.S_CreateAccount - : ScreenState.S_Login - : ScreenState.S_LoginOrCreateAccount, - ) - const {isMobile} = useWebMediaQueries() + const [screenState, setScreenState] = React.useState<ScreenState>(() => { + if (requestedAccountSwitchTo === 'new') { + return ScreenState.S_CreateAccount + } else if (requestedAccountSwitchTo === 'starterpack') { + return ScreenState.S_StarterPack + } else if (requestedAccountSwitchTo != null) { + return ScreenState.S_Login + } else { + return ScreenState.S_LoginOrCreateAccount + } + }) const {clearRequestedAccount} = useLoggedOutViewControls() const navigation = useNavigation<NavigationProp>() - const isFirstScreen = screenState === ScreenState.S_LoginOrCreateAccount + const isFirstScreen = screenState === ScreenState.S_LoginOrCreateAccount React.useEffect(() => { screen('Login') setMinimalShellMode(true) @@ -66,18 +71,9 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { }, [navigation]) return ( - <View - testID="noSessionView" - style={[ - s.hContentRegion, - pal.view, - { - // only needed if dismiss button is present - paddingTop: onDismiss && isMobile ? 40 : 0, - }, - ]}> + <View testID="noSessionView" style={[s.hContentRegion, pal.view]}> <ErrorBoundary> - {onDismiss ? ( + {onDismiss && screenState === ScreenState.S_LoginOrCreateAccount ? ( <Pressable accessibilityHint={_(msg`Go back`)} accessibilityLabel={_(msg`Go back`)} @@ -132,7 +128,9 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { </Pressable> ) : null} - {screenState === ScreenState.S_LoginOrCreateAccount ? ( + {screenState === ScreenState.S_StarterPack ? ( + <LandingScreen setScreenState={setScreenState} /> + ) : screenState === ScreenState.S_LoginOrCreateAccount ? ( <SplashScreen onPressSignin={() => { setScreenState(ScreenState.S_Login) diff --git a/src/view/com/feeds/FeedSourceCard.tsx b/src/view/com/feeds/FeedSourceCard.tsx index a61789434..d216849c5 100644 --- a/src/view/com/feeds/FeedSourceCard.tsx +++ b/src/view/com/feeds/FeedSourceCard.tsx @@ -329,6 +329,9 @@ const styles = StyleSheet.create({ flex: 1, gap: 14, }, + border: { + borderTopWidth: hairlineWidth, + }, headerContainer: { flexDirection: 'row', }, diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx index 9cd7a2917..2f8d65a1d 100644 --- a/src/view/com/notifications/FeedItem.tsx +++ b/src/view/com/notifications/FeedItem.tsx @@ -52,7 +52,16 @@ import {TimeElapsed} from '../util/TimeElapsed' import {PreviewableUserAvatar, UserAvatar} from '../util/UserAvatar' import hairlineWidth = StyleSheet.hairlineWidth +import {useNavigation} from '@react-navigation/native' + import {parseTenorGif} from '#/lib/strings/embed-player' +import {logger} from '#/logger' +import {NavigationProp} from 'lib/routes/types' +import {DM_SERVICE_HEADERS} from 'state/queries/messages/const' +import {useAgent} from 'state/session' +import {Button, ButtonText} from '#/components/Button' +import {StarterPack} from '#/components/icons/StarterPack' +import {Notification as StarterPackCard} from '#/components/StarterPack/StarterPackCard' const MAX_AUTHORS = 5 @@ -89,7 +98,10 @@ let FeedItem = ({ } else if (item.type === 'reply') { const urip = new AtUri(item.notification.uri) return `/profile/${urip.host}/post/${urip.rkey}` - } else if (item.type === 'feedgen-like') { + } else if ( + item.type === 'feedgen-like' || + item.type === 'starterpack-joined' + ) { if (item.subjectUri) { const urip = new AtUri(item.subjectUri) return `/profile/${urip.host}/feed/${urip.rkey}` @@ -176,6 +188,13 @@ let FeedItem = ({ icon = <PersonPlusIcon size="xl" style={{color: t.palette.primary_500}} /> } else if (item.type === 'feedgen-like') { action = _(msg`liked your custom feed`) + } else if (item.type === 'starterpack-joined') { + icon = ( + <View style={{height: 30, width: 30}}> + <StarterPack width={30} gradient="sky" /> + </View> + ) + action = _(msg`signed up with your starter pack`) } else { return null } @@ -289,6 +308,20 @@ let FeedItem = ({ showLikes /> ) : null} + {item.type === 'starterpack-joined' ? ( + <View> + <View + style={[ + a.border, + a.p_sm, + a.rounded_sm, + a.mt_sm, + t.atoms.border_contrast_low, + ]}> + <StarterPackCard starterPack={item.subject} /> + </View> + </View> + ) : null} </View> </Link> ) @@ -319,14 +352,63 @@ function ExpandListPressable({ } } +function SayHelloBtn({profile}: {profile: AppBskyActorDefs.ProfileViewBasic}) { + const {_} = useLingui() + const agent = useAgent() + const navigation = useNavigation<NavigationProp>() + const [isLoading, setIsLoading] = React.useState(false) + + if ( + profile.associated?.chat?.allowIncoming === 'none' || + (profile.associated?.chat?.allowIncoming === 'following' && + !profile.viewer?.followedBy) + ) { + return null + } + + return ( + <Button + label={_(msg`Say hello!`)} + variant="ghost" + color="primary" + size="xsmall" + style={[a.self_center, {marginLeft: 'auto'}]} + disabled={isLoading} + onPress={async () => { + try { + setIsLoading(true) + const res = await agent.api.chat.bsky.convo.getConvoForMembers( + { + members: [profile.did, agent.session!.did!], + }, + {headers: DM_SERVICE_HEADERS}, + ) + navigation.navigate('MessagesConversation', { + conversation: res.data.convo.id, + }) + } catch (e) { + logger.error('Failed to get conversation', {safeMessage: e}) + } finally { + setIsLoading(false) + } + }}> + <ButtonText> + <Trans>Say hello!</Trans> + </ButtonText> + </Button> + ) +} + function CondensedAuthorsList({ visible, authors, onToggleAuthorsExpanded, + showDmButton = true, }: { visible: boolean authors: Author[] onToggleAuthorsExpanded: () => void + showDmButton?: boolean }) { const pal = usePalette('default') const {_} = useLingui() @@ -355,7 +437,7 @@ function CondensedAuthorsList({ } if (authors.length === 1) { return ( - <View style={styles.avis}> + <View style={[styles.avis]}> <PreviewableUserAvatar size={35} profile={authors[0].profile} @@ -363,6 +445,7 @@ function CondensedAuthorsList({ type={authors[0].profile.associated?.labeler ? 'labeler' : 'user'} accessible={false} /> + {showDmButton ? <SayHelloBtn profile={authors[0].profile} /> : null} </View> ) } diff --git a/src/view/com/profile/FollowButton.tsx b/src/view/com/profile/FollowButton.tsx index 7b090ffeb..8e63da85b 100644 --- a/src/view/com/profile/FollowButton.tsx +++ b/src/view/com/profile/FollowButton.tsx @@ -1,12 +1,13 @@ import React from 'react' import {StyleProp, TextStyle, View} from 'react-native' import {AppBskyActorDefs} from '@atproto/api' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {Shadow} from '#/state/cache/types' +import {useProfileFollowMutationQueue} from '#/state/queries/profile' import {Button, ButtonType} from '../util/forms/Button' import * as Toast from '../util/Toast' -import {useProfileFollowMutationQueue} from '#/state/queries/profile' -import {Shadow} from '#/state/cache/types' -import {useLingui} from '@lingui/react' -import {msg} from '@lingui/macro' export function FollowButton({ unfollowedType = 'inverted', @@ -19,7 +20,7 @@ export function FollowButton({ followedType?: ButtonType profile: Shadow<AppBskyActorDefs.ProfileViewBasic> labelStyle?: StyleProp<TextStyle> - logContext: 'ProfileCard' + logContext: 'ProfileCard' | 'StarterPackProfilesList' }) { const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue( profile, diff --git a/src/view/com/profile/ProfileCard.tsx b/src/view/com/profile/ProfileCard.tsx index a3cd5ca1b..d7ed0dd6a 100644 --- a/src/view/com/profile/ProfileCard.tsx +++ b/src/view/com/profile/ProfileCard.tsx @@ -251,12 +251,14 @@ export function ProfileCardWithFollowBtn({ noBorder, followers, onPress, + logContext = 'ProfileCard', }: { profile: AppBskyActorDefs.ProfileViewBasic noBg?: boolean noBorder?: boolean followers?: AppBskyActorDefs.ProfileView[] | undefined onPress?: () => void + logContext?: 'ProfileCard' | 'StarterPackProfilesList' }) { const {currentAccount} = useSession() const isMe = profile.did === currentAccount?.did @@ -271,7 +273,7 @@ export function ProfileCardWithFollowBtn({ isMe ? undefined : profileShadow => ( - <FollowButton profile={profileShadow} logContext="ProfileCard" /> + <FollowButton profile={profileShadow} logContext={logContext} /> ) } onPress={onPress} @@ -314,6 +316,7 @@ const styles = StyleSheet.create({ paddingRight: 10, }, details: { + justifyContent: 'center', paddingLeft: 54, paddingRight: 10, paddingBottom: 10, @@ -339,7 +342,6 @@ const styles = StyleSheet.create({ followedBy: { flexDirection: 'row', - alignItems: 'center', paddingLeft: 54, paddingRight: 20, marginBottom: 10, diff --git a/src/view/com/profile/ProfileSubpageHeader.tsx b/src/view/com/profile/ProfileSubpageHeader.tsx index edc6b75f9..ac5febcda 100644 --- a/src/view/com/profile/ProfileSubpageHeader.tsx +++ b/src/view/com/profile/ProfileSubpageHeader.tsx @@ -21,7 +21,9 @@ import {Text} from '../util/text/Text' import {UserAvatar, UserAvatarType} from '../util/UserAvatar' import {CenteredView} from '../util/Views' import hairlineWidth = StyleSheet.hairlineWidth + import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu' +import {StarterPack} from '#/components/icons/StarterPack' export function ProfileSubpageHeader({ isLoading, @@ -44,7 +46,7 @@ export function ProfileSubpageHeader({ handle: string } | undefined - avatarType: UserAvatarType + avatarType: UserAvatarType | 'starter-pack' }>) { const setDrawerOpen = useSetDrawerOpen() const navigation = useNavigation<NavigationProp>() @@ -127,7 +129,11 @@ export function ProfileSubpageHeader({ accessibilityLabel={_(msg`View the avatar`)} accessibilityHint="" style={{width: 58}}> - <UserAvatar type={avatarType} size={58} avatar={avatar} /> + {avatarType === 'starter-pack' ? ( + <StarterPack width={58} gradient="sky" /> + ) : ( + <UserAvatar type={avatarType} size={58} avatar={avatar} /> + )} </Pressable> <View style={{flex: 1}}> {isLoading ? ( |