Add PWI opt-out toggle (#2122)
* Add PWI opt-out toggle * Bump @atproto/api@0.7.0 * Tweak copy * Bump lockfile * Fix layout on ios * Tweak copy more * Fix types * Tweak copy some more
This commit is contained in:
parent
261a935747
commit
17c27581b6
10 changed files with 821 additions and 460 deletions
|
@ -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',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue