minor styling fixes
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import {View} from 'react-native'
|
import {Modal, Pressable, View} from 'react-native'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {Robot_Filled_Corner2_Rounded as RobotIcon} from '#/components/icons/Robot'
|
import {Robot_Filled_Corner2_Rounded as RobotIcon} from '#/components/icons/Robot'
|
||||||
@@ -12,58 +12,132 @@ import {navigate} from '#/Navigation'
|
|||||||
|
|
||||||
export function BotAccountInfoDialog({
|
export function BotAccountInfoDialog({
|
||||||
control,
|
control,
|
||||||
isMe,
|
|
||||||
}: {
|
}: {
|
||||||
control: Dialog.DialogControlProps
|
control: Dialog.DialogControlProps
|
||||||
isMe?: boolean
|
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Dialog.Outer control={control}>
|
<Dialog.Outer control={control}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<BotAccountInfoDialogInner control={control} isMe={isMe} />
|
<BotAccountInfoDialogInner control={control} />
|
||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function BotAccountInfoDialogInner({
|
export function BotAccountOwnAlert({
|
||||||
control,
|
visible,
|
||||||
isMe,
|
onClose,
|
||||||
}: {
|
}: {
|
||||||
control: Dialog.DialogControlProps
|
visible: boolean
|
||||||
isMe?: boolean
|
onClose: (cb?: () => void) => void
|
||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.ScrollableInner label={_(msg`Automated account`)}>
|
<Modal
|
||||||
<View style={[a.align_center, a.gap_2xl, a.py_md]}>
|
visible={visible}
|
||||||
<View style={[t.atoms.shadow_sm]}>
|
transparent
|
||||||
<RobotIcon width={48} fill={t.atoms.text_contrast_medium.color} />
|
animationType="fade"
|
||||||
</View>
|
onRequestClose={() => onClose()}
|
||||||
<Text style={[a.text_lg, a.text_center, a.font_semi_bold]}>
|
accessibilityLabel={_(msg`Automated account`)}
|
||||||
{isMe ? (
|
accessibilityViewIsModal>
|
||||||
|
<Pressable
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel={_(msg`Close`)}
|
||||||
|
onPress={() => onClose()}
|
||||||
|
style={[
|
||||||
|
a.flex_1,
|
||||||
|
a.justify_center,
|
||||||
|
a.align_center,
|
||||||
|
a.px_xl,
|
||||||
|
{backgroundColor: 'rgba(0,0,0,0.5)'},
|
||||||
|
]}>
|
||||||
|
<Pressable
|
||||||
|
accessibilityRole="button"
|
||||||
|
onPress={e => e.stopPropagation()}
|
||||||
|
style={[
|
||||||
|
t.atoms.bg,
|
||||||
|
a.w_full,
|
||||||
|
{borderRadius: 48},
|
||||||
|
a.p_2xl,
|
||||||
|
{maxWidth: 280},
|
||||||
|
]}>
|
||||||
|
<View style={[a.align_center, a.gap_md]}>
|
||||||
|
<View style={[t.atoms.shadow_sm]}>
|
||||||
|
<RobotIcon width={48} fill={t.atoms.text_contrast_medium.color} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={[a.text_md, a.text_center, a.py_sm]}>
|
||||||
|
<Trans>
|
||||||
|
You have marked this account as automated. You can remove it at
|
||||||
|
any time from your account settings.
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={_(msg`Okay`)}
|
||||||
|
onPress={() => onClose()}
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
style={[a.w_full]}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Okay</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
label={_(msg`Open settings`)}
|
||||||
|
onPress={() => {
|
||||||
|
onClose(() => {
|
||||||
|
navigate('AutomationLabelSettings')
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
color="secondary"
|
||||||
|
size="large"
|
||||||
|
style={[a.w_full]}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Open settings</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
</Pressable>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BotAccountOwnAlertWeb({
|
||||||
|
control,
|
||||||
|
}: {
|
||||||
|
control: Dialog.DialogControlProps
|
||||||
|
}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog.Outer control={control} webOptions={{alignCenter: true}}>
|
||||||
|
<Dialog.ScrollableInner
|
||||||
|
label={_(msg`Automated account`)}
|
||||||
|
style={web([{maxWidth: 320, borderRadius: 36}])}>
|
||||||
|
<View style={[a.align_center, a.gap_2xl, a.py_md]}>
|
||||||
|
<View style={[t.atoms.shadow_sm]}>
|
||||||
|
<RobotIcon width={48} fill={t.atoms.text_contrast_medium.color} />
|
||||||
|
</View>
|
||||||
|
<Text style={[a.text_md, a.text_center]}>
|
||||||
<Trans>
|
<Trans>
|
||||||
You have marked this account as automated. You can remove it at
|
You have marked this account as automated. You can remove it at
|
||||||
any time from your account settings.
|
any time from your account settings.
|
||||||
</Trans>
|
</Trans>
|
||||||
) : (
|
</Text>
|
||||||
<Trans>
|
<Button
|
||||||
This account has been marked as automated by its owner
|
label={_(msg`Okay`)}
|
||||||
</Trans>
|
onPress={() => control.close()}
|
||||||
)}
|
color="primary"
|
||||||
</Text>
|
size="large"
|
||||||
<Button
|
style={[a.w_full]}>
|
||||||
label={_(msg`Okay`)}
|
<ButtonText>
|
||||||
onPress={() => control.close()}
|
<Trans>Okay</Trans>
|
||||||
color="primary"
|
</ButtonText>
|
||||||
size="large"
|
</Button>
|
||||||
style={[a.w_full]}>
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>Okay</Trans>
|
|
||||||
</ButtonText>
|
|
||||||
</Button>
|
|
||||||
{isMe && (
|
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Open settings`)}
|
label={_(msg`Open settings`)}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
@@ -79,7 +153,40 @@ function BotAccountInfoDialogInner({
|
|||||||
<Trans>Open settings</Trans>
|
<Trans>Open settings</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
</View>
|
||||||
|
<Dialog.Close />
|
||||||
|
</Dialog.ScrollableInner>
|
||||||
|
</Dialog.Outer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function BotAccountInfoDialogInner({
|
||||||
|
control,
|
||||||
|
}: {
|
||||||
|
control: Dialog.DialogControlProps
|
||||||
|
}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog.ScrollableInner label={_(msg`Automated account`)}>
|
||||||
|
<View style={[a.align_center, a.gap_2xl, a.py_md]}>
|
||||||
|
<View style={[t.atoms.shadow_sm]}>
|
||||||
|
<RobotIcon width={48} fill={t.atoms.text_contrast_medium.color} />
|
||||||
|
</View>
|
||||||
|
<Text style={[a.text_lg, a.text_center, a.font_semi_bold]}>
|
||||||
|
<Trans>This account has been marked as automated by its owner</Trans>
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
label={_(msg`Okay`)}
|
||||||
|
onPress={() => control.close()}
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
style={[a.w_full]}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Okay</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
</Dialog.ScrollableInner>
|
</Dialog.ScrollableInner>
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
|
import {useState} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {type ComAtprotoLabelDefs} from '@atproto/api'
|
import {type ComAtprotoLabelDefs} from '@atproto/api'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {isBotAccount} from '#/lib/bots'
|
import {isBotAccount} from '#/lib/bots'
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {BotAccountInfoDialog} from '#/components/BotAccountInfoDialog'
|
import {
|
||||||
|
BotAccountInfoDialog,
|
||||||
|
BotAccountOwnAlert,
|
||||||
|
BotAccountOwnAlertWeb,
|
||||||
|
} from '#/components/BotAccountInfoDialog'
|
||||||
import {Button} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
import {useDialogControl} from '#/components/Dialog'
|
import {useDialogControl} from '#/components/Dialog'
|
||||||
import {Robot_Filled_Corner2_Rounded as RobotIcon} from '#/components/icons/Robot'
|
import {Robot_Filled_Corner2_Rounded as RobotIcon} from '#/components/icons/Robot'
|
||||||
import {useAnalytics} from '#/analytics'
|
|
||||||
|
|
||||||
export function BotBadge({
|
export function BotBadge({
|
||||||
profile,
|
profile,
|
||||||
@@ -47,6 +53,7 @@ export function BotBadgeButton({
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {gtPhone} = useBreakpoints()
|
const {gtPhone} = useBreakpoints()
|
||||||
const control = useDialogControl()
|
const control = useDialogControl()
|
||||||
|
const [alertVisible, setAlertVisible] = useState(false)
|
||||||
|
|
||||||
if (!isBotAccount(profile)) {
|
if (!isBotAccount(profile)) {
|
||||||
return null
|
return null
|
||||||
@@ -59,6 +66,8 @@ export function BotBadgeButton({
|
|||||||
dimensions = 14
|
dimensions = 14
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useNativeAlert = isMe && IS_NATIVE
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
@@ -67,7 +76,11 @@ export function BotBadgeButton({
|
|||||||
onPress={evt => {
|
onPress={evt => {
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
ax.metric('bot:badge:click', {})
|
ax.metric('bot:badge:click', {})
|
||||||
control.open()
|
if (useNativeAlert) {
|
||||||
|
setAlertVisible(true)
|
||||||
|
} else {
|
||||||
|
control.open()
|
||||||
|
}
|
||||||
}}>
|
}}>
|
||||||
{({hovered}) => (
|
{({hovered}) => (
|
||||||
<View
|
<View
|
||||||
@@ -88,7 +101,19 @@ export function BotBadgeButton({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
<BotAccountInfoDialog control={control} isMe={isMe} />
|
{useNativeAlert ? (
|
||||||
|
<BotAccountOwnAlert
|
||||||
|
visible={alertVisible}
|
||||||
|
onClose={cb => {
|
||||||
|
setAlertVisible(false)
|
||||||
|
cb?.()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : isMe ? (
|
||||||
|
<BotAccountOwnAlertWeb control={control} />
|
||||||
|
) : (
|
||||||
|
<BotAccountInfoDialog control={control} />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,7 +273,14 @@ function InlineNameAndHandle({
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<BotBadge profile={profile} />
|
<View
|
||||||
|
style={[
|
||||||
|
a.pl_2xs,
|
||||||
|
a.self_center,
|
||||||
|
{marginTop: platform({default: 0, android: -1})},
|
||||||
|
]}>
|
||||||
|
<BotBadge profile={profile} />
|
||||||
|
</View>
|
||||||
<Text
|
<Text
|
||||||
emoji
|
emoji
|
||||||
style={[
|
style={[
|
||||||
@@ -328,7 +335,9 @@ export function Name({
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<BotBadge profile={profile} />
|
<View style={[a.pl_xs]}>
|
||||||
|
<BotBadge profile={profile} />
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {type $Typed, ComAtprotoLabelDefs} from '@atproto/api'
|
import {type $Typed, ComAtprotoLabelDefs} from '@atproto/api'
|
||||||
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
@@ -8,6 +9,8 @@ import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
|||||||
|
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
import {type CommonNavigatorParams} from '#/lib/routes/types'
|
import {type CommonNavigatorParams} from '#/lib/routes/types'
|
||||||
|
import {RQKEY_ROOT as POST_FEED_RQKEY_ROOT} from '#/state/queries/post-feed'
|
||||||
|
import {postThreadQueryKeyRoot} from '#/state/queries/usePostThread/types'
|
||||||
import {
|
import {
|
||||||
useProfileQuery,
|
useProfileQuery,
|
||||||
useProfileUpdateMutation,
|
useProfileUpdateMutation,
|
||||||
@@ -32,6 +35,7 @@ export function AutomationLabelSettingsScreen({}: Props) {
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const {data: profile} = useProfileQuery({did: currentAccount?.did})
|
const {data: profile} = useProfileQuery({did: currentAccount?.did})
|
||||||
const updateProfile = useProfileUpdateMutation()
|
const updateProfile = useProfileUpdateMutation()
|
||||||
@@ -48,41 +52,50 @@ export function AutomationLabelSettingsScreen({}: Props) {
|
|||||||
}
|
}
|
||||||
let wasAdded = false
|
let wasAdded = false
|
||||||
ax.metric('bot:label:toggle', {state: isBotLabeled ? 'remove' : 'add'})
|
ax.metric('bot:label:toggle', {state: isBotLabeled ? 'remove' : 'add'})
|
||||||
updateProfile.mutate({
|
updateProfile.mutate(
|
||||||
profile,
|
{
|
||||||
updates: existing => {
|
profile,
|
||||||
const labels: $Typed<ComAtprotoLabelDefs.SelfLabels> = bsky.validate(
|
updates: existing => {
|
||||||
existing.labels,
|
const labels: $Typed<ComAtprotoLabelDefs.SelfLabels> =
|
||||||
ComAtprotoLabelDefs.validateSelfLabels,
|
bsky.validate(
|
||||||
)
|
existing.labels,
|
||||||
? existing.labels
|
ComAtprotoLabelDefs.validateSelfLabels,
|
||||||
: {
|
)
|
||||||
$type: 'com.atproto.label.defs#selfLabels',
|
? existing.labels
|
||||||
values: [],
|
: {
|
||||||
}
|
$type: 'com.atproto.label.defs#selfLabels',
|
||||||
|
values: [],
|
||||||
|
}
|
||||||
|
|
||||||
const hasLabel = labels.values.some(l => l.val === 'bot')
|
const hasLabel = labels.values.some(l => l.val === 'bot')
|
||||||
if (hasLabel) {
|
if (hasLabel) {
|
||||||
wasAdded = false
|
wasAdded = false
|
||||||
labels.values = labels.values.filter(l => l.val !== 'bot')
|
labels.values = labels.values.filter(l => l.val !== 'bot')
|
||||||
} else {
|
} else {
|
||||||
wasAdded = true
|
wasAdded = true
|
||||||
labels.values.push({val: 'bot'})
|
labels.values.push({val: 'bot'})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (labels.values.length === 0) {
|
if (labels.values.length === 0) {
|
||||||
delete existing.labels
|
delete existing.labels
|
||||||
} else {
|
} else {
|
||||||
existing.labels = labels
|
existing.labels = labels
|
||||||
}
|
}
|
||||||
|
|
||||||
return existing
|
return existing
|
||||||
|
},
|
||||||
|
checkCommitted: res => {
|
||||||
|
const exists = !!res.data.labels?.some(l => l.val === 'bot')
|
||||||
|
return exists === wasAdded
|
||||||
|
},
|
||||||
},
|
},
|
||||||
checkCommitted: res => {
|
{
|
||||||
const exists = !!res.data.labels?.some(l => l.val === 'bot')
|
onSuccess() {
|
||||||
return exists === wasAdded
|
queryClient.invalidateQueries({queryKey: [POST_FEED_RQKEY_ROOT]})
|
||||||
|
queryClient.invalidateQueries({queryKey: [postThreadQueryKeyRoot]})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
}, [updateProfile, profile])
|
}, [updateProfile, profile])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user