about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2025-02-11 16:07:10 -0600
committerGitHub <noreply@github.com>2025-02-11 14:07:10 -0800
commit459611ca7a0d1559e3c9373ef9a61ea8e4c1e2f7 (patch)
tree12808a7ee8f9abce9bf06c50b047a9c426fc04f1 /src
parent03f75e8ff49d8fa0f7b96321ba8d3a5dd8841703 (diff)
downloadvoidsky-459611ca7a0d1559e3c9373ef9a61ea8e4c1e2f7.tar.zst
[APP-1031] Add new followerRule to threadgate settings (#7681)
* Add new followerRule to threadgate settings

* Handle WhoCanReply copy

* Handle follow case

* fix ci

* Revert "Handle follow case"

This reverts commit bc454dad896fe577bec91f3d65d971ad9e0fec8d.

* Hide Follow button if followedBy rule enabled

* Revert "Revert "Handle follow case""

This reverts commit cadc46d2dc50120424ed460943775c58efc59c4d.

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/components/WhoCanReply.tsx13
-rw-r--r--src/components/dialogs/PostInteractionSettingsDialog.tsx12
-rw-r--r--src/state/queries/threadgate/types.ts1
-rw-r--r--src/state/queries/threadgate/util.ts4
-rw-r--r--src/view/com/post-thread/PostThreadItem.tsx7
-rw-r--r--src/view/com/util/post-ctrls/PostCtrls.tsx14
6 files changed, 47 insertions, 4 deletions
diff --git a/src/components/WhoCanReply.tsx b/src/components/WhoCanReply.tsx
index 34ac3fe5b..7d74a50c6 100644
--- a/src/components/WhoCanReply.tsx
+++ b/src/components/WhoCanReply.tsx
@@ -258,6 +258,19 @@ function Rule({
   if (rule.type === 'mention') {
     return <Trans>mentioned users</Trans>
   }
+  if (rule.type === 'followers') {
+    return (
+      <Trans>
+        users following{' '}
+        <InlineLinkText
+          label={`@${post.author.handle}`}
+          to={makeProfileLink(post.author)}
+          style={[a.text_sm, a.leading_snug]}>
+          @{post.author.handle}
+        </InlineLinkText>
+      </Trans>
+    )
+  }
   if (rule.type === 'following') {
     return (
       <Trans>
diff --git a/src/components/dialogs/PostInteractionSettingsDialog.tsx b/src/components/dialogs/PostInteractionSettingsDialog.tsx
index b443d59f2..e4bc77702 100644
--- a/src/components/dialogs/PostInteractionSettingsDialog.tsx
+++ b/src/components/dialogs/PostInteractionSettingsDialog.tsx
@@ -429,7 +429,7 @@ export function PostInteractionSettingsForm({
                     disabled={replySettingsDisabled}
                   />
                   <Selectable
-                    label={_(msg`Followed users`)}
+                    label={_(msg`Users you follow`)}
                     isSelected={
                       !!threadgateAllowUISettings.find(
                         v => v.type === 'following',
@@ -438,6 +438,16 @@ export function PostInteractionSettingsForm({
                     onPress={() => onPressAudience({type: 'following'})}
                     disabled={replySettingsDisabled}
                   />
+                  <Selectable
+                    label={_(msg`Your followers`)}
+                    isSelected={
+                      !!threadgateAllowUISettings.find(
+                        v => v.type === 'followers',
+                      )
+                    }
+                    onPress={() => onPressAudience({type: 'followers'})}
+                    disabled={replySettingsDisabled}
+                  />
                   {lists && lists.length > 0
                     ? lists.map(list => (
                         <Selectable
diff --git a/src/state/queries/threadgate/types.ts b/src/state/queries/threadgate/types.ts
index 0cbea311c..56eadabcd 100644
--- a/src/state/queries/threadgate/types.ts
+++ b/src/state/queries/threadgate/types.ts
@@ -3,4 +3,5 @@ export type ThreadgateAllowUISetting =
   | {type: 'nobody'}
   | {type: 'mention'}
   | {type: 'following'}
+  | {type: 'followers'}
   | {type: 'list'; list: unknown}
diff --git a/src/state/queries/threadgate/util.ts b/src/state/queries/threadgate/util.ts
index 09ae0a0c1..4459eddbe 100644
--- a/src/state/queries/threadgate/util.ts
+++ b/src/state/queries/threadgate/util.ts
@@ -43,6 +43,8 @@ export function threadgateRecordToAllowUISetting(
         setting = {type: 'mention'}
       } else if (allow.$type === 'app.bsky.feed.threadgate#followingRule') {
         setting = {type: 'following'}
+      } else if (allow.$type === 'app.bsky.feed.threadgate#followerRule') {
+        setting = {type: 'followers'}
       } else if (allow.$type === 'app.bsky.feed.threadgate#listRule') {
         setting = {type: 'list', list: allow.list}
       }
@@ -79,6 +81,8 @@ export function threadgateAllowUISettingToAllowRecordValue(
         allow.push({$type: 'app.bsky.feed.threadgate#mentionRule'})
       } else if (rule.type === 'following') {
         allow.push({$type: 'app.bsky.feed.threadgate#followingRule'})
+      } else if (rule.type === 'followers') {
+        allow.push({$type: 'app.bsky.feed.threadgate#followerRule'})
       } else if (rule.type === 'list') {
         allow.push({
           $type: 'app.bsky.feed.threadgate#listRule',
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 4f950e261..928ccd783 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -241,6 +241,11 @@ let PostThreadItemLoaded = ({
     return makeProfileLink(post.author, 'post', urip.rkey, 'quotes')
   }, [post.uri, post.author])
   const quotesTitle = _(msg`Quotes of this post`)
+  const onlyFollowersCanReply = !!threadgateRecord?.allow?.find(
+    rule => rule.$type === 'app.bsky.feed.threadgate#followerRule',
+  )
+  const showFollowButton =
+    currentAccount?.did !== post.author.did && !onlyFollowersCanReply
 
   const translatorUrl = getTranslatorLink(
     record?.text || '',
@@ -343,7 +348,7 @@ let PostThreadItemLoaded = ({
                 </Text>
               </Link>
             </View>
-            {currentAccount?.did !== post.author.did && (
+            {showFollowButton && (
               <View>
                 <PostThreadFollowBtn did={post.author.did} />
               </View>
diff --git a/src/view/com/util/post-ctrls/PostCtrls.tsx b/src/view/com/util/post-ctrls/PostCtrls.tsx
index f73cede35..b61bad2ca 100644
--- a/src/view/com/util/post-ctrls/PostCtrls.tsx
+++ b/src/view/com/util/post-ctrls/PostCtrls.tsx
@@ -26,6 +26,7 @@ import {makeProfileLink} from '#/lib/routes/links'
 import {shareUrl} from '#/lib/sharing'
 import {useGate} from '#/lib/statsig/statsig'
 import {toShareUrl} from '#/lib/strings/url-helpers'
+import {useProfileShadow} from '#/state/cache/profile-shadow'
 import {Shadow} from '#/state/cache/types'
 import {useFeedFeedbackContext} from '#/state/feed-feedback'
 import {
@@ -94,6 +95,15 @@ let PostCtrls = ({
       post.author.viewer?.blockingByList,
   )
 
+  const shadowedAuthor = useProfileShadow(post.author)
+  const followersCanReply = !!threadgateRecord?.allow?.find(
+    rule => rule.$type === 'app.bsky.feed.threadgate#followerRule',
+  )
+  const canOverrideReplyDisabled =
+    followersCanReply &&
+    shadowedAuthor.viewer?.following?.startsWith('at://did')
+  const replyDisabled = post.viewer?.replyDisabled && !canOverrideReplyDisabled
+
   const shouldShowLoggedOutWarning = React.useMemo(() => {
     return (
       post.author.did !== currentAccount?.did &&
@@ -247,13 +257,13 @@ let PostCtrls = ({
       <View
         style={[
           big ? a.align_center : [a.flex_1, a.align_start, {marginLeft: -6}],
-          post.viewer?.replyDisabled ? {opacity: 0.5} : undefined,
+          replyDisabled ? {opacity: 0.5} : undefined,
         ]}>
         <Pressable
           testID="replyBtn"
           style={btnStyle}
           onPress={() => {
-            if (!post.viewer?.replyDisabled) {
+            if (!replyDisabled) {
               playHaptic('Light')
               requireAuth(() => onPressReply())
             }