diff options
Diffstat (limited to 'src/view/com')
-rw-r--r-- | src/view/com/auth/HomeLoggedOutCTA.tsx | 165 | ||||
-rw-r--r-- | src/view/com/auth/LoggedOut.tsx | 4 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThread.tsx | 18 | ||||
-rw-r--r-- | src/view/com/profile/ProfileCard.tsx | 3 | ||||
-rw-r--r-- | src/view/com/util/moderation/ContentHider.tsx | 20 | ||||
-rw-r--r-- | src/view/com/util/moderation/ScreenHider.tsx | 64 |
6 files changed, 238 insertions, 36 deletions
diff --git a/src/view/com/auth/HomeLoggedOutCTA.tsx b/src/view/com/auth/HomeLoggedOutCTA.tsx new file mode 100644 index 000000000..32b873ac6 --- /dev/null +++ b/src/view/com/auth/HomeLoggedOutCTA.tsx @@ -0,0 +1,165 @@ +import React from 'react' +import {StyleSheet, TouchableOpacity, View} from 'react-native' +import {useLingui} from '@lingui/react' +import {Trans, msg} from '@lingui/macro' +import {ScrollView} from '../util/Views' +import {Text} from '../util/text/Text' +import {usePalette} from '#/lib/hooks/usePalette' +import {colors, s} from '#/lib/styles' +import {TextLink} from '../util/Link' +import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' +import {useLoggedOutViewControls} from '#/state/shell/logged-out' + +export function HomeLoggedOutCTA() { + const pal = usePalette('default') + const {_} = useLingui() + const {isMobile} = useWebMediaQueries() + const {requestSwitchToAccount} = useLoggedOutViewControls() + + const showCreateAccount = React.useCallback(() => { + requestSwitchToAccount({requestedAccount: 'new'}) + }, [requestSwitchToAccount]) + + const showSignIn = React.useCallback(() => { + requestSwitchToAccount({requestedAccount: 'none'}) + }, [requestSwitchToAccount]) + + return ( + <ScrollView style={styles.container} testID="loggedOutCTA"> + <View style={[styles.hero, isMobile && styles.heroMobile]}> + <Text style={[styles.title, pal.link]}> + <Trans>Bluesky</Trans> + </Text> + <Text + style={[ + styles.subtitle, + isMobile && styles.subtitleMobile, + pal.textLight, + ]}> + <Trans>See what's next</Trans> + </Text> + </View> + <View + testID="signinOrCreateAccount" + style={isMobile ? undefined : styles.btnsDesktop}> + <TouchableOpacity + testID="createAccountButton" + style={[ + styles.btn, + isMobile && styles.btnMobile, + {backgroundColor: colors.blue3}, + ]} + onPress={showCreateAccount} + accessibilityRole="button" + accessibilityLabel={_(msg`Create new account`)} + accessibilityHint="Opens flow to create a new Bluesky account"> + <Text + style={[ + s.white, + styles.btnLabel, + isMobile && styles.btnLabelMobile, + ]}> + <Trans>Create a new account</Trans> + </Text> + </TouchableOpacity> + <TouchableOpacity + testID="signInButton" + style={[styles.btn, isMobile && styles.btnMobile, pal.btn]} + onPress={showSignIn} + accessibilityRole="button" + accessibilityLabel={_(msg`Sign in`)} + accessibilityHint="Opens flow to sign into your existing Bluesky account"> + <Text + style={[ + pal.text, + styles.btnLabel, + isMobile && styles.btnLabelMobile, + ]}> + <Trans>Sign In</Trans> + </Text> + </TouchableOpacity> + </View> + + <View style={[styles.footer, pal.view, pal.border]}> + <TextLink + type="2xl" + href="https://blueskyweb.xyz" + text={_(msg`Business`)} + style={[styles.footerLink, pal.link]} + /> + <TextLink + type="2xl" + href="https://blueskyweb.xyz/blog" + text={_(msg`Blog`)} + style={[styles.footerLink, pal.link]} + /> + <TextLink + type="2xl" + href="https://blueskyweb.xyz/join" + text={_(msg`Jobs`)} + style={[styles.footerLink, pal.link]} + /> + </View> + </ScrollView> + ) +} + +const styles = StyleSheet.create({ + container: { + height: '100%', + }, + hero: { + justifyContent: 'center', + paddingTop: 100, + paddingBottom: 30, + }, + heroMobile: { + paddingBottom: 50, + }, + title: { + textAlign: 'center', + fontSize: 68, + fontWeight: 'bold', + }, + subtitle: { + textAlign: 'center', + fontSize: 48, + fontWeight: 'bold', + }, + subtitleMobile: { + fontSize: 42, + }, + btnsDesktop: { + flexDirection: 'row', + justifyContent: 'center', + gap: 20, + marginHorizontal: 20, + }, + btn: { + borderRadius: 32, + width: 230, + paddingVertical: 12, + marginBottom: 20, + }, + btnMobile: { + flex: 1, + width: 'auto', + marginHorizontal: 20, + paddingVertical: 16, + }, + btnLabel: { + textAlign: 'center', + fontSize: 18, + }, + btnLabelMobile: { + textAlign: 'center', + fontSize: 21, + }, + + footer: { + flexDirection: 'row', + gap: 20, + justifyContent: 'center', + }, + footerLink: {}, +}) diff --git a/src/view/com/auth/LoggedOut.tsx b/src/view/com/auth/LoggedOut.tsx index fcff4f782..b0b2bf7ed 100644 --- a/src/view/com/auth/LoggedOut.tsx +++ b/src/view/com/auth/LoggedOut.tsx @@ -33,7 +33,9 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { const {requestedAccountSwitchTo} = useLoggedOutView() const [screenState, setScreenState] = React.useState<ScreenState>( requestedAccountSwitchTo - ? ScreenState.S_Login + ? requestedAccountSwitchTo === 'new' + ? ScreenState.S_CreateAccount + : ScreenState.S_Login : ScreenState.S_LoginOrCreateAccount, ) const {isMobile} = useWebMediaQueries() diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx index f27da331f..917550884 100644 --- a/src/view/com/post-thread/PostThread.tsx +++ b/src/view/com/post-thread/PostThread.tsx @@ -157,7 +157,9 @@ function PostThreadLoaded({ // construct content const posts = React.useMemo(() => { let arr = [TOP_COMPONENT].concat( - Array.from(flattenThreadSkeleton(sortThread(thread, threadViewPrefs))), + Array.from( + flattenThreadSkeleton(sortThread(thread, threadViewPrefs), hasSession), + ), ) if (arr.length > maxVisible) { arr = arr.slice(0, maxVisible).concat([LOAD_MORE]) @@ -166,7 +168,7 @@ function PostThreadLoaded({ arr.push(BOTTOM_COMPONENT) } return arr - }, [thread, maxVisible, threadViewPrefs]) + }, [thread, maxVisible, threadViewPrefs, hasSession]) /** * NOTE @@ -468,20 +470,24 @@ function isThreadPost(v: unknown): v is ThreadPost { function* flattenThreadSkeleton( node: ThreadNode, + hasSession: boolean, ): Generator<YieldedItem, void> { if (node.type === 'post') { if (node.parent) { - yield* flattenThreadSkeleton(node.parent) + yield* flattenThreadSkeleton(node.parent, hasSession) } else if (node.ctx.isParentLoading) { yield PARENT_SPINNER } + if (!hasSession && node.ctx.depth > 0 && hasPwiOptOut(node)) { + return + } yield node if (node.ctx.isHighlightedPost && !node.post.viewer?.replyDisabled) { yield REPLY_PROMPT } if (node.replies?.length) { for (const reply of node.replies) { - yield* flattenThreadSkeleton(reply) + yield* flattenThreadSkeleton(reply, hasSession) } } else if (node.ctx.isChildLoading) { yield CHILD_SPINNER @@ -493,6 +499,10 @@ function* flattenThreadSkeleton( } } +function hasPwiOptOut(node: ThreadPost) { + return !!node.post.author.labels?.find(l => l.val === '!no-unauthenticated') +} + function hasBranchingReplies(node: ThreadNode) { if (node.type !== 'post') { return false diff --git a/src/view/com/profile/ProfileCard.tsx b/src/view/com/profile/ProfileCard.tsx index 21972f274..c5b2dc528 100644 --- a/src/view/com/profile/ProfileCard.tsx +++ b/src/view/com/profile/ProfileCard.tsx @@ -50,6 +50,9 @@ export function ProfileCard({ return null } const moderation = moderateProfile(profile, moderationOpts) + if (moderation.account.filter) { + return null + } return ( <Link diff --git a/src/view/com/util/moderation/ContentHider.tsx b/src/view/com/util/moderation/ContentHider.tsx index b1ea76621..1269b7ebf 100644 --- a/src/view/com/util/moderation/ContentHider.tsx +++ b/src/view/com/util/moderation/ContentHider.tsx @@ -7,7 +7,7 @@ import {Text} from '../text/Text' import {ShieldExclamation} from 'lib/icons' import {describeModerationCause} from 'lib/moderation' import {useLingui} from '@lingui/react' -import {msg} from '@lingui/macro' +import {msg, Trans} from '@lingui/macro' import {useModalControls} from '#/state/modals' import {isPostMediaBlurred} from 'lib/moderation' @@ -95,13 +95,17 @@ export function ContentHider({ <Text type="md" style={pal.text}> {desc.name} </Text> - {!moderation.noOverride && ( - <View style={styles.showBtn}> - <Text type="lg" style={pal.link}> - {override ? 'Hide' : 'Show'} - </Text> - </View> - )} + <View style={styles.showBtn}> + <Text type="lg" style={pal.link}> + {moderation.noOverride ? ( + <Trans>Learn more</Trans> + ) : override ? ( + <Trans>Hide</Trans> + ) : ( + <Trans>Show</Trans> + )} + </Text> + </View> </Pressable> {override && <View style={childContainerStyle}>{children}</View>} </View> diff --git a/src/view/com/util/moderation/ScreenHider.tsx b/src/view/com/util/moderation/ScreenHider.tsx index 946f937e9..86f0cbf7b 100644 --- a/src/view/com/util/moderation/ScreenHider.tsx +++ b/src/view/com/util/moderation/ScreenHider.tsx @@ -22,6 +22,7 @@ import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useModalControls} from '#/state/modals' import {s} from '#/lib/styles' +import {CenteredView} from '../Views' export function ScreenHider({ testID, @@ -53,41 +54,58 @@ export function ScreenHider({ ) } + const isNoPwi = + moderation.cause?.type === 'label' && + moderation.cause?.labelDef.id === '!no-unauthenticated' const desc = describeModerationCause(moderation.cause, 'account') return ( - <View style={[styles.container, pal.view, containerStyle]}> + <CenteredView + style={[styles.container, pal.view, containerStyle]} + sideBorders> <View style={styles.iconContainer}> <View style={[styles.icon, palInverted.view]}> <FontAwesomeIcon - icon="exclamation" + icon={isNoPwi ? ['far', 'eye-slash'] : 'exclamation'} style={pal.textInverted as FontAwesomeIconStyle} size={24} /> </View> </View> <Text type="title-2xl" style={[styles.title, pal.text]}> - <Trans>Content Warning</Trans> + {isNoPwi ? ( + <Trans>Sign-in Required</Trans> + ) : ( + <Trans>Content Warning</Trans> + )} </Text> <Text type="2xl" style={[styles.description, pal.textLight]}> - <Trans>This {screenDescription} has been flagged:</Trans> - <Text type="2xl-medium" style={[pal.text, s.ml5]}> - {desc.name}. - </Text> - <TouchableWithoutFeedback - onPress={() => { - openModal({ - name: 'moderation-details', - context: 'account', - moderation, - }) - }} - accessibilityRole="button" - accessibilityLabel={_(msg`Learn more about this warning`)} - accessibilityHint=""> - <Text type="2xl" style={pal.link}> - <Trans>Learn More</Trans> - </Text> - </TouchableWithoutFeedback> + {isNoPwi ? ( + <Trans> + This account has requested that users sign in to view their profile. + </Trans> + ) : ( + <> + <Trans>This {screenDescription} has been flagged:</Trans> + <Text type="2xl-medium" style={[pal.text, s.ml5]}> + {desc.name}. + </Text> + <TouchableWithoutFeedback + onPress={() => { + openModal({ + name: 'moderation-details', + context: 'account', + moderation, + }) + }} + accessibilityRole="button" + accessibilityLabel={_(msg`Learn more about this warning`)} + accessibilityHint=""> + <Text type="2xl" style={pal.link}> + <Trans>Learn More</Trans> + </Text> + </TouchableWithoutFeedback> + </> + )}{' '} </Text> {isMobile && <View style={styles.spacer} />} <View style={styles.btnContainer}> @@ -116,7 +134,7 @@ export function ScreenHider({ </Button> )} </View> - </View> + </CenteredView> ) } |