diff --git a/src/screens/Settings/PrivacyAndSecuritySettings.tsx b/src/screens/Settings/PrivacyAndSecuritySettings.tsx index 2979ace213..4ba11fdec9 100644 --- a/src/screens/Settings/PrivacyAndSecuritySettings.tsx +++ b/src/screens/Settings/PrivacyAndSecuritySettings.tsx @@ -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) { /> - + + + + + - - Logged-out visibility - - + @@ -115,11 +118,10 @@ export function PrivacyAndSecuritySettingsScreen({}: Props) { - 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. diff --git a/src/screens/Settings/components/AlgoVisibilityOptOut.tsx b/src/screens/Settings/components/AlgoVisibilityOptOut.tsx new file mode 100644 index 0000000000..e60f6da636 --- /dev/null +++ b/src/screens/Settings/components/AlgoVisibilityOptOut.tsx @@ -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 = 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 ( + + + + + Ask apps to hide my posts from algorithmic recommendations + + + + + + + + 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. + + + + ) +} diff --git a/src/screens/Settings/components/PwiOptOut.tsx b/src/screens/Settings/components/PwiOptOut.tsx index 193f26994e..9c32e48595 100644 --- a/src/screens/Settings/components/PwiOptOut.tsx +++ b/src/screens/Settings/components/PwiOptOut.tsx @@ -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]}> - Discourage apps from showing my account to logged-out users + Ask apps and sites not to show my account to logged-out users @@ -98,9 +98,9 @@ export function PwiOptOut() { - 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.