diff options
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/components/WhoCanReply.tsx | 13 | ||||
-rw-r--r-- | src/components/dialogs/PostInteractionSettingsDialog.tsx | 12 | ||||
-rw-r--r-- | src/state/queries/threadgate/types.ts | 1 | ||||
-rw-r--r-- | src/state/queries/threadgate/util.ts | 4 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThreadItem.tsx | 7 | ||||
-rw-r--r-- | src/view/com/util/post-ctrls/PostCtrls.tsx | 14 | ||||
-rw-r--r-- | yarn.lock | 54 |
8 files changed, 94 insertions, 13 deletions
diff --git a/package.json b/package.json index bc161b8bc..708ed7ccf 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "icons:optimize": "svgo -f ./assets/icons" }, "dependencies": { - "@atproto/api": "^0.13.33", + "@atproto/api": "^0.13.35", "@bitdrift/react-native": "^0.6.2", "@braintree/sanitize-url": "^6.0.2", "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", 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()) } diff --git a/yarn.lock b/yarn.lock index f6a3781c0..e2792a4cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -72,10 +72,10 @@ tlds "^1.234.0" zod "^3.23.8" -"@atproto/api@^0.13.33": - version "0.13.33" - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.33.tgz#01d31a1cfd1be311e11324b810b8a83fe4cbf9b0" - integrity sha512-d8AOvtxo2J2zrmcakJTUtLdz2ns+pAqywNXhPxPzHrHcw79D6MKBLHR0vr8oxkGwhDBQTsHiQWTk4gSo8PF7YA== +"@atproto/api@^0.13.35": + version "0.13.35" + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.35.tgz#1e3a6c6e035c8e06302508983ed206effc92a7e8" + integrity sha512-vsEfBj0C333TLjDppvTdTE0IdKlXuljKSveAeI4PPx/l6eUKNnDTsYxvILtXUVzwUlTDmSRqy5O4Ryh78n1b7g== dependencies: "@atproto/common-web" "^0.4.0" "@atproto/lexicon" "^0.4.6" @@ -3295,7 +3295,7 @@ "@babel/parser" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9": +"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== @@ -3356,6 +3356,19 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" + integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/generator" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/template" "^7.25.9" + "@babel/types" "^7.25.9" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.10", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.22.10" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03" @@ -17644,7 +17657,16 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17744,7 +17766,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17758,6 +17780,13 @@ strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -19032,7 +19061,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19050,6 +19079,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" |