Merge branch '3p-moderators' of github.com:bluesky-social/social-app into 3p-moderators
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M14 5a1 1 0 1 1 0-2h6a1 1 0 0 1 1 1v6a1 1 0 1 1-2 0V6.414l-7.293 7.293a1 1 0 0 1-1.414-1.414L17.586 5H14ZM3 6a1 1 0 0 1 1-1h5a1 1 0 0 1 0 2H5v12h12v-4a1 1 0 1 1 2 0v5a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6Z" clip-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 342 B |
@@ -0,0 +1 @@
|
|||||||
|
export const DMCA_LINK = 'https://bsky.social/about/support/copyright'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View, Dimensions} from 'react-native'
|
import {View, Dimensions, Linking} from 'react-native'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {AppBskyModerationDefs, LabelGroupDefinition} from '@atproto/api'
|
import {AppBskyModerationDefs, LabelGroupDefinition} from '@atproto/api'
|
||||||
@@ -31,31 +31,37 @@ import * as Toast from '#/view/com/util/Toast'
|
|||||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
import {useModServicesDetailedInfoQuery} from '#/state/queries/modservice'
|
import {useModServicesDetailedInfoQuery} from '#/state/queries/modservice'
|
||||||
import {
|
import {
|
||||||
getLabelGroupsFromLabels,
|
|
||||||
getModerationServiceTitle,
|
getModerationServiceTitle,
|
||||||
useConfigurableLabelGroups,
|
useConfigurableContentLabelGroups,
|
||||||
|
useConfigurableProfileLabelGroups,
|
||||||
|
getLabelGroupToLabelerMap,
|
||||||
} from '#/lib/moderation'
|
} from '#/lib/moderation'
|
||||||
|
import {DMCA_LINK} from '#/components/dialogs/ReportDialog/const'
|
||||||
|
import {Link} from '#/components/Link'
|
||||||
|
import {SquareArrowTopRight_Stroke2_Corner0_Rounded as SquareArrowTopRight} from '#/components/icons/SquareArrowTopRight'
|
||||||
|
// import {getAgent} from '#/state/session'
|
||||||
|
|
||||||
|
export type ReportDialogLabelIds = LabelGroupDefinition['id'] | 'other'
|
||||||
export type ReportDialogProps =
|
export type ReportDialogProps =
|
||||||
| {
|
| {
|
||||||
type: 'post'
|
type: 'content'
|
||||||
uri: string
|
uri: string
|
||||||
cid: string
|
cid: string
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'user'
|
type: 'profile'
|
||||||
did: string
|
did: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function LabelGroupButton({
|
function LabelGroupButton({
|
||||||
labelGroup,
|
name,
|
||||||
|
description,
|
||||||
}: {
|
}: {
|
||||||
labelGroup: LabelGroupDefinition['id']
|
name: string
|
||||||
|
description: string
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {hovered, focused, pressed} = useButtonContext()
|
const {hovered, focused, pressed} = useButtonContext()
|
||||||
const labelGroupStrings = useLabelGroupStrings()
|
|
||||||
const groupInfoStrings = labelGroupStrings[labelGroup]
|
|
||||||
const interacted = hovered || focused || pressed
|
const interacted = hovered || focused || pressed
|
||||||
|
|
||||||
const styles = React.useMemo(() => {
|
const styles = React.useMemo(() => {
|
||||||
@@ -80,11 +86,9 @@ function LabelGroupButton({
|
|||||||
]}>
|
]}>
|
||||||
<View style={[a.flex_1, a.gap_xs]}>
|
<View style={[a.flex_1, a.gap_xs]}>
|
||||||
<Text style={[a.text_md, a.font_bold, t.atoms.text_contrast_medium]}>
|
<Text style={[a.text_md, a.font_bold, t.atoms.text_contrast_medium]}>
|
||||||
{groupInfoStrings.name}
|
{name}
|
||||||
</Text>
|
|
||||||
<Text style={[a.leading_tight, {maxWidth: 400}]}>
|
|
||||||
{groupInfoStrings.description}
|
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text style={[a.leading_tight, {maxWidth: 400}]}>{description}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
@@ -158,7 +162,7 @@ function SubmitViewLoader({
|
|||||||
}: {
|
}: {
|
||||||
children: (props: {
|
children: (props: {
|
||||||
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
|
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
|
||||||
labelGroupToModServiceMap: Record<LabelGroupDefinition['id'], string[]>
|
labelGroupToModServiceMap: ReturnType<typeof getLabelGroupToLabelerMap>
|
||||||
}) => React.ReactNode
|
}) => React.ReactNode
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
@@ -175,25 +179,7 @@ function SubmitViewLoader({
|
|||||||
})
|
})
|
||||||
const labelGroupToModServiceMap = React.useMemo(() => {
|
const labelGroupToModServiceMap = React.useMemo(() => {
|
||||||
if (!modservices) return {}
|
if (!modservices) return {}
|
||||||
|
return getLabelGroupToLabelerMap(modservices)
|
||||||
const groups: Partial<
|
|
||||||
Record<
|
|
||||||
LabelGroupDefinition['id'],
|
|
||||||
AppBskyModerationDefs.ModServiceViewDetailed[]
|
|
||||||
>
|
|
||||||
> = {}
|
|
||||||
|
|
||||||
for (const modservice of modservices) {
|
|
||||||
const labelGroups = getLabelGroupsFromLabels(
|
|
||||||
modservice.policies.labelValues,
|
|
||||||
)
|
|
||||||
for (const group of labelGroups) {
|
|
||||||
const g = (groups[group.id] = groups[group.id] || [])
|
|
||||||
g.push(modservice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return groups
|
|
||||||
}, [modservices])
|
}, [modservices])
|
||||||
|
|
||||||
const isLoading = isPreferencesLoading || isModServicesLoading
|
const isLoading = isPreferencesLoading || isModServicesLoading
|
||||||
@@ -206,27 +192,24 @@ function SubmitViewLoader({
|
|||||||
) : error || !(preferences && modservices) ? null : ( // TODO
|
) : error || !(preferences && modservices) ? null : ( // TODO
|
||||||
children({
|
children({
|
||||||
labelers: modservices,
|
labelers: modservices,
|
||||||
// TODO mismatched types
|
|
||||||
// @ts-ignore
|
|
||||||
labelGroupToModServiceMap,
|
labelGroupToModServiceMap,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SubmitView({
|
function SubmitView({
|
||||||
|
params,
|
||||||
selectedLabelGroup,
|
selectedLabelGroup,
|
||||||
goBack,
|
goBack,
|
||||||
onSubmitComplete,
|
onSubmitComplete,
|
||||||
labelGroupToModServiceMap,
|
labelGroupToModServiceMap,
|
||||||
}: {
|
}: {
|
||||||
selectedLabelGroup: LabelGroupDefinition['id']
|
params: ReportDialogProps
|
||||||
|
selectedLabelGroup: ReportDialogLabelIds
|
||||||
goBack: () => void
|
goBack: () => void
|
||||||
onSubmitComplete: () => void
|
onSubmitComplete: () => void
|
||||||
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
|
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
|
||||||
labelGroupToModServiceMap: Record<
|
labelGroupToModServiceMap: ReturnType<typeof getLabelGroupToLabelerMap>
|
||||||
LabelGroupDefinition['id'],
|
|
||||||
AppBskyModerationDefs.ModServiceViewDetailed[]
|
|
||||||
>
|
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
@@ -240,12 +223,28 @@ function SubmitView({
|
|||||||
const submit = React.useCallback(async () => {
|
const submit = React.useCallback(async () => {
|
||||||
setSubmitting(true)
|
setSubmitting(true)
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
|
|
||||||
|
const $type =
|
||||||
|
params.type === 'content'
|
||||||
|
? 'com.atproto.repo.strongRef'
|
||||||
|
: 'com.atproto.admin.defs#repoRef'
|
||||||
|
const report = {
|
||||||
|
reasonType: selectedLabelGroup, // TODO map to reasons
|
||||||
|
subject: {
|
||||||
|
$type,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
reason: details,
|
||||||
|
}
|
||||||
|
console.log(report)
|
||||||
|
// await getAgent().createModerationReport(report)
|
||||||
|
|
||||||
setSubmitting(false)
|
setSubmitting(false)
|
||||||
|
|
||||||
Toast.show(`Thank you. Your report has been sent.`)
|
Toast.show(`Thank you. Your report has been sent.`)
|
||||||
|
|
||||||
onSubmitComplete()
|
onSubmitComplete()
|
||||||
}, [onSubmitComplete])
|
}, [params, details, selectedLabelGroup, onSubmitComplete])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.gap_2xl]}>
|
<View style={[a.gap_2xl]}>
|
||||||
@@ -364,31 +363,30 @@ function SubmitView({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO copyright link out to DMCA
|
|
||||||
* TODO add "other" option
|
|
||||||
*/
|
|
||||||
export function ReportDialog({
|
export function ReportDialog({
|
||||||
params,
|
params,
|
||||||
cleanup,
|
cleanup,
|
||||||
}: GlobalDialogProps<ReportDialogProps>) {
|
}: GlobalDialogProps<ReportDialogProps>) {
|
||||||
|
// REQUIRED CLEANUP
|
||||||
|
const onClose = React.useCallback(() => cleanup(), [cleanup])
|
||||||
|
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const control = Dialog.useDialogControl()
|
const control = Dialog.useDialogControl()
|
||||||
const [selectedLabelGroup, setSelectedLabelGroup] = React.useState<
|
const [selectedLabelGroup, setSelectedLabelGroup] = React.useState<
|
||||||
LabelGroupDefinition['id'] | undefined
|
ReportDialogLabelIds | undefined
|
||||||
>()
|
>()
|
||||||
const labelGroupStrings = useLabelGroupStrings()
|
const labelGroupStrings = useLabelGroupStrings()
|
||||||
|
const contentGroups = useConfigurableContentLabelGroups()
|
||||||
// REQUIRED CLEANUP
|
const profileGroups = useConfigurableProfileLabelGroups()
|
||||||
const onClose = React.useCallback(() => cleanup(), [cleanup])
|
const groups = params.type === 'content' ? contentGroups : profileGroups
|
||||||
|
|
||||||
const i18n = React.useMemo(() => {
|
const i18n = React.useMemo(() => {
|
||||||
let title = _(msg`Report this post`)
|
let title = _(msg`Report this post`)
|
||||||
let description = _(msg`Why should this post be reviewed?`)
|
let description = _(msg`Why should this post be reviewed?`)
|
||||||
|
|
||||||
if (params.type === 'user') {
|
if (params.type === 'profile') {
|
||||||
title = _(msg`Report this user`)
|
title = _(msg`Report this user`)
|
||||||
description = _(msg`Why should this user be reviewed?`)
|
description = _(msg`Why should this user be reviewed?`)
|
||||||
}
|
}
|
||||||
@@ -399,7 +397,16 @@ export function ReportDialog({
|
|||||||
}
|
}
|
||||||
}, [_, params.type])
|
}, [_, params.type])
|
||||||
|
|
||||||
const groups = useConfigurableLabelGroups()
|
const next = React.useCallback(
|
||||||
|
(group: ReportDialogLabelIds | 'copyright') => {
|
||||||
|
if (group === 'copyright') {
|
||||||
|
Linking.openURL(DMCA_LINK)
|
||||||
|
} else {
|
||||||
|
setSelectedLabelGroup(group)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[setSelectedLabelGroup],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.Outer
|
<Dialog.Outer
|
||||||
@@ -417,10 +424,9 @@ export function ReportDialog({
|
|||||||
{selectedLabelGroup ? (
|
{selectedLabelGroup ? (
|
||||||
<SubmitViewLoader>
|
<SubmitViewLoader>
|
||||||
{props => (
|
{props => (
|
||||||
// TODO same types mismatch
|
|
||||||
// @ts-ignore
|
|
||||||
<SubmitView
|
<SubmitView
|
||||||
{...props}
|
{...props}
|
||||||
|
params={params}
|
||||||
selectedLabelGroup={selectedLabelGroup}
|
selectedLabelGroup={selectedLabelGroup}
|
||||||
goBack={() => setSelectedLabelGroup(undefined)}
|
goBack={() => setSelectedLabelGroup(undefined)}
|
||||||
onSubmitComplete={control.close}
|
onSubmitComplete={control.close}
|
||||||
@@ -440,16 +446,59 @@ export function ReportDialog({
|
|||||||
|
|
||||||
<View style={[a.gap_sm, {marginHorizontal: a.p_md.padding * -1}]}>
|
<View style={[a.gap_sm, {marginHorizontal: a.p_md.padding * -1}]}>
|
||||||
{groups.map(def => {
|
{groups.map(def => {
|
||||||
const groupStrings = labelGroupStrings[def.id]
|
const strings = labelGroupStrings[def.id]
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
key={def.id}
|
key={def.id}
|
||||||
label={_(msg`Create report for ${groupStrings.name}`)}
|
label={_(msg`Create report for ${strings.name}`)}
|
||||||
onPress={() => setSelectedLabelGroup(def.id)}>
|
onPress={() => next(def.id)}>
|
||||||
<LabelGroupButton labelGroup={def.id} />
|
<LabelGroupButton
|
||||||
|
name={strings.name}
|
||||||
|
description={strings.description}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={_(msg`Create report for other reasons`)}
|
||||||
|
onPress={() => next('other')}>
|
||||||
|
<LabelGroupButton
|
||||||
|
name="Other"
|
||||||
|
description="An issue not covered by another option"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{params.type === 'content' && (
|
||||||
|
<View style={[a.pt_md, a.px_md]}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.justify_between,
|
||||||
|
a.gap_md,
|
||||||
|
a.p_md,
|
||||||
|
a.pl_lg,
|
||||||
|
a.rounded_md,
|
||||||
|
t.atoms.bg_contrast_900,
|
||||||
|
]}>
|
||||||
|
<Text style={[t.atoms.text_inverted, a.italic]}>
|
||||||
|
Need to report a copyright violation?
|
||||||
|
</Text>
|
||||||
|
<Link
|
||||||
|
to={DMCA_LINK}
|
||||||
|
label={_(
|
||||||
|
msg`View details for reporting a copyright violation`,
|
||||||
|
)}
|
||||||
|
size="small"
|
||||||
|
variant="solid"
|
||||||
|
color="secondary">
|
||||||
|
<ButtonText>View details</ButtonText>
|
||||||
|
<ButtonIcon position="right" icon={SquareArrowTopRight} />
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import {createSinglePathSVG} from './TEMPLATE'
|
||||||
|
|
||||||
|
export const SquareArrowTopRight_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||||
|
path: 'M14 5a1 1 0 1 1 0-2h6a1 1 0 0 1 1 1v6a1 1 0 1 1-2 0V6.414l-7.293 7.293a1 1 0 0 1-1.414-1.414L17.586 5H14ZM3 6a1 1 0 0 1 1-1h5a1 1 0 0 1 0 2H5v12h12v-4a1 1 0 1 1 2 0v5a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6Z',
|
||||||
|
})
|
||||||
+62
-1
@@ -1,5 +1,11 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {ModerationCause, LABEL_GROUPS, LabelGroupDefinition} from '@atproto/api'
|
import {
|
||||||
|
ModerationCause,
|
||||||
|
LABEL_GROUPS,
|
||||||
|
LabelGroupDefinition,
|
||||||
|
AppBskyModerationDefs,
|
||||||
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
|
|
||||||
@@ -39,6 +45,33 @@ export function useConfigurableLabelGroups() {
|
|||||||
return React.useMemo(() => getConfigurableLabelGroups(), [])
|
return React.useMemo(() => getConfigurableLabelGroups(), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useConfigurableContentLabelGroups() {
|
||||||
|
return React.useMemo(() => {
|
||||||
|
const groups = getConfigurableLabelGroups()
|
||||||
|
return groups.filter(group => {
|
||||||
|
return group.labels.every(l => l.targets.includes('content'))
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useConfigurableProfileLabelGroups() {
|
||||||
|
return React.useMemo(() => {
|
||||||
|
const groups = getConfigurableLabelGroups()
|
||||||
|
return groups.filter(group => {
|
||||||
|
return group.labels.every(l => l.targets.includes('profile'))
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useConfigurableAccountLabelGroups() {
|
||||||
|
return React.useMemo(() => {
|
||||||
|
const groups = getConfigurableLabelGroups()
|
||||||
|
return groups.filter(group => {
|
||||||
|
return group.labels.every(l => l.targets.includes('account'))
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
|
|
||||||
export function getModerationServiceTitle({
|
export function getModerationServiceTitle({
|
||||||
displayName,
|
displayName,
|
||||||
handle,
|
handle,
|
||||||
@@ -50,3 +83,31 @@ export function getModerationServiceTitle({
|
|||||||
? sanitizeDisplayName(displayName)
|
? sanitizeDisplayName(displayName)
|
||||||
: sanitizeHandle(handle, '@')
|
: sanitizeHandle(handle, '@')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getLabelGroupToLabelerMap(
|
||||||
|
labelers: AppBskyModerationDefs.ModServiceViewDetailed[],
|
||||||
|
) {
|
||||||
|
if (!labelers) return {}
|
||||||
|
|
||||||
|
const groups: Partial<
|
||||||
|
Record<
|
||||||
|
LabelGroupDefinition['id'] | 'other',
|
||||||
|
AppBskyModerationDefs.ModServiceViewDetailed[]
|
||||||
|
>
|
||||||
|
> = {
|
||||||
|
// `other` reports go to all labelers TODO confirm this
|
||||||
|
other: labelers,
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const modservice of labelers) {
|
||||||
|
const labelGroups = getLabelGroupsFromLabels(
|
||||||
|
modservice.policies.labelValues,
|
||||||
|
)
|
||||||
|
for (const group of labelGroups) {
|
||||||
|
const g = (groups[group.id] = groups[group.id] || [])
|
||||||
|
g.push(modservice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {useMemo} from 'react'
|
import {useMemo} from 'react'
|
||||||
|
|
||||||
export type LabelGroupStrings = Record<
|
export type LabelGroupStrings = Record<
|
||||||
keyof typeof LABEL_GROUPS,
|
keyof typeof LABEL_GROUPS | 'other',
|
||||||
{name: string; description: string}
|
{name: string; description: string}
|
||||||
>
|
>
|
||||||
|
|
||||||
@@ -116,6 +116,10 @@ export function useLabelGroupStrings(): LabelGroupStrings {
|
|||||||
msg`Helpful annotations to explain intent, such as satire or parody.`,
|
msg`Helpful annotations to explain intent, such as satire or parody.`,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
other: {
|
||||||
|
name: _(msg`Other`),
|
||||||
|
description: _(msg`Other content not covered by the other categories.`),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
[_],
|
[_],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ function LabelerToggle({
|
|||||||
preferences: UsePreferencesQueryResponse
|
preferences: UsePreferencesQueryResponse
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {mutateAsync, variables, reset} =
|
const {mutateAsync, variables} = useModServiceLabelGroupEnableMutation()
|
||||||
useModServiceLabelGroupEnableMutation()
|
|
||||||
|
|
||||||
const modservicePreferences = preferences.moderationOpts.mods.find(
|
const modservicePreferences = preferences.moderationOpts.mods.find(
|
||||||
({did}) => did === labeler.creator.did,
|
({did}) => did === labeler.creator.did,
|
||||||
@@ -46,12 +45,11 @@ function LabelerToggle({
|
|||||||
group: labelGroup,
|
group: labelGroup,
|
||||||
enabled: !enabled,
|
enabled: !enabled,
|
||||||
})
|
})
|
||||||
reset() // Important: clears query `variables`
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
// TODO
|
// TODO
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
}, [mutateAsync, enabled, modservicePreferences, labelGroup, reset])
|
}, [mutateAsync, enabled, modservicePreferences, labelGroup])
|
||||||
return (
|
return (
|
||||||
<Toggle.Item
|
<Toggle.Item
|
||||||
name={labeler.creator.did}
|
name={labeler.creator.did}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
import {msg} from '@lingui/macro'
|
||||||
// import {msg} from '@lingui/macro'
|
// import {msg} from '@lingui/macro'
|
||||||
import {LABEL_GROUPS} from '@atproto/api'
|
import {LABEL_GROUPS} from '@atproto/api'
|
||||||
// TODO
|
// TODO
|
||||||
@@ -24,7 +25,7 @@ export function PreferenceRow({
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const labelGroupStrings = useLabelGroupStrings()
|
const labelGroupStrings = useLabelGroupStrings()
|
||||||
const groupInfoStrings = labelGroupStrings[labelGroup]
|
const groupInfoStrings = labelGroupStrings[labelGroup]
|
||||||
const {mutateAsync, variables, reset} = useModServiceLabelGroupEnableMutation()
|
const {mutateAsync, variables} = useModServiceLabelGroupEnableMutation()
|
||||||
const enabled =
|
const enabled =
|
||||||
variables?.enabled ??
|
variables?.enabled ??
|
||||||
!modservicePreferences?.disabledLabelGroups?.includes(labelGroup)
|
!modservicePreferences?.disabledLabelGroups?.includes(labelGroup)
|
||||||
@@ -37,12 +38,11 @@ export function PreferenceRow({
|
|||||||
group: labelGroup,
|
group: labelGroup,
|
||||||
enabled: !enabled,
|
enabled: !enabled,
|
||||||
})
|
})
|
||||||
reset() // Important: clears query `variables`
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
// TODO
|
// TODO
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
}, [mutateAsync, enabled, modservicePreferences, labelGroup, reset])
|
}, [mutateAsync, enabled, modservicePreferences, labelGroup])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
@@ -65,7 +65,7 @@ export function PreferenceRow({
|
|||||||
name="enable"
|
name="enable"
|
||||||
value={enabled}
|
value={enabled}
|
||||||
onChange={onToggleEnabled}
|
onChange={onToggleEnabled}
|
||||||
label="Enable">
|
label={_(msg`Enable`)}>
|
||||||
<Toggle.Label>{enabled ? 'Enabled' : 'Disabled'}</Toggle.Label>
|
<Toggle.Label>{enabled ? 'Enabled' : 'Disabled'}</Toggle.Label>
|
||||||
<Toggle.Switch />
|
<Toggle.Switch />
|
||||||
</Toggle.Item>
|
</Toggle.Item>
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ import {LabelInfo} from '../util/moderation/LabelInfo'
|
|||||||
import {useProfileShadow} from 'state/cache/profile-shadow'
|
import {useProfileShadow} from 'state/cache/profile-shadow'
|
||||||
import * as ModerationServiceCard from '#/components/ModerationServiceCard'
|
import * as ModerationServiceCard from '#/components/ModerationServiceCard'
|
||||||
import {getModerationServiceTitle} from '#/lib/moderation'
|
import {getModerationServiceTitle} from '#/lib/moderation'
|
||||||
|
import {useOpenGlobalDialog} from '#/components/dialogs'
|
||||||
|
import {ReportDialog} from '#/components/dialogs/ReportDialog'
|
||||||
|
import {NEW_REPORT_DIALOG_ENABLED} from '#/lib/build-flags'
|
||||||
|
|
||||||
import {useTheme} from '#/alf'
|
import {useTheme} from '#/alf'
|
||||||
|
|
||||||
@@ -119,6 +122,7 @@ let ProfileHeader = ({
|
|||||||
() => moderateProfile(profile, moderationOpts),
|
() => moderateProfile(profile, moderationOpts),
|
||||||
[profile, moderationOpts],
|
[profile, moderationOpts],
|
||||||
)
|
)
|
||||||
|
const openDialog = useOpenGlobalDialog()
|
||||||
|
|
||||||
const invalidateProfileQuery = React.useCallback(() => {
|
const invalidateProfileQuery = React.useCallback(() => {
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
@@ -280,11 +284,15 @@ let ProfileHeader = ({
|
|||||||
|
|
||||||
const onPressReportAccount = React.useCallback(() => {
|
const onPressReportAccount = React.useCallback(() => {
|
||||||
track('ProfileHeader:ReportAccountButtonClicked')
|
track('ProfileHeader:ReportAccountButtonClicked')
|
||||||
openModal({
|
if (NEW_REPORT_DIALOG_ENABLED) {
|
||||||
name: 'report',
|
openDialog(ReportDialog, {type: 'profile', did: profile.did})
|
||||||
did: profile.did,
|
} else {
|
||||||
})
|
openModal({
|
||||||
}, [track, openModal, profile])
|
name: 'report',
|
||||||
|
did: profile.did,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [track, openModal, profile, openDialog])
|
||||||
|
|
||||||
const isMe = React.useMemo(
|
const isMe = React.useMemo(
|
||||||
() => currentAccount?.did === profile.did,
|
() => currentAccount?.did === profile.did,
|
||||||
|
|||||||
@@ -214,7 +214,11 @@ let PostDropdownBtn = ({
|
|||||||
label: _(msg`Report post`),
|
label: _(msg`Report post`),
|
||||||
onPress() {
|
onPress() {
|
||||||
if (NEW_REPORT_DIALOG_ENABLED) {
|
if (NEW_REPORT_DIALOG_ENABLED) {
|
||||||
openDialog(ReportDialog, {type: 'post', uri: postUri, cid: postCid})
|
openDialog(ReportDialog, {
|
||||||
|
type: 'content',
|
||||||
|
uri: postUri,
|
||||||
|
cid: postCid,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
openModal({
|
openModal({
|
||||||
name: 'report',
|
name: 'report',
|
||||||
|
|||||||
Reference in New Issue
Block a user