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 {atoms as a, useBreakpoints} from '#/alf'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import {GlobalDialogProps} from '#/components/dialogs'
import {Button} from '#/components/Button' import {Button} from '#/components/Button'
import {InlineLink} from '#/components/Link' import {InlineLink} from '#/components/Link'
import {useLabelStrings} from '#/lib/moderation/useLabelStrings' import {useLabelStrings} from '#/lib/moderation/useLabelStrings'
import {listUriToHref} from '#/lib/strings/url-helpers' import {listUriToHref} from '#/lib/strings/url-helpers'
export {useDialogControl as useModerationDetailsDialogControl} from '#/components/Dialog'
export interface ModerationDetailsDialogProps { export interface ModerationDetailsDialogProps {
control: Dialog.DialogOuterProps['control']
context: 'account' | 'content' context: 'account' | 'content'
modcause: ModerationCause modcause: ModerationCause
} }
export function ModerationDetailsDialog({ export function ModerationDetailsDialog(props: ModerationDetailsDialogProps) {
params, return (
cleanup, <Dialog.Outer control={props.control}>
}: GlobalDialogProps<ModerationDetailsDialogProps>) { <Dialog.Handle />
<ModerationDetailsDialogInner {...props} />
</Dialog.Outer>
)
}
function ModerationDetailsDialogInner({
context,
modcause,
}: ModerationDetailsDialogProps & {
control: Dialog.DialogOuterProps['control']
}) {
const {_} = useLingui() const {_} = useLingui()
const labelStrings = useLabelStrings() const labelStrings = useLabelStrings()
const control = Dialog.useDialogControl() const control = Dialog.useDialogControl()
const {gtMobile} = useBreakpoints() const {gtMobile} = useBreakpoints()
const {context, modcause} = params
// REQUIRED CLEANUP
const onClose = React.useCallback(() => cleanup(), [cleanup])
let name let name
let description let description
@@ -99,9 +109,6 @@ export function ModerationDetailsDialog({
} }
return ( return (
<Dialog.Outer defaultOpen control={control} onClose={onClose}>
<Dialog.Handle />
<Dialog.ScrollableInner <Dialog.ScrollableInner
accessibilityDescribedBy="dialog-description" accessibilityDescribedBy="dialog-description"
accessibilityLabelledBy="dialog-title"> accessibilityLabelledBy="dialog-title">
@@ -123,6 +130,5 @@ export function ModerationDetailsDialog({
</Button> </Button>
</View> </View>
</Dialog.ScrollableInner> </Dialog.ScrollableInner>
</Dialog.Outer>
) )
} }
+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 React from 'react'
import {DialogControlProps} from '#/components/Dialog' import {DialogControlProps} from '#/components/Dialog'
import {Provider as GlobalDialogsProvider} from '#/components/dialogs' import {Provider as GlobalDialogsProvider} from '#/components/dialogs'
import {Provider as GlobalDialogsProviderV2} from '#/components/dialogs/Context'
const DialogContext = React.createContext<{ const DialogContext = React.createContext<{
activeDialogs: React.MutableRefObject< activeDialogs: React.MutableRefObject<
@@ -28,7 +29,7 @@ export function useDialogStateControlContext() {
export function Provider({children}: React.PropsWithChildren<{}>) { export function Provider({children}: React.PropsWithChildren<{}>) {
const activeDialogs = React.useRef< const activeDialogs = React.useRef<
Map<string, React.MutableRefObject<DialogControlProps<{}>>> Map<string, React.MutableRefObject<DialogControlProps>>
>(new Map()) >(new Map())
const closeAllDialogs = React.useCallback(() => { const closeAllDialogs = React.useCallback(() => {
activeDialogs.current.forEach(dialog => dialog.current.close()) activeDialogs.current.forEach(dialog => dialog.current.close())
@@ -38,7 +39,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
return ( return (
<DialogContext.Provider value={context}> <DialogContext.Provider value={context}>
<DialogControlContext.Provider value={controls}> <DialogControlContext.Provider value={controls}>
<GlobalDialogsProvider>{children}</GlobalDialogsProvider> <GlobalDialogsProvider>
<GlobalDialogsProviderV2>{children}</GlobalDialogsProviderV2>
</GlobalDialogsProvider>
</DialogControlContext.Provider> </DialogControlContext.Provider>
</DialogContext.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 {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash' import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails' import {
import {useOpenGlobalDialog} from '#/components/dialogs' ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function ContentHider({ export function ContentHider({
testID, testID,
@@ -32,7 +34,7 @@ export function ContentHider({
const {_} = useLingui() const {_} = useLingui()
const [override, setOverride] = React.useState(false) const [override, setOverride] = React.useState(false)
const {gtMobile} = useBreakpoints() const {gtMobile} = useBreakpoints()
const openDialog = useOpenGlobalDialog() const control = useModerationDetailsDialogControl()
const blur = modui?.blurs[0] const blur = modui?.blurs[0]
const desc = useModerationCauseDescription(blur, 'content') const desc = useModerationCauseDescription(blur, 'content')
@@ -47,6 +49,12 @@ export function ContentHider({
return ( return (
<View testID={testID} style={[a.overflow_hidden, style]}> <View testID={testID} style={[a.overflow_hidden, style]}>
<ModerationDetailsDialog
control={control}
context="content"
modcause={blur}
/>
<View style={[a.flex_col, a.gap_xs]}> <View style={[a.flex_col, a.gap_xs]}>
<Button <Button
variant="solid" variant="solid"
@@ -57,10 +65,7 @@ export function ContentHider({
if (!modui.noOverride) { if (!modui.noOverride) {
setOverride(v => !v) setOverride(v => !v)
} else { } else {
openDialog(ModerationDetailsDialog, { control.open()
context: 'content',
modcause: blur,
})
} }
}} }}
label={desc.name} label={desc.name}
@@ -83,10 +88,7 @@ export function ContentHider({
variant="ghost" variant="ghost"
size="tiny" size="tiny"
onPress={() => { onPress={() => {
openDialog(ModerationDetailsDialog, { control.open()
context: 'content',
modcause: blur,
})
}} }}
label={_(msg`Learn more`)}> label={_(msg`Learn more`)}>
<ButtonText <ButtonText
+24 -12
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 {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash' import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails' import {
import {useOpenGlobalDialog} from '#/components/dialogs' ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function PostAlerts({ export function PostAlerts({
modui, modui,
@@ -43,10 +45,11 @@ export function PostAlerts({
} }
function PostInform({cause}: {cause: ModerationCause}) { function PostInform({cause}: {cause: ModerationCause}) {
const openDialog = useOpenGlobalDialog() const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'content') const desc = useModerationCauseDescription(cause, 'content')
return ( return (
<>
<Button <Button
label={desc.name} label={desc.name}
variant="solid" variant="solid"
@@ -54,10 +57,7 @@ function PostInform({cause}: {cause: ModerationCause}) {
size="tiny" size="tiny"
shape="default" shape="default"
onPress={() => { onPress={() => {
openDialog(ModerationDetailsDialog, { control.open()
context: 'content',
modcause: cause,
})
}}> }}>
<ButtonIcon <ButtonIcon
icon={cause.type === 'muted' ? EyeSlash : CircleInfo} icon={cause.type === 'muted' ? EyeSlash : CircleInfo}
@@ -65,15 +65,23 @@ function PostInform({cause}: {cause: ModerationCause}) {
/>{' '} />{' '}
<ButtonText>{desc.name}</ButtonText> <ButtonText>{desc.name}</ButtonText>
</Button> </Button>
<ModerationDetailsDialog
control={control}
context="content"
modcause={cause}
/>
</>
) )
} }
function PostAlert({cause}: {cause: ModerationCause}) { function PostAlert({cause}: {cause: ModerationCause}) {
const t = useTheme() const t = useTheme()
const openDialog = useOpenGlobalDialog() const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'content') const desc = useModerationCauseDescription(cause, 'content')
return ( return (
<>
<Button <Button
label={desc.name} label={desc.name}
variant="solid" variant="solid"
@@ -81,10 +89,7 @@ function PostAlert({cause}: {cause: ModerationCause}) {
size="small" size="small"
shape="default" shape="default"
onPress={() => { onPress={() => {
openDialog(ModerationDetailsDialog, { control.open()
context: 'content',
modcause: cause,
})
}}> }}>
<ButtonIcon icon={Shield} position="left" /> <ButtonIcon icon={Shield} position="left" />
<ButtonText style={[a.flex_1, a.text_left]}> <ButtonText style={[a.flex_1, a.text_left]}>
@@ -95,5 +100,12 @@ function PostAlert({cause}: {cause: ModerationCause}) {
</Text> </Text>
</ButtonText> </ButtonText>
</Button> </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 {Trans, msg} from '@lingui/macro'
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails' import {
import {useOpenGlobalDialog} from '#/components/dialogs' ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
interface Props extends ComponentProps<typeof Link> { interface Props extends ComponentProps<typeof Link> {
iconSize: number iconSize: number
@@ -33,7 +35,7 @@ export function PostHider({
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const [override, setOverride] = React.useState(false) const [override, setOverride] = React.useState(false)
const openDialog = useOpenGlobalDialog() const control = useModerationDetailsDialogControl()
const blur = modui.blurs[0] const blur = modui.blurs[0]
const desc = useModerationCauseDescription(blur, 'content') const desc = useModerationCauseDescription(blur, 'content')
@@ -69,12 +71,14 @@ export function PostHider({
override ? {paddingBottom: 0} : undefined, override ? {paddingBottom: 0} : undefined,
pal.view, pal.view,
]}> ]}>
<ModerationDetailsDialog
control={control}
context="content"
modcause={blur}
/>
<Pressable <Pressable
onPress={() => { onPress={() => {
openDialog(ModerationDetailsDialog, { control.open()
context: 'content',
modcause: blur,
})
}} }}
accessibilityRole="button" accessibilityRole="button"
accessibilityLabel={_(msg`Learn more about this warning`)} 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 {Shield_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash' import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails' import {
import {useOpenGlobalDialog} from '#/components/dialogs' ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function ProfileHeaderAlerts({ export function ProfileHeaderAlerts({
moderation, moderation,
@@ -43,10 +45,11 @@ export function ProfileHeaderAlerts({
} }
function ProfileInform({cause}: {cause: ModerationCause}) { function ProfileInform({cause}: {cause: ModerationCause}) {
const openDialog = useOpenGlobalDialog() const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'account') const desc = useModerationCauseDescription(cause, 'account')
return ( return (
<>
<Button <Button
label={desc.name} label={desc.name}
variant="solid" variant="solid"
@@ -54,10 +57,7 @@ function ProfileInform({cause}: {cause: ModerationCause}) {
size="tiny" size="tiny"
shape="default" shape="default"
onPress={() => { onPress={() => {
openDialog(ModerationDetailsDialog, { control.open()
context: 'account',
modcause: cause,
})
}}> }}>
<ButtonIcon <ButtonIcon
icon={cause.type === 'muted' ? EyeSlash : CircleInfo} icon={cause.type === 'muted' ? EyeSlash : CircleInfo}
@@ -65,15 +65,23 @@ function ProfileInform({cause}: {cause: ModerationCause}) {
/>{' '} />{' '}
<ButtonText>{desc.name}</ButtonText> <ButtonText>{desc.name}</ButtonText>
</Button> </Button>
<ModerationDetailsDialog
control={control}
context="account"
modcause={cause}
/>
</>
) )
} }
function ProfileAlert({cause}: {cause: ModerationCause}) { function ProfileAlert({cause}: {cause: ModerationCause}) {
const t = useTheme() const t = useTheme()
const openDialog = useOpenGlobalDialog() const control = useModerationDetailsDialogControl()
const desc = useModerationCauseDescription(cause, 'account') const desc = useModerationCauseDescription(cause, 'account')
return ( return (
<>
<Button <Button
label={desc.name} label={desc.name}
variant="solid" variant="solid"
@@ -81,10 +89,7 @@ function ProfileAlert({cause}: {cause: ModerationCause}) {
size="small" size="small"
shape="default" shape="default"
onPress={() => { onPress={() => {
openDialog(ModerationDetailsDialog, { control.open()
context: 'account',
modcause: cause,
})
}}> }}>
<ButtonIcon icon={Shield} position="left" /> <ButtonIcon icon={Shield} position="left" />
<ButtonText style={[a.flex_1, a.text_left]}> <ButtonText style={[a.flex_1, a.text_left]}>
@@ -95,5 +100,11 @@ function ProfileAlert({cause}: {cause: ModerationCause}) {
</Text> </Text>
</ButtonText> </ButtonText>
</Button> </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 {s} from '#/lib/styles'
import {CenteredView} from '../Views' import {CenteredView} from '../Views'
import {ModerationDetailsDialog} from '#/components/dialogs/ModerationDetails' import {
import {useOpenGlobalDialog} from '#/components/dialogs' ModerationDetailsDialog,
useModerationDetailsDialogControl,
} from '#/components/ModerationDetailsDialog'
export function ScreenHider({ export function ScreenHider({
testID, testID,
@@ -46,7 +48,7 @@ export function ScreenHider({
const [override, setOverride] = React.useState(false) const [override, setOverride] = React.useState(false)
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {isMobile} = useWebMediaQueries() const {isMobile} = useWebMediaQueries()
const openDialog = useOpenGlobalDialog() const control = useModerationDetailsDialogControl()
const blur = modui.blurs[0] const blur = modui.blurs[0]
const desc = useModerationCauseDescription(blur, 'content') const desc = useModerationCauseDescription(blur, 'content')
@@ -95,10 +97,7 @@ export function ScreenHider({
</Text> </Text>
<TouchableWithoutFeedback <TouchableWithoutFeedback
onPress={() => { onPress={() => {
openDialog(ModerationDetailsDialog, { control.open()
context: 'account',
modcause: blur,
})
}} }}
accessibilityRole="button" accessibilityRole="button"
accessibilityLabel={_(msg`Learn more about this warning`)} accessibilityLabel={_(msg`Learn more about this warning`)}
@@ -107,6 +106,12 @@ export function ScreenHider({
<Trans>Learn More</Trans> <Trans>Learn More</Trans>
</Text> </Text>
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
<ModerationDetailsDialog
control={control}
context="account"
modcause={blur}
/>
</> </>
)}{' '} )}{' '}
</Text> </Text>