Delete old report dialog (#9214)e
This commit is contained in:
@@ -1,85 +0,0 @@
|
|||||||
import {View} from 'react-native'
|
|
||||||
import {type AppBskyLabelerDefs} from '@atproto/api'
|
|
||||||
import {msg, Trans} from '@lingui/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
|
|
||||||
import {getLabelingServiceTitle} from '#/lib/moderation'
|
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
|
||||||
import {Button, useButtonContext} from '#/components/Button'
|
|
||||||
import {Divider} from '#/components/Divider'
|
|
||||||
import * as LabelingServiceCard from '#/components/LabelingServiceCard'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
import {type ReportDialogProps} from './types'
|
|
||||||
|
|
||||||
export function SelectLabelerView({
|
|
||||||
...props
|
|
||||||
}: ReportDialogProps & {
|
|
||||||
labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
|
|
||||||
onSelectLabeler: (v: string) => void
|
|
||||||
}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const {_} = useLingui()
|
|
||||||
const {gtMobile} = useBreakpoints()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={[a.gap_lg]}>
|
|
||||||
<View style={[a.justify_center, gtMobile ? a.gap_sm : a.gap_xs]}>
|
|
||||||
<Text style={[a.text_2xl, a.font_semi_bold]}>
|
|
||||||
<Trans>Select moderator</Trans>
|
|
||||||
</Text>
|
|
||||||
<Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
|
||||||
<Trans>To whom would you like to send this report?</Trans>
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<View style={[a.gap_sm]}>
|
|
||||||
{props.labelers.map(labeler => {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
key={labeler.creator.did}
|
|
||||||
label={_(msg`Send report to ${labeler.creator.displayName}`)}
|
|
||||||
onPress={() => props.onSelectLabeler(labeler.creator.did)}>
|
|
||||||
<LabelerButton labeler={labeler} />
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function LabelerButton({
|
|
||||||
labeler,
|
|
||||||
}: {
|
|
||||||
labeler: AppBskyLabelerDefs.LabelerViewDetailed
|
|
||||||
}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const {hovered, pressed} = useButtonContext()
|
|
||||||
const interacted = hovered || pressed
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LabelingServiceCard.Outer
|
|
||||||
style={[
|
|
||||||
a.p_md,
|
|
||||||
a.rounded_sm,
|
|
||||||
t.atoms.bg_contrast_25,
|
|
||||||
interacted && t.atoms.bg_contrast_50,
|
|
||||||
]}>
|
|
||||||
<LabelingServiceCard.Avatar avatar={labeler.creator.avatar} />
|
|
||||||
<LabelingServiceCard.Content>
|
|
||||||
<LabelingServiceCard.Title
|
|
||||||
value={getLabelingServiceTitle({
|
|
||||||
displayName: labeler.creator.displayName,
|
|
||||||
handle: labeler.creator.handle,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<Text
|
|
||||||
style={[t.atoms.text_contrast_medium, a.text_sm, a.font_semi_bold]}>
|
|
||||||
@{labeler.creator.handle}
|
|
||||||
</Text>
|
|
||||||
</LabelingServiceCard.Content>
|
|
||||||
</LabelingServiceCard.Outer>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import {View} from 'react-native'
|
|
||||||
import {type AppBskyLabelerDefs} from '@atproto/api'
|
|
||||||
import {msg, Trans} from '@lingui/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
|
|
||||||
import {
|
|
||||||
type ReportOption,
|
|
||||||
useReportOptions,
|
|
||||||
} from '#/lib/moderation/useReportOptions'
|
|
||||||
import {Link} from '#/components/Link'
|
|
||||||
import {DMCA_LINK} from '#/components/ReportDialog/const'
|
|
||||||
export {useDialogControl as useReportDialogControl} from '#/components/Dialog'
|
|
||||||
|
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
ButtonIcon,
|
|
||||||
ButtonText,
|
|
||||||
useButtonContext,
|
|
||||||
} from '#/components/Button'
|
|
||||||
import {Divider} from '#/components/Divider'
|
|
||||||
import {
|
|
||||||
ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft,
|
|
||||||
ChevronRight_Stroke2_Corner0_Rounded as ChevronRight,
|
|
||||||
} from '#/components/icons/Chevron'
|
|
||||||
import {SquareArrowTopRight_Stroke2_Corner0_Rounded as SquareArrowTopRight} from '#/components/icons/SquareArrowTopRight'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
import {type ReportDialogProps} from './types'
|
|
||||||
|
|
||||||
export function SelectReportOptionView(props: {
|
|
||||||
params: ReportDialogProps['params']
|
|
||||||
labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
|
|
||||||
onSelectReportOption: (reportOption: ReportOption) => void
|
|
||||||
goBack: () => void
|
|
||||||
}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const {_} = useLingui()
|
|
||||||
const {gtMobile} = useBreakpoints()
|
|
||||||
const allReportOptions = useReportOptions()
|
|
||||||
const reportOptions = allReportOptions[props.params.type]
|
|
||||||
|
|
||||||
const i18n = React.useMemo(() => {
|
|
||||||
let title = _(msg`Report this content`)
|
|
||||||
let description = _(msg`Why should this content be reviewed?`)
|
|
||||||
|
|
||||||
if (props.params.type === 'account') {
|
|
||||||
title = _(msg`Report this user`)
|
|
||||||
description = _(msg`Why should this user be reviewed?`)
|
|
||||||
} else if (props.params.type === 'post') {
|
|
||||||
title = _(msg`Report this post`)
|
|
||||||
description = _(msg`Why should this post be reviewed?`)
|
|
||||||
} else if (props.params.type === 'list') {
|
|
||||||
title = _(msg`Report this list`)
|
|
||||||
description = _(msg`Why should this list be reviewed?`)
|
|
||||||
} else if (props.params.type === 'feedgen') {
|
|
||||||
title = _(msg`Report this feed`)
|
|
||||||
description = _(msg`Why should this feed be reviewed?`)
|
|
||||||
} else if (props.params.type === 'starterpack') {
|
|
||||||
title = _(msg`Report this starter pack`)
|
|
||||||
description = _(msg`Why should this starter pack be reviewed?`)
|
|
||||||
} else if (props.params.type === 'convoMessage') {
|
|
||||||
title = _(msg`Report this message`)
|
|
||||||
description = _(msg`Why should this message be reviewed?`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
}
|
|
||||||
}, [_, props.params.type])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={[a.gap_lg]}>
|
|
||||||
{props.labelers?.length > 1 ? (
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
variant="solid"
|
|
||||||
color="secondary"
|
|
||||||
shape="round"
|
|
||||||
label={_(msg`Go back to previous step`)}
|
|
||||||
onPress={props.goBack}>
|
|
||||||
<ButtonIcon icon={ChevronLeft} />
|
|
||||||
</Button>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<View style={[a.justify_center, gtMobile ? a.gap_sm : a.gap_xs]}>
|
|
||||||
<Text style={[a.text_2xl, a.font_semi_bold]}>{i18n.title}</Text>
|
|
||||||
<Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
|
||||||
{i18n.description}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<View style={[a.gap_sm]}>
|
|
||||||
{reportOptions.map(reportOption => {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
key={reportOption.reason}
|
|
||||||
testID={reportOption.reason}
|
|
||||||
label={_(msg`Create report for ${reportOption.title}`)}
|
|
||||||
onPress={() => props.onSelectReportOption(reportOption)}>
|
|
||||||
<ReportOptionButton
|
|
||||||
title={reportOption.title}
|
|
||||||
description={reportOption.description}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
|
|
||||||
{(props.params.type === 'post' || props.params.type === 'account') && (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_between,
|
|
||||||
a.gap_lg,
|
|
||||||
a.p_md,
|
|
||||||
a.pl_lg,
|
|
||||||
a.rounded_md,
|
|
||||||
t.atoms.bg_contrast_900,
|
|
||||||
]}>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.flex_1,
|
|
||||||
t.atoms.text_inverted,
|
|
||||||
a.italic,
|
|
||||||
a.leading_snug,
|
|
||||||
]}>
|
|
||||||
<Trans>Need to report a copyright violation?</Trans>
|
|
||||||
</Text>
|
|
||||||
<Link
|
|
||||||
to={DMCA_LINK}
|
|
||||||
label={_(msg`View details for reporting a copyright violation`)}
|
|
||||||
size="small"
|
|
||||||
variant="solid"
|
|
||||||
color="secondary">
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>View details</Trans>
|
|
||||||
</ButtonText>
|
|
||||||
<ButtonIcon position="right" icon={SquareArrowTopRight} />
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ReportOptionButton({
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
}: {
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const {hovered, pressed} = useButtonContext()
|
|
||||||
const interacted = hovered || pressed
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.w_full,
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_between,
|
|
||||||
a.p_md,
|
|
||||||
a.rounded_md,
|
|
||||||
{paddingRight: 70},
|
|
||||||
t.atoms.bg_contrast_25,
|
|
||||||
interacted && t.atoms.bg_contrast_50,
|
|
||||||
]}>
|
|
||||||
<View style={[a.flex_1, a.gap_xs]}>
|
|
||||||
<Text
|
|
||||||
style={[a.text_md, a.font_semi_bold, t.atoms.text_contrast_medium]}>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
<Text style={[a.leading_tight, {maxWidth: 400}]}>{description}</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.absolute,
|
|
||||||
a.inset_0,
|
|
||||||
a.justify_center,
|
|
||||||
a.pr_md,
|
|
||||||
{left: 'auto'},
|
|
||||||
]}>
|
|
||||||
<ChevronRight size="md" fill={t.atoms.text_contrast_low.color} />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import {View} from 'react-native'
|
|
||||||
import {type AppBskyLabelerDefs} from '@atproto/api'
|
|
||||||
import {msg, Trans} from '@lingui/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
|
|
||||||
import {getLabelingServiceTitle} from '#/lib/moderation'
|
|
||||||
import {type ReportOption} from '#/lib/moderation/useReportOptions'
|
|
||||||
import {isAndroid} from '#/platform/detection'
|
|
||||||
import {useAgent} from '#/state/session'
|
|
||||||
import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
|
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
|
||||||
import {atoms as a, native, useTheme} from '#/alf'
|
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
|
||||||
import * as Dialog from '#/components/Dialog'
|
|
||||||
import * as Toggle from '#/components/forms/Toggle'
|
|
||||||
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
|
||||||
import {ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft} from '#/components/icons/Chevron'
|
|
||||||
import {PaperPlane_Stroke2_Corner0_Rounded as SendIcon} from '#/components/icons/PaperPlane'
|
|
||||||
import {Loader} from '#/components/Loader'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
import {type ReportDialogProps} from './types'
|
|
||||||
|
|
||||||
export function SubmitView({
|
|
||||||
params,
|
|
||||||
labelers,
|
|
||||||
selectedLabeler,
|
|
||||||
selectedReportOption,
|
|
||||||
goBack,
|
|
||||||
onSubmitComplete,
|
|
||||||
}: ReportDialogProps & {
|
|
||||||
labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
|
|
||||||
selectedLabeler: string
|
|
||||||
selectedReportOption: ReportOption
|
|
||||||
goBack: () => void
|
|
||||||
onSubmitComplete: () => void
|
|
||||||
}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const {_} = useLingui()
|
|
||||||
const agent = useAgent()
|
|
||||||
const [details, setDetails] = React.useState<string>('')
|
|
||||||
const [submitting, setSubmitting] = React.useState<boolean>(false)
|
|
||||||
const [selectedServices, setSelectedServices] = React.useState<string[]>([
|
|
||||||
selectedLabeler,
|
|
||||||
])
|
|
||||||
const [error, setError] = React.useState('')
|
|
||||||
|
|
||||||
const submit = React.useCallback(async () => {
|
|
||||||
setSubmitting(true)
|
|
||||||
setError('')
|
|
||||||
|
|
||||||
const $type =
|
|
||||||
params.type === 'account'
|
|
||||||
? 'com.atproto.admin.defs#repoRef'
|
|
||||||
: 'com.atproto.repo.strongRef'
|
|
||||||
const report = {
|
|
||||||
reasonType: selectedReportOption.reason,
|
|
||||||
subject: {
|
|
||||||
$type,
|
|
||||||
...params,
|
|
||||||
},
|
|
||||||
reason: details,
|
|
||||||
}
|
|
||||||
const results = await Promise.all(
|
|
||||||
selectedServices.map(did => {
|
|
||||||
return agent
|
|
||||||
.createModerationReport(report, {
|
|
||||||
encoding: 'application/json',
|
|
||||||
headers: {
|
|
||||||
'atproto-proxy': `${did}#atproto_labeler`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(
|
|
||||||
_ => true,
|
|
||||||
_ => false,
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
setSubmitting(false)
|
|
||||||
|
|
||||||
if (results.includes(true)) {
|
|
||||||
Toast.show(_(msg`Thank you. Your report has been sent.`))
|
|
||||||
onSubmitComplete()
|
|
||||||
} else {
|
|
||||||
setError(
|
|
||||||
_(
|
|
||||||
msg`There was an issue sending your report. Please check your internet connection.`,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
_,
|
|
||||||
params,
|
|
||||||
details,
|
|
||||||
selectedReportOption,
|
|
||||||
selectedServices,
|
|
||||||
onSubmitComplete,
|
|
||||||
setError,
|
|
||||||
agent,
|
|
||||||
])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={[a.gap_2xl]}>
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
variant="solid"
|
|
||||||
color="secondary"
|
|
||||||
shape="round"
|
|
||||||
label={_(msg`Go back to previous step`)}
|
|
||||||
onPress={goBack}>
|
|
||||||
<ButtonIcon icon={ChevronLeft} />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.w_full,
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_between,
|
|
||||||
a.gap_lg,
|
|
||||||
a.p_md,
|
|
||||||
a.rounded_md,
|
|
||||||
a.border,
|
|
||||||
t.atoms.border_contrast_low,
|
|
||||||
]}>
|
|
||||||
<View style={[a.flex_1, a.gap_xs]}>
|
|
||||||
<Text style={[a.text_md, a.font_semi_bold]}>
|
|
||||||
{selectedReportOption.title}
|
|
||||||
</Text>
|
|
||||||
<Text style={[a.leading_tight, {maxWidth: 400}]}>
|
|
||||||
{selectedReportOption.description}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Check size="md" style={[a.pr_sm, t.atoms.text_contrast_low]} />
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={[a.gap_md]}>
|
|
||||||
<Text style={[t.atoms.text_contrast_medium]}>
|
|
||||||
<Trans>Select the moderation service(s) to report to</Trans>
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Toggle.Group
|
|
||||||
label="Select mod services"
|
|
||||||
values={selectedServices}
|
|
||||||
onChange={setSelectedServices}>
|
|
||||||
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
|
|
||||||
{labelers.map(labeler => {
|
|
||||||
const title = getLabelingServiceTitle({
|
|
||||||
displayName: labeler.creator.displayName,
|
|
||||||
handle: labeler.creator.handle,
|
|
||||||
})
|
|
||||||
return (
|
|
||||||
<Toggle.Item
|
|
||||||
key={labeler.creator.did}
|
|
||||||
name={labeler.creator.did}
|
|
||||||
label={title}>
|
|
||||||
<LabelerToggle title={title} />
|
|
||||||
</Toggle.Item>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</Toggle.Group>
|
|
||||||
</View>
|
|
||||||
<View style={[a.gap_md]}>
|
|
||||||
<Text style={[t.atoms.text_contrast_medium]}>
|
|
||||||
<Trans>Optionally provide additional information below:</Trans>
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<View style={[a.relative, a.w_full]}>
|
|
||||||
<Dialog.Input
|
|
||||||
multiline
|
|
||||||
value={details}
|
|
||||||
onChangeText={setDetails}
|
|
||||||
label="Text field"
|
|
||||||
style={{paddingRight: 60}}
|
|
||||||
numberOfLines={6}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.absolute,
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.pr_md,
|
|
||||||
a.pb_sm,
|
|
||||||
{
|
|
||||||
bottom: 0,
|
|
||||||
right: 0,
|
|
||||||
},
|
|
||||||
]}>
|
|
||||||
<CharProgress count={details?.length || 0} />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={[a.flex_row, a.align_center, a.justify_end, a.gap_lg]}>
|
|
||||||
{!selectedServices.length ||
|
|
||||||
(error && (
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.flex_1,
|
|
||||||
a.italic,
|
|
||||||
a.leading_snug,
|
|
||||||
t.atoms.text_contrast_medium,
|
|
||||||
]}>
|
|
||||||
{error ? (
|
|
||||||
error
|
|
||||||
) : (
|
|
||||||
<Trans>You must select at least one labeler for a report</Trans>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<Button
|
|
||||||
testID="sendReportBtn"
|
|
||||||
size="large"
|
|
||||||
variant="solid"
|
|
||||||
color="negative"
|
|
||||||
label={_(msg`Send report`)}
|
|
||||||
onPress={submit}
|
|
||||||
disabled={!selectedServices.length}>
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>Send report</Trans>
|
|
||||||
</ButtonText>
|
|
||||||
<ButtonIcon icon={submitting ? Loader : SendIcon} />
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
{/* Maybe fix this later -h */}
|
|
||||||
{isAndroid ? <View style={{height: 300}} /> : null}
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function LabelerToggle({title}: {title: string}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const ctx = Toggle.useItemContext()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.gap_md,
|
|
||||||
a.p_md,
|
|
||||||
a.pr_lg,
|
|
||||||
a.rounded_sm,
|
|
||||||
a.overflow_hidden,
|
|
||||||
t.atoms.bg_contrast_25,
|
|
||||||
ctx.selected && [t.atoms.bg_contrast_50],
|
|
||||||
]}>
|
|
||||||
<Toggle.Checkbox />
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_between,
|
|
||||||
a.gap_lg,
|
|
||||||
a.z_10,
|
|
||||||
]}>
|
|
||||||
<Text
|
|
||||||
emoji
|
|
||||||
style={[
|
|
||||||
native({marginTop: 2}),
|
|
||||||
t.atoms.text_contrast_medium,
|
|
||||||
ctx.selected && t.atoms.text,
|
|
||||||
]}>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export const DMCA_LINK = 'https://bsky.social/about/support/copyright'
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import {Pressable, View} from 'react-native'
|
|
||||||
import {type ScrollView} from 'react-native-gesture-handler'
|
|
||||||
import {msg, Trans} from '@lingui/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
|
|
||||||
import {type ReportOption} from '#/lib/moderation/useReportOptions'
|
|
||||||
import {useMyLabelersQuery} from '#/state/queries/preferences'
|
|
||||||
export {useDialogControl as useReportDialogControl} from '#/components/Dialog'
|
|
||||||
|
|
||||||
import {type AppBskyLabelerDefs} from '@atproto/api'
|
|
||||||
|
|
||||||
import {atoms as a} from '#/alf'
|
|
||||||
import * as Dialog from '#/components/Dialog'
|
|
||||||
import {useDelayedLoading} from '#/components/hooks/useDelayedLoading'
|
|
||||||
import {Loader} from '#/components/Loader'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
import {SelectLabelerView} from './SelectLabelerView'
|
|
||||||
import {SelectReportOptionView} from './SelectReportOptionView'
|
|
||||||
import {SubmitView} from './SubmitView'
|
|
||||||
import {type ReportDialogProps} from './types'
|
|
||||||
|
|
||||||
export function ReportDialog(props: ReportDialogProps) {
|
|
||||||
return (
|
|
||||||
<Dialog.Outer control={props.control}>
|
|
||||||
<Dialog.Handle />
|
|
||||||
<ReportDialogInner {...props} />
|
|
||||||
</Dialog.Outer>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ReportDialogInner(props: ReportDialogProps) {
|
|
||||||
const {_} = useLingui()
|
|
||||||
const {
|
|
||||||
isLoading: isLabelerLoading,
|
|
||||||
data: labelers,
|
|
||||||
error,
|
|
||||||
} = useMyLabelersQuery({excludeNonConfigurableLabelers: true})
|
|
||||||
const isLoading = useDelayedLoading(500, isLabelerLoading)
|
|
||||||
|
|
||||||
const ref = React.useRef<ScrollView>(null)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog.ScrollableInner label={_(msg`Report dialog`)} ref={ref}>
|
|
||||||
{isLoading ? (
|
|
||||||
<View style={[a.align_center, {height: 100}]}>
|
|
||||||
<Loader size="xl" />
|
|
||||||
{/* Here to capture focus for a hot sec to prevent flash */}
|
|
||||||
<Pressable accessible={false} />
|
|
||||||
</View>
|
|
||||||
) : error || !labelers ? (
|
|
||||||
<View>
|
|
||||||
<Text style={[a.text_md]}>
|
|
||||||
<Trans>Something went wrong, please try again.</Trans>
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<ReportDialogLoaded labelers={labelers} {...props} />
|
|
||||||
)}
|
|
||||||
</Dialog.ScrollableInner>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ReportDialogLoaded(
|
|
||||||
props: ReportDialogProps & {
|
|
||||||
labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const [selectedLabeler, setSelectedLabeler] = React.useState<
|
|
||||||
string | undefined
|
|
||||||
>(props.labelers.length === 1 ? props.labelers[0].creator.did : undefined)
|
|
||||||
const [selectedReportOption, setSelectedReportOption] = React.useState<
|
|
||||||
ReportOption | undefined
|
|
||||||
>()
|
|
||||||
|
|
||||||
if (selectedReportOption && selectedLabeler) {
|
|
||||||
return (
|
|
||||||
<SubmitView
|
|
||||||
{...props}
|
|
||||||
selectedLabeler={selectedLabeler}
|
|
||||||
selectedReportOption={selectedReportOption}
|
|
||||||
goBack={() => setSelectedReportOption(undefined)}
|
|
||||||
onSubmitComplete={() => props.control.close()}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (selectedLabeler) {
|
|
||||||
return (
|
|
||||||
<SelectReportOptionView
|
|
||||||
{...props}
|
|
||||||
goBack={() => setSelectedLabeler(undefined)}
|
|
||||||
onSelectReportOption={setSelectedReportOption}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return <SelectLabelerView {...props} onSelectLabeler={setSelectedLabeler} />
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import type * as Dialog from '#/components/Dialog'
|
|
||||||
|
|
||||||
export type ReportDialogProps = {
|
|
||||||
control: Dialog.DialogOuterProps['control']
|
|
||||||
params:
|
|
||||||
| {
|
|
||||||
type: 'post' | 'list' | 'feedgen' | 'starterpack' | 'other'
|
|
||||||
uri: string
|
|
||||||
cid: string
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'account'
|
|
||||||
did: string
|
|
||||||
}
|
|
||||||
| {type: 'convoMessage'}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user