Update ModerationDetailsDialog

This commit is contained in:
Eric Bailey
2024-02-26 17:41:51 -06:00
parent dbd42ae0c5
commit 67fea6d317
8 changed files with 219 additions and 147 deletions
@@ -7,29 +7,39 @@ import {ModerationCause} from '@atproto/api'
import {atoms as a, useBreakpoints} from '#/alf'
import {Text} from '#/components/Typography'
import * as Dialog from '#/components/Dialog'
import {GlobalDialogProps} from '#/components/dialogs'
import {Button} from '#/components/Button'
import {InlineLink} from '#/components/Link'
import {useLabelStrings} from '#/lib/moderation/useLabelStrings'
import {listUriToHref} from '#/lib/strings/url-helpers'
export {useDialogControl as useModerationDetailsDialogControl} from '#/components/Dialog'
export interface ModerationDetailsDialogProps {
control: Dialog.DialogOuterProps['control']
context: 'account' | 'content'
modcause: ModerationCause
}
export function ModerationDetailsDialog({
params,
cleanup,
}: GlobalDialogProps<ModerationDetailsDialogProps>) {
export function ModerationDetailsDialog(props: ModerationDetailsDialogProps) {
return (
<Dialog.Outer control={props.control}>
<Dialog.Handle />
<ModerationDetailsDialogInner {...props} />
</Dialog.Outer>
)
}
function ModerationDetailsDialogInner({
context,
modcause,
}: ModerationDetailsDialogProps & {
control: Dialog.DialogOuterProps['control']
}) {
const {_} = useLingui()
const labelStrings = useLabelStrings()
const control = Dialog.useDialogControl()
const {gtMobile} = useBreakpoints()
const {context, modcause} = params
// REQUIRED CLEANUP
const onClose = React.useCallback(() => cleanup(), [cleanup])
let name
let description
@@ -99,30 +109,26 @@ export function ModerationDetailsDialog({
}
return (
<Dialog.Outer defaultOpen control={control} onClose={onClose}>
<Dialog.Handle />
<Dialog.ScrollableInner
accessibilityDescribedBy="dialog-description"
accessibilityLabelledBy="dialog-title">
<Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}>
{name}
</Text>
<Text nativeID="dialog-description" style={[a.text_sm]}>
{description}
</Text>
<View style={gtMobile && [a.flex_row, a.justify_end]}>
<Button
testID="doneBtn"
variant="outline"
color="primary"
size="small"
onPress={() => control.close()}
label={_(msg`Done`)}>
{_(msg`Done`)}
</Button>
</View>
</Dialog.ScrollableInner>
</Dialog.Outer>
<Dialog.ScrollableInner
accessibilityDescribedBy="dialog-description"
accessibilityLabelledBy="dialog-title">
<Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}>
{name}
</Text>
<Text nativeID="dialog-description" style={[a.text_sm]}>
{description}
</Text>
<View style={gtMobile && [a.flex_row, a.justify_end]}>
<Button
testID="doneBtn"
variant="outline"
color="primary"
size="small"
onPress={() => control.close()}
label={_(msg`Done`)}>
{_(msg`Done`)}
</Button>
</View>
</Dialog.ScrollableInner>
)
}
+29
View File
@@ -0,0 +1,29 @@
import React from 'react'
import * as Dialog from '#/components/Dialog'
type Control = Dialog.DialogOuterProps['control']
type ControlsContext = {
mutedWordsDialogControl: Control
}
const ControlsContext = React.createContext({
mutedWordsDialogControl: {} as Control,
})
export function useGlobalDialogsControlContext() {
return React.useContext(ControlsContext)
}
export function Provider({children}: React.PropsWithChildren<{}>) {
const mutedWordsDialogControl = Dialog.useDialogControl()
const ctx = React.useMemo<ControlsContext>(
() => ({mutedWordsDialogControl}),
[mutedWordsDialogControl],
)
return (
<ControlsContext.Provider value={ctx}>{children}</ControlsContext.Provider>
)
}
+5 -2
View File
@@ -1,6 +1,7 @@
import React from 'react'
import {DialogControlProps} from '#/components/Dialog'
import {Provider as GlobalDialogsProvider} from '#/components/dialogs'
import {Provider as GlobalDialogsProviderV2} from '#/components/dialogs/Context'
const DialogContext = React.createContext<{
activeDialogs: React.MutableRefObject<
@@ -28,7 +29,7 @@ export function useDialogStateControlContext() {
export function Provider({children}: React.PropsWithChildren<{}>) {
const activeDialogs = React.useRef<
Map<string, React.MutableRefObject<DialogControlProps<{}>>>
Map<string, React.MutableRefObject<DialogControlProps>>
>(new Map())
const closeAllDialogs = React.useCallback(() => {
activeDialogs.current.forEach(dialog => dialog.current.close())
@@ -38,7 +39,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
return (
<DialogContext.Provider value={context}>
<DialogControlContext.Provider value={controls}>
<GlobalDialogsProvider>{children}</GlobalDialogsProvider>
<GlobalDialogsProvider>
<GlobalDialogsProviderV2>{children}</GlobalDialogsProviderV2>
</GlobalDialogsProvider>
</DialogControlContext.Provider>
</DialogContext.Provider>
)
+13 -11
View File
@@ -11,8 +11,10 @@ import {Button, ButtonText, ButtonIcon} from '#/components/Button'
import {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
import {Text} from '#/components/Typography'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails'
import {useOpenGlobalDialog} from '#/components/dialogs'
import {
ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function ContentHider({
testID,
@@ -32,7 +34,7 @@ export function ContentHider({
const {_} = useLingui()
const [override, setOverride] = React.useState(false)
const {gtMobile} = useBreakpoints()
const openDialog = useOpenGlobalDialog()
const control = useModerationDetailsDialogControl()
const blur = modui?.blurs[0]
const desc = useModerationCauseDescription(blur, 'content')
@@ -47,6 +49,12 @@ export function ContentHider({
return (
<View testID={testID} style={[a.overflow_hidden, style]}>
<ModerationDetailsDialog
control={control}
context="content"
modcause={blur}
/>
<View style={[a.flex_col, a.gap_xs]}>
<Button
variant="solid"
@@ -57,10 +65,7 @@ export function ContentHider({
if (!modui.noOverride) {
setOverride(v => !v)
} else {
openDialog(ModerationDetailsDialog, {
context: 'content',
modcause: blur,
})
control.open()
}
}}
label={desc.name}
@@ -83,10 +88,7 @@ export function ContentHider({
variant="ghost"
size="tiny"
onPress={() => {
openDialog(ModerationDetailsDialog, {
context: 'content',
modcause: blur,
})
control.open()
}}
label={_(msg`Learn more`)}>
<ButtonText
+55 -43
View File
@@ -11,8 +11,10 @@ import {Button, ButtonText, ButtonIcon} from '#/components/Button'
import {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails'
import {useOpenGlobalDialog} from '#/components/dialogs'
import {
ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function PostAlerts({
modui,
@@ -43,57 +45,67 @@ export function PostAlerts({
}
function PostInform({cause}: {cause: ModerationCause}) {
const openDialog = useOpenGlobalDialog()
const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'content')
return (
<Button
label={desc.name}
variant="solid"
color="secondary"
size="tiny"
shape="default"
onPress={() => {
openDialog(ModerationDetailsDialog, {
context: 'content',
modcause: cause,
})
}}>
<ButtonIcon
icon={cause.type === 'muted' ? EyeSlash : CircleInfo}
position="left"
/>{' '}
<ButtonText>{desc.name}</ButtonText>
</Button>
<>
<Button
label={desc.name}
variant="solid"
color="secondary"
size="tiny"
shape="default"
onPress={() => {
control.open()
}}>
<ButtonIcon
icon={cause.type === 'muted' ? EyeSlash : CircleInfo}
position="left"
/>{' '}
<ButtonText>{desc.name}</ButtonText>
</Button>
<ModerationDetailsDialog
control={control}
context="content"
modcause={cause}
/>
</>
)
}
function PostAlert({cause}: {cause: ModerationCause}) {
const t = useTheme()
const openDialog = useOpenGlobalDialog()
const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'content')
return (
<Button
label={desc.name}
variant="solid"
color="secondary"
size="small"
shape="default"
onPress={() => {
openDialog(ModerationDetailsDialog, {
context: 'content',
modcause: cause,
})
}}>
<ButtonIcon icon={Shield} position="left" />
<ButtonText style={[a.flex_1, a.text_left]}>
{desc.name}
<Text style={[a.text_sm, t.atoms.text_contrast_medium]}>
{' — ' /* TODO get actual labeler */}
<Trans>Bluesky Safety</Trans>
</Text>
</ButtonText>
</Button>
<>
<Button
label={desc.name}
variant="solid"
color="secondary"
size="small"
shape="default"
onPress={() => {
control.open()
}}>
<ButtonIcon icon={Shield} position="left" />
<ButtonText style={[a.flex_1, a.text_left]}>
{desc.name}
<Text style={[a.text_sm, t.atoms.text_contrast_medium]}>
{' — ' /* TODO get actual labeler */}
<Trans>Bluesky Safety</Trans>
</Text>
</ButtonText>
</Button>
<ModerationDetailsDialog
control={control}
context="content"
modcause={cause}
/>
</>
)
}
+11 -7
View File
@@ -11,8 +11,10 @@ import {useLingui} from '@lingui/react'
import {Trans, msg} from '@lingui/macro'
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails'
import {useOpenGlobalDialog} from '#/components/dialogs'
import {
ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
interface Props extends ComponentProps<typeof Link> {
iconSize: number
@@ -33,7 +35,7 @@ export function PostHider({
const pal = usePalette('default')
const {_} = useLingui()
const [override, setOverride] = React.useState(false)
const openDialog = useOpenGlobalDialog()
const control = useModerationDetailsDialogControl()
const blur = modui.blurs[0]
const desc = useModerationCauseDescription(blur, 'content')
@@ -69,12 +71,14 @@ export function PostHider({
override ? {paddingBottom: 0} : undefined,
pal.view,
]}>
<ModerationDetailsDialog
control={control}
context="content"
modcause={blur}
/>
<Pressable
onPress={() => {
openDialog(ModerationDetailsDialog, {
context: 'content',
modcause: blur,
})
control.open()
}}
accessibilityRole="button"
accessibilityLabel={_(msg`Learn more about this warning`)}
@@ -11,8 +11,10 @@ import {Button, ButtonText, ButtonIcon} from '#/components/Button'
import {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails'
import {useOpenGlobalDialog} from '#/components/dialogs'
import {
ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function ProfileHeaderAlerts({
moderation,
@@ -43,57 +45,66 @@ export function ProfileHeaderAlerts({
}
function ProfileInform({cause}: {cause: ModerationCause}) {
const openDialog = useOpenGlobalDialog()
const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'account')
return (
<Button
label={desc.name}
variant="solid"
color="secondary"
size="tiny"
shape="default"
onPress={() => {
openDialog(ModerationDetailsDialog, {
context: 'account',
modcause: cause,
})
}}>
<ButtonIcon
icon={cause.type === 'muted' ? EyeSlash : CircleInfo}
position="left"
/>{' '}
<ButtonText>{desc.name}</ButtonText>
</Button>
<>
<Button
label={desc.name}
variant="solid"
color="secondary"
size="tiny"
shape="default"
onPress={() => {
control.open()
}}>
<ButtonIcon
icon={cause.type === 'muted' ? EyeSlash : CircleInfo}
position="left"
/>{' '}
<ButtonText>{desc.name}</ButtonText>
</Button>
<ModerationDetailsDialog
control={control}
context="account"
modcause={cause}
/>
</>
)
}
function ProfileAlert({cause}: {cause: ModerationCause}) {
const t = useTheme()
const openDialog = useOpenGlobalDialog()
const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'account')
return (
<Button
label={desc.name}
variant="solid"
color="secondary"
size="small"
shape="default"
onPress={() => {
openDialog(ModerationDetailsDialog, {
context: 'account',
modcause: cause,
})
}}>
<ButtonIcon icon={Shield} position="left" />
<ButtonText style={[a.flex_1, a.text_left]}>
{desc.name}
<Text style={[a.text_sm, t.atoms.text_contrast_medium]}>
{' — ' /* TODO get actual labeler */}
<Trans>Bluesky Safety</Trans>
</Text>
</ButtonText>
</Button>
<>
<Button
label={desc.name}
variant="solid"
color="secondary"
size="small"
shape="default"
onPress={() => {
control.open()
}}>
<ButtonIcon icon={Shield} position="left" />
<ButtonText style={[a.flex_1, a.text_left]}>
{desc.name}
<Text style={[a.text_sm, t.atoms.text_contrast_medium]}>
{' — ' /* TODO get actual labeler */}
<Trans>Bluesky Safety</Trans>
</Text>
</ButtonText>
</Button>
<ModerationDetailsDialog
control={control}
context="account"
modcause={cause}
/>
</>
)
}
+12 -7
View File
@@ -23,8 +23,10 @@ import {useModerationCauseDescription} from '#/lib/moderation/useModerationCause
import {s} from '#/lib/styles'
import {CenteredView} from '../Views'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails'
import {useOpenGlobalDialog} from '#/components/dialogs'
import {
ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function ScreenHider({
testID,
@@ -46,7 +48,7 @@ export function ScreenHider({
const [override, setOverride] = React.useState(false)
const navigation = useNavigation<NavigationProp>()
const {isMobile} = useWebMediaQueries()
const openDialog = useOpenGlobalDialog()
const control = useModerationDetailsDialogControl()
const blur = modui.blurs[0]
const desc = useModerationCauseDescription(blur, 'content')
@@ -95,10 +97,7 @@ export function ScreenHider({
</Text>
<TouchableWithoutFeedback
onPress={() => {
openDialog(ModerationDetailsDialog, {
context: 'account',
modcause: blur,
})
control.open()
}}
accessibilityRole="button"
accessibilityLabel={_(msg`Learn more about this warning`)}
@@ -107,6 +106,12 @@ export function ScreenHider({
<Trans>Learn More</Trans>
</Text>
</TouchableWithoutFeedback>
<ModerationDetailsDialog
control={control}
context="account"
modcause={blur}
/>
</>
)}{' '}
</Text>