diff options
Diffstat (limited to 'src/view/screens/Moderation.tsx')
-rw-r--r-- | src/view/screens/Moderation.tsx | 136 |
1 files changed, 134 insertions, 2 deletions
diff --git a/src/view/screens/Moderation.tsx b/src/view/screens/Moderation.tsx index 4d8d8cad7..fe1e5a28c 100644 --- a/src/view/screens/Moderation.tsx +++ b/src/view/screens/Moderation.tsx @@ -1,15 +1,21 @@ import React from 'react' -import {StyleSheet, TouchableOpacity, View} from 'react-native' +import { + ActivityIndicator, + StyleSheet, + TouchableOpacity, + View, +} from 'react-native' import {useFocusEffect} from '@react-navigation/native' import { FontAwesomeIcon, FontAwesomeIconStyle, } from '@fortawesome/react-native-fontawesome' +import {ComAtprotoLabelDefs} from '@atproto/api' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {s} from 'lib/styles' import {CenteredView} from '../com/util/Views' import {ViewHeader} from '../com/util/ViewHeader' -import {Link} from '../com/util/Link' +import {Link, TextLink} from '../com/util/Link' import {Text} from '../com/util/text/Text' import {usePalette} from 'lib/hooks/usePalette' import {useAnalytics} from 'lib/analytics/analytics' @@ -18,6 +24,12 @@ import {useSetMinimalShellMode} from '#/state/shell' import {useModalControls} from '#/state/modals' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {ToggleButton} from '../com/util/forms/ToggleButton' +import {useSession} from '#/state/session' +import { + useProfileQuery, + useProfileUpdateMutation, +} from '#/state/queries/profile' type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'> export function ModerationScreen({}: Props) { @@ -109,10 +121,124 @@ export function ModerationScreen({}: Props) { <Trans>Blocked accounts</Trans> </Text> </Link> + <Text + type="xl-bold" + style={[ + pal.text, + { + paddingHorizontal: 18, + paddingTop: 18, + paddingBottom: 6, + }, + ]}> + <Trans>Logged-out users</Trans> + </Text> + <PwiOptOut /> </CenteredView> ) } +function PwiOptOut() { + const pal = usePalette('default') + const {_} = useLingui() + const {currentAccount} = useSession() + const {data: profile} = useProfileQuery({did: currentAccount?.did}) + const updateProfile = useProfileUpdateMutation() + + const isOptedOut = + profile?.labels?.some(l => l.val === '!no-unauthenticated') || false + const canToggle = profile && !updateProfile.isPending + + const onToggleOptOut = React.useCallback(() => { + if (!profile) { + return + } + let wasAdded = false + updateProfile.mutate({ + profile, + updates: existing => { + // create labels attr if needed + existing.labels = ComAtprotoLabelDefs.isSelfLabels(existing.labels) + ? existing.labels + : { + $type: 'com.atproto.label.defs#selfLabels', + values: [], + } + + // toggle the label + const hasLabel = existing.labels.values.some( + l => l.val === '!no-unauthenticated', + ) + if (hasLabel) { + wasAdded = false + existing.labels.values = existing.labels.values.filter( + l => l.val !== '!no-unauthenticated', + ) + } else { + wasAdded = true + existing.labels.values.push({val: '!no-unauthenticated'}) + } + + // delete if no longer needed + if (existing.labels.values.length === 0) { + delete existing.labels + } + return existing + }, + checkCommitted: res => { + const exists = !!res.data.labels?.some( + l => l.val === '!no-unauthenticated', + ) + return exists === wasAdded + }, + }) + }, [updateProfile, profile]) + + return ( + <View style={[pal.view, styles.toggleCard]}> + <View + style={{flexDirection: 'row', alignItems: 'center', paddingRight: 14}}> + <ToggleButton + type="default-light" + label={_(msg`Limit the visibility of my account`)} + labelType="lg" + isSelected={isOptedOut} + onPress={canToggle ? onToggleOptOut : undefined} + style={[canToggle ? undefined : {opacity: 0.5}, {flex: 1}]} + /> + {updateProfile.isPending && <ActivityIndicator />} + </View> + <View + style={{ + flexDirection: 'column', + gap: 10, + paddingLeft: 66, + paddingRight: 12, + paddingBottom: 10, + }}> + <Text style={pal.textLight}> + <Trans> + Your profile and content will not be visible to anyone visiting the + Bluesky app without an account. Enabling this will not make your + profile private. + </Trans> + </Text> + <Text style={[pal.textLight, {fontWeight: '500'}]}> + <Trans> + Note: Third-party apps that display Bluesky content may not respect + this setting. + </Trans> + </Text> + <TextLink + style={pal.link} + href="https://blueskyweb.zendesk.com/hc/en-us/articles/15835264007693-Data-Privacy" + text={_(msg`Learn more about what is public on Bluesky.`)} + /> + </View> + </View> + ) +} + const styles = StyleSheet.create({ desktopContainer: { borderLeftWidth: 1, @@ -128,6 +254,12 @@ const styles = StyleSheet.create({ paddingHorizontal: 18, marginBottom: 1, }, + toggleCard: { + paddingVertical: 8, + paddingTop: 2, + paddingHorizontal: 6, + marginBottom: 1, + }, iconContainer: { alignItems: 'center', justifyContent: 'center', |