Add algorithmic visibility setting

This commit is contained in:
vineyardbovines
2026-08-07 08:42:39 -04:00
parent 1cbe7a39e6
commit bb4796de86
3 changed files with 123 additions and 15 deletions
@@ -14,9 +14,11 @@ import * as Admonition from '#/components/Admonition'
import {BellRinging_Stroke2_Corner0_Rounded as BellRingingIcon} from '#/components/icons/BellRinging'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlashIcon} from '#/components/icons/EyeSlash'
import {Key_Stroke2_Corner2_Rounded as KeyIcon} from '#/components/icons/Key'
import {MagnifyingGlass_Stroke2_Corner0_Rounded as MagnifyingGlassIcon} from '#/components/icons/MagnifyingGlass'
import {ShieldCheck_Stroke2_Corner0_Rounded as ShieldIcon} from '#/components/icons/Shield'
import * as Layout from '#/components/Layout'
import {InlineLinkText} from '#/components/Link'
import {AlgoVisibilityOptOut} from './components/AlgoVisibilityOptOut'
import {Email2FAToggle} from './components/Email2FAToggle'
import {PwiOptOut} from './components/PwiOptOut'
import {ItemTextWithSubtitle} from './NotificationSettings/components/ItemTextWithSubtitle'
@@ -101,13 +103,14 @@ export function PrivacyAndSecuritySettingsScreen({}: Props) {
/>
</SettingsList.LinkItem>
<SettingsList.Divider />
<SettingsList.Group>
<SettingsList.Item style={[a.align_start]}>
<SettingsList.ItemIcon icon={MagnifyingGlassIcon} />
<AlgoVisibilityOptOut />
</SettingsList.Item>
<SettingsList.Item style={[a.align_start]}>
<SettingsList.ItemIcon icon={EyeSlashIcon} />
<SettingsList.ItemText>
<Trans>Logged-out visibility</Trans>
</SettingsList.ItemText>
<PwiOptOut />
</SettingsList.Group>
</SettingsList.Item>
<SettingsList.Item>
<Admonition.Outer type="tip" style={[a.flex_1]}>
<Admonition.Row>
@@ -115,11 +118,10 @@ export function PrivacyAndSecuritySettingsScreen({}: Props) {
<Admonition.Content>
<Admonition.Text>
<Trans>
Note: Bluesky is an open and public network. This setting
only limits the visibility of your content on the Bluesky
app and website, and other apps may not respect this
setting. Your content may still be shown to logged-out
users by other apps and websites.
Note: Bluesky is part of the Atmosphere, an open public
network. These settings ask other apps and websites to
limit your visibility, but they can choose not to. Your
public content may still appear elsewhere.
</Trans>
</Admonition.Text>
<Admonition.Text>
@@ -0,0 +1,106 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {type $Typed, ComAtprotoLabelDefs} from '@atproto/api'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {
useProfileQuery,
useProfileUpdateMutation,
} from '#/state/queries/profile'
import {useSession} from '#/state/session'
import {atoms as a, useTheme} from '#/alf'
import * as Toggle from '#/components/forms/Toggle'
import {Text} from '#/components/Typography'
import * as bsky from '#/types/bsky'
const NO_PROMOTE_LABEL = '!no-promote'
export function AlgoVisibilityOptOut() {
const t = useTheme()
const {_} = useLingui()
const {currentAccount} = useSession()
const {data: profile} = useProfileQuery({did: currentAccount?.did})
const updateProfile = useProfileUpdateMutation()
const isOptedOut =
profile?.labels?.some(label => label.val === NO_PROMOTE_LABEL) || false
const canToggle = profile && !updateProfile.isPending
const onToggleOptOut = useCallback(() => {
if (!profile) {
return
}
let wasAdded = false
updateProfile.mutate({
profile,
updates: existing => {
const labels: $Typed<ComAtprotoLabelDefs.SelfLabels> = bsky.validate(
existing.labels,
ComAtprotoLabelDefs.validateSelfLabels,
)
? existing.labels
: {
$type: 'com.atproto.label.defs#selfLabels',
values: [],
}
const hasLabel = labels.values.some(
label => label.val === NO_PROMOTE_LABEL,
)
if (hasLabel) {
labels.values = labels.values.filter(
label => label.val !== NO_PROMOTE_LABEL,
)
} else {
wasAdded = true
labels.values.push({val: NO_PROMOTE_LABEL})
}
if (labels.values.length === 0) {
delete existing.labels
} else {
existing.labels = labels
}
return existing
},
checkCommitted: response => {
const exists = !!response.data.labels?.some(
label => label.val === NO_PROMOTE_LABEL,
)
return exists === wasAdded
},
})
}, [updateProfile, profile])
return (
<View style={[a.flex_1, a.gap_sm]}>
<Toggle.Item
name="algorithmic_visibility"
disabled={!canToggle}
value={isOptedOut}
onChange={onToggleOptOut}
label={_(
msg`Ask apps to hide my posts from algorithmic recommendations`,
)}
style={[a.w_full]}>
<Toggle.LabelText style={[a.flex_1]}>
<Trans>
Ask apps to hide my posts from algorithmic recommendations
</Trans>
</Toggle.LabelText>
<Toggle.Platform />
</Toggle.Item>
<Text style={[a.leading_snug, t.atoms.text_contrast_high]}>
<Trans>
Bluesky will not show your posts in algorithmic recommendations and
will ask other apps to do the same. Your posts may still appear in the
Discover feed, but only to your followers.
</Trans>
</Text>
</View>
)
}
@@ -85,12 +85,12 @@ export function PwiOptOut() {
value={isOptedOut}
onChange={onToggleOptOut}
label={_(
msg`Discourage apps from showing my account to logged-out users`,
msg`Ask apps and sites not to show my account to logged-out users`,
)}
style={[a.w_full]}>
<Toggle.LabelText style={[a.flex_1]}>
<Trans>
Discourage apps from showing my account to logged-out users
Ask apps and sites not to show my account to logged-out users
</Trans>
</Toggle.LabelText>
<Toggle.Platform />
@@ -98,9 +98,9 @@ export function PwiOptOut() {
<Text style={[a.leading_snug, t.atoms.text_contrast_high]}>
<Trans>
Bluesky will not show your profile and posts to logged-out users.
Other apps may not honor this request. This does not make your account
private.
Bluesky will not show your account to logged-out users and will ask
other apps to do the same. Other apps may not honor this request. It
doesn't make your account private.
</Trans>
</Text>
</View>