Mod screen design
This commit is contained in:
@@ -8,7 +8,9 @@ import * as Toggle from '#/components/forms/Toggle'
|
|||||||
|
|
||||||
export type ItemProps = Omit<Toggle.ItemProps, 'style' | 'role' | 'children'> &
|
export type ItemProps = Omit<Toggle.ItemProps, 'style' | 'role' | 'children'> &
|
||||||
AccessibilityProps &
|
AccessibilityProps &
|
||||||
React.PropsWithChildren<{testID?: string}>
|
React.PropsWithChildren<{
|
||||||
|
testID?: string
|
||||||
|
}>
|
||||||
|
|
||||||
export type GroupProps = Omit<Toggle.GroupProps, 'style' | 'type'> & {
|
export type GroupProps = Omit<Toggle.GroupProps, 'style' | 'type'> & {
|
||||||
multiple?: boolean
|
multiple?: boolean
|
||||||
|
|||||||
+257
-156
@@ -31,7 +31,8 @@ import {Divider} from '#/components/Divider'
|
|||||||
import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign'
|
import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign'
|
||||||
import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group'
|
import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group'
|
||||||
import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person'
|
import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person'
|
||||||
import {SquareBehindSquare4_Stroke2_Corner0_Rounded as SquareBehindSquare} from '#/components/icons/SquareBehindSquare4'
|
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
|
||||||
|
import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import * as Toggle from '#/components/forms/Toggle'
|
import * as Toggle from '#/components/forms/Toggle'
|
||||||
import * as ToggleButton from '#/components/forms/ToggleButton'
|
import * as ToggleButton from '#/components/forms/ToggleButton'
|
||||||
@@ -39,12 +40,13 @@ import {InlineLink, Link} from '#/components/Link'
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {useLabelGroupStrings} from '#/lib/moderation/useLabelGroupStrings'
|
import {useLabelGroupStrings} from '#/lib/moderation/useLabelGroupStrings'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {Button, ButtonText, ButtonIcon} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
import {
|
import {
|
||||||
getModerationServiceTitle,
|
getModerationServiceTitle,
|
||||||
useConfigurableLabelGroups,
|
useConfigurableLabelGroups,
|
||||||
getLabelGroupToLabelerMap,
|
getLabelGroupToLabelerMap,
|
||||||
} from '#/lib/moderation'
|
} from '#/lib/moderation'
|
||||||
|
import * as ModerationServiceCard from '#/components/ModerationServiceCard'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SettingsDialog,
|
SettingsDialog,
|
||||||
@@ -109,7 +111,6 @@ export function ModerationScreen(
|
|||||||
<CenteredView
|
<CenteredView
|
||||||
testID="moderationScreen"
|
testID="moderationScreen"
|
||||||
style={[
|
style={[
|
||||||
a.border,
|
|
||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
{minHeight: height},
|
{minHeight: height},
|
||||||
@@ -148,7 +149,7 @@ export function ModerationScreenInner({
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
const {gtTablet} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
const modSettingsDialogControl = Dialog.useDialogControl()
|
const modSettingsDialogControl = Dialog.useDialogControl()
|
||||||
const [settingsDialogProps, setSettingsDialogProps] =
|
const [settingsDialogProps, setSettingsDialogProps] =
|
||||||
React.useState<SettingsDialogProps>({
|
React.useState<SettingsDialogProps>({
|
||||||
@@ -186,77 +187,145 @@ export function ModerationScreenInner({
|
|||||||
<SettingsDialog {...settingsDialogProps} preferences={preferences} />
|
<SettingsDialog {...settingsDialogProps} preferences={preferences} />
|
||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
|
|
||||||
<ScrollView contentContainerStyle={[a.border_0]}>
|
<ScrollView
|
||||||
{!gtTablet && <Divider />}
|
contentContainerStyle={[
|
||||||
|
a.border_0,
|
||||||
|
a.pt_2xl,
|
||||||
|
a.px_lg,
|
||||||
|
gtMobile && a.px_2xl,
|
||||||
|
]}>
|
||||||
|
<Text
|
||||||
|
style={[a.text_md, a.font_bold, a.pb_md, t.atoms.text_contrast_high]}>
|
||||||
|
<Trans>Moderation tools</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
<Link
|
<View
|
||||||
testID="moderationlistsBtn"
|
style={[
|
||||||
style={[a.flex_row, a.align_center, a.py_md, a.px_lg, a.gap_md]}
|
a.w_full,
|
||||||
to="/moderation/modlists">
|
a.rounded_md,
|
||||||
<View
|
a.overflow_hidden,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
]}>
|
||||||
|
<Link
|
||||||
|
testID="moderationlistsBtn"
|
||||||
style={[
|
style={[
|
||||||
|
a.flex_row,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_center,
|
a.justify_between,
|
||||||
a.p_md,
|
a.p_lg,
|
||||||
a.rounded_full,
|
a.gap_sm,
|
||||||
t.atoms.bg_contrast_50,
|
]}
|
||||||
]}>
|
to="/moderation/modlists">
|
||||||
<Group size="md" style={[t.atoms.text_contrast_medium]} />
|
<View style={[a.flex_row, a.align_center, a.gap_md]}>
|
||||||
</View>
|
<Group size="md" style={[t.atoms.text_contrast_medium]} />
|
||||||
<Text style={[a.text_md]}>
|
<Text style={[a.text_md]}>
|
||||||
<Trans>Moderation lists</Trans>
|
<Trans>Moderation lists</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</Link>
|
</View>
|
||||||
|
<ChevronRight
|
||||||
<Divider />
|
size="sm"
|
||||||
|
style={[t.atoms.text_contrast_low, a.self_end]}
|
||||||
<Link
|
/>
|
||||||
testID="mutedAccountsBtn"
|
</Link>
|
||||||
style={[a.flex_row, a.align_center, a.py_md, a.px_lg, a.gap_md]}
|
<Divider />
|
||||||
to="/moderation/muted-accounts">
|
<Link
|
||||||
<View
|
testID="mutedAccountsBtn"
|
||||||
style={[
|
style={[
|
||||||
|
a.flex_row,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_center,
|
a.justify_between,
|
||||||
a.p_md,
|
a.p_lg,
|
||||||
a.rounded_full,
|
a.gap_sm,
|
||||||
t.atoms.bg_contrast_50,
|
]}
|
||||||
]}>
|
to="/moderation/muted-accounts">
|
||||||
<Person size="md" style={[t.atoms.text_contrast_medium]} />
|
<View style={[a.flex_row, a.align_center, a.gap_md]}>
|
||||||
</View>
|
<Person size="md" style={[t.atoms.text_contrast_medium]} />
|
||||||
<Text style={[a.text_md]}>
|
<Text style={[a.text_md]}>
|
||||||
<Trans>Muted accounts</Trans>
|
<Trans>Muted accounts</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</Link>
|
</View>
|
||||||
|
<ChevronRight
|
||||||
<Divider />
|
size="sm"
|
||||||
|
style={[t.atoms.text_contrast_low, a.self_end]}
|
||||||
<Link
|
/>
|
||||||
testID="blockedAccountsBtn"
|
</Link>
|
||||||
style={[a.flex_row, a.align_center, a.py_md, a.px_lg, a.gap_md]}
|
<Divider />
|
||||||
to="/moderation/blocked-accounts">
|
<Link
|
||||||
<View
|
testID="blockedAccountsBtn"
|
||||||
style={[
|
style={[
|
||||||
|
a.flex_row,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_center,
|
a.justify_between,
|
||||||
a.p_md,
|
a.p_lg,
|
||||||
a.rounded_full,
|
a.gap_sm,
|
||||||
t.atoms.bg_contrast_50,
|
]}
|
||||||
]}>
|
to="/moderation/blocked-accounts">
|
||||||
<CircleBanSign size="md" style={[t.atoms.text_contrast_medium]} />
|
<View style={[a.flex_row, a.align_center, a.gap_md]}>
|
||||||
</View>
|
<CircleBanSign size="md" style={[t.atoms.text_contrast_medium]} />
|
||||||
<Text style={[a.text_md]}>
|
<Text style={[a.text_md]}>
|
||||||
<Trans>Blocked accounts</Trans>
|
<Trans>Blocked accounts</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</Link>
|
</View>
|
||||||
|
<ChevronRight
|
||||||
|
size="sm"
|
||||||
|
style={[t.atoms.text_contrast_low, a.self_end]}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
|
|
||||||
<Divider />
|
<Text
|
||||||
|
style={[
|
||||||
|
a.text_md,
|
||||||
|
a.font_bold,
|
||||||
|
a.pt_2xl,
|
||||||
|
a.pb_md,
|
||||||
|
t.atoms.text_contrast_high,
|
||||||
|
]}>
|
||||||
|
<Trans>Labeler subscriptions</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
<View style={[a.gap_sm, a.px_lg, a.py_lg]}>
|
<View style={[a.gap_sm]}>
|
||||||
<Text style={[a.text_lg, a.font_bold, a.pb_sm]}>
|
{modservices.map(mod => {
|
||||||
<Trans>Content filtering settings</Trans>
|
return (
|
||||||
</Text>
|
<ModerationServiceCard.Link
|
||||||
|
modservice={mod}
|
||||||
|
key={mod.creator.did}>
|
||||||
|
<ModerationServiceCard.Card.Outer>
|
||||||
|
<ModerationServiceCard.Card.Avatar
|
||||||
|
avatar={mod.creator.avatar}
|
||||||
|
/>
|
||||||
|
<ModerationServiceCard.Card.Content
|
||||||
|
title={getModerationServiceTitle({
|
||||||
|
displayName: mod.creator.displayName,
|
||||||
|
handle: mod.creator.handle,
|
||||||
|
})}
|
||||||
|
handle={mod.creator.handle}
|
||||||
|
description={mod.description}
|
||||||
|
/>
|
||||||
|
</ModerationServiceCard.Card.Outer>
|
||||||
|
</ModerationServiceCard.Link>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.text_md,
|
||||||
|
a.font_bold,
|
||||||
|
a.pt_2xl,
|
||||||
|
a.pb_md,
|
||||||
|
t.atoms.text_contrast_high,
|
||||||
|
]}>
|
||||||
|
<Trans>Content filtering</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.w_full,
|
||||||
|
a.rounded_md,
|
||||||
|
a.overflow_hidden,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
]}>
|
||||||
{groups.map((def, i) => {
|
{groups.map((def, i) => {
|
||||||
const labelers = labelGroupToLabelerMap[def.id] || []
|
const labelers = labelGroupToLabelerMap[def.id] || []
|
||||||
return (
|
return (
|
||||||
@@ -273,11 +342,17 @@ export function ModerationScreenInner({
|
|||||||
})}
|
})}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Divider />
|
<Text
|
||||||
|
style={[
|
||||||
<Text style={[a.text_lg, a.font_bold, a.pl_lg, a.pt_lg, a.pb_sm]}>
|
a.text_md,
|
||||||
|
a.font_bold,
|
||||||
|
a.pt_2xl,
|
||||||
|
a.pb_md,
|
||||||
|
t.atoms.text_contrast_high,
|
||||||
|
]}>
|
||||||
<Trans>Logged-out visibility</Trans>
|
<Trans>Logged-out visibility</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<PwiOptOut />
|
<PwiOptOut />
|
||||||
|
|
||||||
<View style={{height: 200}} />
|
<View style={{height: 200}} />
|
||||||
@@ -290,8 +365,8 @@ function LabelGroup({
|
|||||||
labelGroup,
|
labelGroup,
|
||||||
labelers: mods,
|
labelers: mods,
|
||||||
preferences,
|
preferences,
|
||||||
openModSettingsDialog,
|
}: // openModSettingsDialog,
|
||||||
}: {
|
{
|
||||||
labelGroup: LabelGroupDefinition['id']
|
labelGroup: LabelGroupDefinition['id']
|
||||||
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
|
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
|
||||||
preferences: UsePreferencesQueryResponse
|
preferences: UsePreferencesQueryResponse
|
||||||
@@ -299,9 +374,11 @@ function LabelGroup({
|
|||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const {gtMobile} = useBreakpoints()
|
||||||
const labelGroupStrings = useLabelGroupStrings()
|
const labelGroupStrings = useLabelGroupStrings()
|
||||||
const {mutateAsync: setContentLabelPref, variables: optimisticContentLabel} =
|
const {mutateAsync: setContentLabelPref, variables: optimisticContentLabel} =
|
||||||
useSetContentLabelMutation()
|
useSetContentLabelMutation()
|
||||||
|
const [settingsOpen, setSettingsOpen] = React.useState(false)
|
||||||
|
|
||||||
const onChangeVisibility = React.useCallback(
|
const onChangeVisibility = React.useCallback(
|
||||||
async (values: string[]) => {
|
async (values: string[]) => {
|
||||||
@@ -329,7 +406,7 @@ function LabelGroup({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[]}>
|
<View style={[a.px_md, a.pr_md, gtMobile && a.px_lg]}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.py_md,
|
a.py_md,
|
||||||
@@ -339,7 +416,7 @@ function LabelGroup({
|
|||||||
a.align_center,
|
a.align_center,
|
||||||
]}>
|
]}>
|
||||||
<View style={[a.gap_xs, {width: '50%'}]}>
|
<View style={[a.gap_xs, {width: '50%'}]}>
|
||||||
<Text style={[a.text_md, a.font_bold, t.atoms.text_contrast_medium]}>
|
<Text style={[a.font_bold, t.atoms.text_contrast_medium]}>
|
||||||
{name}
|
{name}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[a.leading_tight, {maxWidth: 400}]}>{description}</Text>
|
<Text style={[a.leading_tight, {maxWidth: 400}]}>{description}</Text>
|
||||||
@@ -366,91 +443,115 @@ function LabelGroup({
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{!!mods.length && (
|
{!!mods.length && (
|
||||||
<View
|
<View style={[a.mb_md, a.rounded_sm, t.atoms.bg]}>
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_start,
|
|
||||||
a.justify_between,
|
|
||||||
a.mb_md,
|
|
||||||
a.p_sm,
|
|
||||||
a.rounded_sm,
|
|
||||||
t.atoms.bg_contrast_25,
|
|
||||||
]}>
|
|
||||||
<View style={[a.flex_row, a.align_center, a.flex_1, a.gap_xs]}>
|
|
||||||
{mods.map(mod => {
|
|
||||||
const modservicePreferences =
|
|
||||||
preferences.moderationOpts.mods.find(
|
|
||||||
({did}) => did === mod.creator.did,
|
|
||||||
)
|
|
||||||
const labelGroupEnabled =
|
|
||||||
!modservicePreferences?.disabledLabelGroups?.includes(
|
|
||||||
labelGroup,
|
|
||||||
)
|
|
||||||
const isLabelerEnabled = modservicePreferences?.enabled
|
|
||||||
const enabled = labelGroupEnabled && isLabelerEnabled
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
key={mod.creator.did}
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.gap_sm,
|
|
||||||
a.py_sm,
|
|
||||||
a.px_md,
|
|
||||||
a.rounded_full,
|
|
||||||
a.border,
|
|
||||||
t.atoms.border_contrast_low,
|
|
||||||
enabled && t.atoms.border_contrast_high,
|
|
||||||
enabled && t.atoms.bg,
|
|
||||||
]}>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.rounded_full,
|
|
||||||
t.atoms.bg_contrast_300,
|
|
||||||
{
|
|
||||||
height: 6,
|
|
||||||
width: 6,
|
|
||||||
},
|
|
||||||
enabled && {
|
|
||||||
backgroundColor: t.palette.positive_500,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_xs,
|
|
||||||
a.font_bold,
|
|
||||||
native({
|
|
||||||
top: 1,
|
|
||||||
}),
|
|
||||||
t.atoms.text_contrast_medium,
|
|
||||||
enabled && t.atoms.text_contrast_high,
|
|
||||||
]}>
|
|
||||||
{getModerationServiceTitle({
|
|
||||||
displayName: mod.creator.displayName,
|
|
||||||
handle: mod.creator.handle,
|
|
||||||
})}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
size="tiny"
|
label="Expand to configure labelers"
|
||||||
variant="ghost"
|
onPress={() => setSettingsOpen(!settingsOpen)}>
|
||||||
color="secondary"
|
<View
|
||||||
label={_(msg`Configure enabled labelers for this content type`)}
|
style={[
|
||||||
style={[a.mt_xs]}
|
a.w_full,
|
||||||
onPress={() => {
|
a.flex_row,
|
||||||
openModSettingsDialog({
|
a.align_center,
|
||||||
labelGroup,
|
a.justify_between,
|
||||||
modservices: mods,
|
a.p_md,
|
||||||
})
|
]}>
|
||||||
}}>
|
<View style={[a.flex_row, a.align_center, a.flex_1, a.gap_xs]}>
|
||||||
<ButtonText>Configure</ButtonText>
|
{mods.map(mod => {
|
||||||
<ButtonIcon icon={SquareBehindSquare} position="right" />
|
const modservicePreferences =
|
||||||
|
preferences.moderationOpts.mods.find(
|
||||||
|
({did}) => did === mod.creator.did,
|
||||||
|
)
|
||||||
|
const labelGroupEnabled =
|
||||||
|
!modservicePreferences?.disabledLabelGroups?.includes(
|
||||||
|
labelGroup,
|
||||||
|
)
|
||||||
|
const isLabelerEnabled = modservicePreferences?.enabled
|
||||||
|
const enabled = labelGroupEnabled && isLabelerEnabled
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
key={mod.creator.did}
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.gap_xs,
|
||||||
|
a.py_xs,
|
||||||
|
a.px_sm,
|
||||||
|
a.rounded_xs,
|
||||||
|
t.atoms.bg_contrast_600,
|
||||||
|
enabled && t.atoms.bg_contrast_800,
|
||||||
|
]}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.rounded_full,
|
||||||
|
t.atoms.bg_contrast_300,
|
||||||
|
{
|
||||||
|
height: 6,
|
||||||
|
width: 6,
|
||||||
|
},
|
||||||
|
enabled && {
|
||||||
|
backgroundColor: t.palette.positive_500,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.text_xs,
|
||||||
|
a.font_bold,
|
||||||
|
native({
|
||||||
|
top: 1,
|
||||||
|
}),
|
||||||
|
t.atoms.text_inverted,
|
||||||
|
]}>
|
||||||
|
{getModerationServiceTitle({
|
||||||
|
displayName: mod.creator.displayName,
|
||||||
|
handle: mod.creator.handle,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ChevronDown size="sm" />
|
||||||
|
</View>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{settingsOpen && (
|
||||||
|
<View style={[a.px_md]}>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
{mods.map((mod, i) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{i !== 0 && <Divider />}
|
||||||
|
|
||||||
|
<Toggle.Item
|
||||||
|
label={'Toggle label'}
|
||||||
|
name={mod.creator.did}
|
||||||
|
value
|
||||||
|
onChange={() => {}}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.w_full,
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.justify_between,
|
||||||
|
a.py_md,
|
||||||
|
]}>
|
||||||
|
<Text style={[a.font_bold]}>
|
||||||
|
{getModerationServiceTitle({
|
||||||
|
displayName: mod.creator.displayName,
|
||||||
|
handle: mod.creator.handle,
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
<Toggle.Switch />
|
||||||
|
</View>
|
||||||
|
</Toggle.Item>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
@@ -514,7 +615,7 @@ function PwiOptOut() {
|
|||||||
}, [updateProfile, profile])
|
}, [updateProfile, profile])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.pt_sm, a.px_lg]}>
|
<View style={[a.pt_sm]}>
|
||||||
<View style={[a.flex_row, a.align_center, a.justify_between, a.gap_lg]}>
|
<View style={[a.flex_row, a.align_center, a.justify_between, a.gap_lg]}>
|
||||||
<Toggle.Item
|
<Toggle.Item
|
||||||
disabled={!canToggle}
|
disabled={!canToggle}
|
||||||
|
|||||||
Reference in New Issue
Block a user