Add report dialog to starter pack screen (#4546)
This commit is contained in:
@@ -55,6 +55,9 @@ export function SelectReportOptionView({
|
|||||||
} else if (props.params.type === 'feedgen') {
|
} else if (props.params.type === 'feedgen') {
|
||||||
title = _(msg`Report this feed`)
|
title = _(msg`Report this feed`)
|
||||||
description = _(msg`Why should this feed be reviewed?`)
|
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') {
|
} else if (props.params.type === 'convoMessage') {
|
||||||
title = _(msg`Report this message`)
|
title = _(msg`Report this message`)
|
||||||
description = _(msg`Why should this message be reviewed?`)
|
description = _(msg`Why should this message be reviewed?`)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export type ReportDialogProps = {
|
|||||||
control: Dialog.DialogOuterProps['control']
|
control: Dialog.DialogOuterProps['control']
|
||||||
params:
|
params:
|
||||||
| {
|
| {
|
||||||
type: 'post' | 'list' | 'feedgen' | 'other'
|
type: 'post' | 'list' | 'feedgen' | 'starterpack' | 'other'
|
||||||
uri: string
|
uri: string
|
||||||
cid: string
|
cid: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ export const ProfilesList = React.forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
const bottomBarOffset = useBottomBarOffset(20)
|
const bottomBarOffset = useBottomBarOffset(20)
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
const {data} = useListMembersQuery(listUri)
|
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||||
|
const {data, refetch} = useListMembersQuery(listUri)
|
||||||
const profiles = data?.pages.flatMap(p => p.items.map(i => i.subject))
|
const profiles = data?.pages.flatMap(p => p.items.map(i => i.subject))
|
||||||
const isOwn = new AtUri(listUri).host === currentAccount?.did
|
const isOwn = new AtUri(listUri).host === currentAccount?.did
|
||||||
|
|
||||||
@@ -76,6 +77,12 @@ export const ProfilesList = React.forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
}
|
}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
desktopFixedHeight
|
desktopFixedHeight
|
||||||
|
refreshing={isPTRing}
|
||||||
|
onRefresh={async () => {
|
||||||
|
setIsPTRing(true)
|
||||||
|
await refetch()
|
||||||
|
setIsPTRing(false)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ interface ReportOptions {
|
|||||||
account: ReportOption[]
|
account: ReportOption[]
|
||||||
post: ReportOption[]
|
post: ReportOption[]
|
||||||
list: ReportOption[]
|
list: ReportOption[]
|
||||||
|
starterpack: ReportOption[]
|
||||||
feedgen: ReportOption[]
|
feedgen: ReportOption[]
|
||||||
other: ReportOption[]
|
other: ReportOption[]
|
||||||
convoMessage: ReportOption[]
|
convoMessage: ReportOption[]
|
||||||
@@ -94,6 +95,14 @@ export function useReportOptions(): ReportOptions {
|
|||||||
},
|
},
|
||||||
...common,
|
...common,
|
||||||
],
|
],
|
||||||
|
starterpack: [
|
||||||
|
{
|
||||||
|
reason: ComAtprotoModerationDefs.REASONVIOLATION,
|
||||||
|
title: _(msg`Name or Description Violates Community Standards`),
|
||||||
|
description: _(msg`Terms used violate community standards`),
|
||||||
|
},
|
||||||
|
...common,
|
||||||
|
],
|
||||||
feedgen: [
|
feedgen: [
|
||||||
{
|
{
|
||||||
reason: ComAtprotoModerationDefs.REASONVIOLATION,
|
reason: ComAtprotoModerationDefs.REASONVIOLATION,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {useNavigation} from '@react-navigation/native'
|
|||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
|
import {HITSLOP_20} from 'lib/constants'
|
||||||
import {makeProfileLink, makeStarterPackLink} from 'lib/routes/links'
|
import {makeProfileLink, makeStarterPackLink} from 'lib/routes/links'
|
||||||
import {CommonNavigatorParams, NavigationProp} from 'lib/routes/types'
|
import {CommonNavigatorParams, NavigationProp} from 'lib/routes/types'
|
||||||
import {shareUrl} from 'lib/sharing'
|
import {shareUrl} from 'lib/sharing'
|
||||||
@@ -23,12 +24,15 @@ import {CenteredView} from 'view/com/util/Views'
|
|||||||
import {bulkWriteFollows} from '#/screens/Onboarding/util'
|
import {bulkWriteFollows} from '#/screens/Onboarding/util'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import {useDialogControl} from '#/components/Dialog'
|
import {DialogControlProps, useDialogControl} from '#/components/Dialog'
|
||||||
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox'
|
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox'
|
||||||
|
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
|
||||||
|
import {DotGrid_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid'
|
||||||
import {QrCode_Stroke2_Corner0_Rounded as QrCode} from '#/components/icons/QrCode'
|
import {QrCode_Stroke2_Corner0_Rounded as QrCode} from '#/components/icons/QrCode'
|
||||||
import {ListMaybePlaceholder} from '#/components/Lists'
|
import {ListMaybePlaceholder} from '#/components/Lists'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
|
import {ReportDialog, useReportDialogControl} from '#/components/ReportDialog'
|
||||||
import {FeedsList} from '#/components/StarterPack/Main/FeedsList'
|
import {FeedsList} from '#/components/StarterPack/Main/FeedsList'
|
||||||
import {ProfilesList} from '#/components/StarterPack/Main/ProfilesList'
|
import {ProfilesList} from '#/components/StarterPack/Main/ProfilesList'
|
||||||
import {QrCodeDialog} from '#/components/StarterPack/QrCodeDialog'
|
import {QrCodeDialog} from '#/components/StarterPack/QrCodeDialog'
|
||||||
@@ -126,6 +130,7 @@ function Header({
|
|||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const qrCodeDialogControl = useDialogControl()
|
const qrCodeDialogControl = useDialogControl()
|
||||||
|
const reportDialogControl = useReportDialogControl()
|
||||||
|
|
||||||
const [isProcessing, setIsProcessing] = React.useState(false)
|
const [isProcessing, setIsProcessing] = React.useState(false)
|
||||||
|
|
||||||
@@ -177,10 +182,90 @@ function Header({
|
|||||||
avatar={undefined}
|
avatar={undefined}
|
||||||
creator={creator}
|
creator={creator}
|
||||||
avatarType="starter-pack">
|
avatarType="starter-pack">
|
||||||
<View style={[a.flex_row, a.gap_sm]}>
|
<View style={[a.gap_sm, isOwn ? a.flex_row_reverse : a.flex_row]}>
|
||||||
|
{isOwn ? (
|
||||||
|
<Button
|
||||||
|
label={_(msg`Edit`)}
|
||||||
|
variant="solid"
|
||||||
|
color="secondary"
|
||||||
|
size="small"
|
||||||
|
onPress={() => navigation.navigate('StarterPackEdit', {rkey})}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Edit</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
label={_(msg`Follow all`)}
|
||||||
|
variant="solid"
|
||||||
|
color="primary"
|
||||||
|
size="small"
|
||||||
|
disabled={isProcessing}
|
||||||
|
onPress={onFollowAll}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Follow all</Trans>
|
||||||
|
{isProcessing && <Loader size="xs" />}
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Dropdown
|
||||||
|
name={name}
|
||||||
|
rkey={rkey}
|
||||||
|
starterPack={starterPack}
|
||||||
|
qrCodeDialogControl={qrCodeDialogControl}
|
||||||
|
reportDialogControl={reportDialogControl}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</ProfileSubpageHeader>
|
||||||
|
<View style={[a.px_md, a.py_lg, a.gap_md]}>
|
||||||
|
<Text style={[a.text_md]}>{record.description}</Text>
|
||||||
|
{starterPack.joinedWeekCount && starterPack.joinedWeekCount >= 25 ? (
|
||||||
|
<Text style={[a.font_bold, a.text_md, t.atoms.text_contrast_medium]}>
|
||||||
|
<Trans>
|
||||||
|
{starterPack.joinedAllTimeCount || 0} people have used this
|
||||||
|
starter pack!
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
<QrCodeDialog control={qrCodeDialogControl} starterPack={starterPack} />
|
||||||
|
<ReportDialog
|
||||||
|
control={reportDialogControl}
|
||||||
|
params={{
|
||||||
|
type: 'starterpack',
|
||||||
|
uri: starterPack.list!.uri,
|
||||||
|
cid: starterPack.list!.cid,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Dropdown({
|
||||||
|
name,
|
||||||
|
rkey,
|
||||||
|
starterPack,
|
||||||
|
qrCodeDialogControl,
|
||||||
|
reportDialogControl,
|
||||||
|
}: {
|
||||||
|
name: string
|
||||||
|
rkey: string
|
||||||
|
starterPack: AppBskyGraphDefs.StarterPackView
|
||||||
|
qrCodeDialogControl: DialogControlProps
|
||||||
|
reportDialogControl: DialogControlProps
|
||||||
|
}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const t = useTheme()
|
||||||
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
|
const isOwn = starterPack.creator.did === currentAccount?.did
|
||||||
|
|
||||||
|
return (
|
||||||
<Menu.Root>
|
<Menu.Root>
|
||||||
<Menu.Trigger label={_(msg`Repost or quote post`)}>
|
<Menu.Trigger label={_(msg`Repost or quote post`)}>
|
||||||
{({props, state}) => (
|
{({props, state}) => (
|
||||||
|
<>
|
||||||
|
{isOwn ? (
|
||||||
<Pressable
|
<Pressable
|
||||||
style={[
|
style={[
|
||||||
a.px_lg,
|
a.px_lg,
|
||||||
@@ -212,6 +297,23 @@ function Header({
|
|||||||
<Trans>Share</Trans>
|
<Trans>Share</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
) : (
|
||||||
|
<Pressable
|
||||||
|
{...props}
|
||||||
|
hitSlop={HITSLOP_20}
|
||||||
|
style={[
|
||||||
|
a.justify_center,
|
||||||
|
a.align_center,
|
||||||
|
a.rounded_full,
|
||||||
|
{height: 36, width: 36},
|
||||||
|
t.atoms.bg_contrast_50,
|
||||||
|
(state.hovered || state.pressed) && [t.atoms.bg_contrast_100],
|
||||||
|
]}
|
||||||
|
testID="headerDropdownBtn">
|
||||||
|
<Ellipsis size="lg" fill={t.atoms.text_contrast_medium.color} />
|
||||||
|
</Pressable>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</Menu.Trigger>
|
</Menu.Trigger>
|
||||||
<Menu.Outer style={{minWidth: 170}}>
|
<Menu.Outer style={{minWidth: 170}}>
|
||||||
@@ -241,47 +343,17 @@ function Header({
|
|||||||
<Menu.ItemIcon icon={QrCode} position="right" />
|
<Menu.ItemIcon icon={QrCode} position="right" />
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu.Group>
|
</Menu.Group>
|
||||||
|
{!isOwn && (
|
||||||
|
<Menu.Item
|
||||||
|
label={_(msg`Report starter pack`)}
|
||||||
|
onPress={reportDialogControl.open}>
|
||||||
|
<Menu.ItemText>
|
||||||
|
<Trans>Report starter pack</Trans>
|
||||||
|
</Menu.ItemText>
|
||||||
|
<Menu.ItemIcon icon={CircleInfo} position="right" />
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
</Menu.Outer>
|
</Menu.Outer>
|
||||||
</Menu.Root>
|
</Menu.Root>
|
||||||
{isOwn ? (
|
|
||||||
<Button
|
|
||||||
label={_(msg`Edit`)}
|
|
||||||
variant="solid"
|
|
||||||
color="secondary"
|
|
||||||
size="small"
|
|
||||||
onPress={() => navigation.navigate('StarterPackEdit', {rkey})}>
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>Edit</Trans>
|
|
||||||
</ButtonText>
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
label={_(msg`Follow all`)}
|
|
||||||
variant="solid"
|
|
||||||
color="primary"
|
|
||||||
size="small"
|
|
||||||
disabled={isProcessing}
|
|
||||||
onPress={onFollowAll}>
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>Follow all</Trans>
|
|
||||||
{isProcessing && <Loader size="xs" />}
|
|
||||||
</ButtonText>
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</ProfileSubpageHeader>
|
|
||||||
<View style={[a.px_md, a.py_lg, a.gap_md]}>
|
|
||||||
<Text style={[a.text_md]}>{record.description}</Text>
|
|
||||||
{starterPack.joinedWeekCount && starterPack.joinedWeekCount >= 25 ? (
|
|
||||||
<Text style={[a.font_bold, a.text_md, t.atoms.text_contrast_medium]}>
|
|
||||||
<Trans>
|
|
||||||
{starterPack.joinedAllTimeCount || 0} people have used this
|
|
||||||
starter pack!
|
|
||||||
</Trans>
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
</View>
|
|
||||||
<QrCodeDialog control={qrCodeDialogControl} starterPack={starterPack} />
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user