about summary refs log tree commit diff
path: root/src/view/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com')
-rw-r--r--src/view/com/auth/HomeLoggedOutCTA.tsx165
-rw-r--r--src/view/com/auth/LoggedOut.tsx4
-rw-r--r--src/view/com/post-thread/PostThread.tsx18
-rw-r--r--src/view/com/profile/ProfileCard.tsx3
-rw-r--r--src/view/com/util/moderation/ContentHider.tsx20
-rw-r--r--src/view/com/util/moderation/ScreenHider.tsx64
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>
   )
 }