Unify label pills (#4676)
* New label pills * Fix type errors, add default case * Remove negative margin, only works in some places * Fix alignment edge case * Add a bit of padding --------- Co-authored-by: Dan Abramov <dan.abramov@gmail.com>zio/stable
parent
c133661768
commit
14c2d75d49
|
@ -0,0 +1,169 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {BSKY_LABELER_DID, ModerationCause} from '@atproto/api'
|
||||||
|
import {Trans} from '@lingui/macro'
|
||||||
|
|
||||||
|
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
|
||||||
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
|
import {atoms as a, useTheme, ViewStyleProp} from '#/alf'
|
||||||
|
import {Button} from '#/components/Button'
|
||||||
|
import {
|
||||||
|
ModerationDetailsDialog,
|
||||||
|
useModerationDetailsDialogControl,
|
||||||
|
} from '#/components/moderation/ModerationDetailsDialog'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
|
export type CommonProps = {
|
||||||
|
size?: 'sm' | 'lg'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Row({
|
||||||
|
children,
|
||||||
|
style,
|
||||||
|
size = 'sm',
|
||||||
|
}: {children: React.ReactNode | React.ReactNode[]} & CommonProps &
|
||||||
|
ViewStyleProp) {
|
||||||
|
const styles = React.useMemo(() => {
|
||||||
|
switch (size) {
|
||||||
|
case 'lg':
|
||||||
|
return [{gap: 5}]
|
||||||
|
case 'sm':
|
||||||
|
default:
|
||||||
|
return [{gap: 3}]
|
||||||
|
}
|
||||||
|
}, [size])
|
||||||
|
return (
|
||||||
|
<View style={[a.flex_row, a.flex_wrap, a.gap_xs, styles, style]}>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LabelProps = {
|
||||||
|
cause: ModerationCause
|
||||||
|
disableDetailsDialog?: boolean
|
||||||
|
noBg?: boolean
|
||||||
|
} & CommonProps
|
||||||
|
|
||||||
|
export function Label({
|
||||||
|
cause,
|
||||||
|
size = 'sm',
|
||||||
|
disableDetailsDialog,
|
||||||
|
noBg,
|
||||||
|
}: LabelProps) {
|
||||||
|
const t = useTheme()
|
||||||
|
const control = useModerationDetailsDialogControl()
|
||||||
|
const desc = useModerationCauseDescription(cause)
|
||||||
|
const isLabeler = Boolean(desc.sourceType && desc.sourceDid)
|
||||||
|
const isBlueskyLabel =
|
||||||
|
desc.sourceType === 'labeler' && desc.sourceDid === BSKY_LABELER_DID
|
||||||
|
|
||||||
|
const {outer, avi, text} = React.useMemo(() => {
|
||||||
|
switch (size) {
|
||||||
|
case 'lg': {
|
||||||
|
return {
|
||||||
|
outer: [
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
{
|
||||||
|
gap: 5,
|
||||||
|
paddingHorizontal: 5,
|
||||||
|
paddingVertical: 5,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
avi: 16,
|
||||||
|
text: [a.text_sm],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'sm':
|
||||||
|
default: {
|
||||||
|
return {
|
||||||
|
outer: [
|
||||||
|
!noBg && t.atoms.bg_contrast_25,
|
||||||
|
{
|
||||||
|
gap: 3,
|
||||||
|
paddingHorizontal: 3,
|
||||||
|
paddingVertical: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
avi: 12,
|
||||||
|
text: [a.text_xs],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [t, size, noBg])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
disabled={disableDetailsDialog}
|
||||||
|
label={desc.name}
|
||||||
|
onPress={e => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
control.open()
|
||||||
|
}}>
|
||||||
|
{({hovered, pressed}) => (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.rounded_full,
|
||||||
|
outer,
|
||||||
|
(hovered || pressed) && t.atoms.bg_contrast_50,
|
||||||
|
]}>
|
||||||
|
{isBlueskyLabel || !isLabeler ? (
|
||||||
|
<desc.icon
|
||||||
|
width={avi}
|
||||||
|
fill={t.atoms.text_contrast_medium.color}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<UserAvatar avatar={desc.sourceAvi} size={avi} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
text,
|
||||||
|
a.font_semibold,
|
||||||
|
a.leading_tight,
|
||||||
|
t.atoms.text_contrast_medium,
|
||||||
|
{paddingRight: 3},
|
||||||
|
]}>
|
||||||
|
{desc.name}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{!disableDetailsDialog && (
|
||||||
|
<ModerationDetailsDialog control={control} modcause={cause} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FollowsYou({size = 'sm'}: CommonProps) {
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
const variantStyles = React.useMemo(() => {
|
||||||
|
switch (size) {
|
||||||
|
case 'sm':
|
||||||
|
case 'lg':
|
||||||
|
default:
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
paddingHorizontal: 6,
|
||||||
|
paddingVertical: 3,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, [size])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[variantStyles, a.justify_center, t.atoms.bg_contrast_25]}>
|
||||||
|
<Text style={[a.text_xs, a.leading_tight]}>
|
||||||
|
<Trans>Follows You</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
|
@ -29,10 +29,10 @@ import {
|
||||||
} from '#/components/KnownFollowers'
|
} from '#/components/KnownFollowers'
|
||||||
import {InlineLinkText, Link} from '#/components/Link'
|
import {InlineLinkText, Link} from '#/components/Link'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
|
import * as Pills from '#/components/Pills'
|
||||||
import {Portal} from '#/components/Portal'
|
import {Portal} from '#/components/Portal'
|
||||||
import {RichText} from '#/components/RichText'
|
import {RichText} from '#/components/RichText'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {ProfileLabel} from '../moderation/ProfileHeaderAlerts'
|
|
||||||
import {ProfileHoverCardProps} from './types'
|
import {ProfileHoverCardProps} from './types'
|
||||||
|
|
||||||
const floatingMiddlewares = [
|
const floatingMiddlewares = [
|
||||||
|
@ -476,8 +476,9 @@ function Inner({
|
||||||
{isBlockedUser && (
|
{isBlockedUser && (
|
||||||
<View style={[a.flex_row, a.flex_wrap, a.gap_xs]}>
|
<View style={[a.flex_row, a.flex_wrap, a.gap_xs]}>
|
||||||
{moderation.ui('profileView').alerts.map(cause => (
|
{moderation.ui('profileView').alerts.map(cause => (
|
||||||
<ProfileLabel
|
<Pills.Label
|
||||||
key={getModerationCauseKey(cause)}
|
key={getModerationCauseKey(cause)}
|
||||||
|
size="lg"
|
||||||
cause={cause}
|
cause={cause}
|
||||||
disableDetailsDialog
|
disableDetailsDialog
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -214,7 +214,7 @@ function HeaderReady({
|
||||||
]}>
|
]}>
|
||||||
<PostAlerts
|
<PostAlerts
|
||||||
modui={moderation.ui('contentList')}
|
modui={moderation.ui('contentList')}
|
||||||
size="large"
|
size="lg"
|
||||||
style={[a.pt_xs]}
|
style={[a.pt_xs]}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -165,9 +165,7 @@ export function ContentHider({
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
outer: {
|
outer: {},
|
||||||
overflow: 'hidden',
|
|
||||||
},
|
|
||||||
cover: {
|
cover: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
|
@ -1,25 +1,17 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleProp, View, ViewStyle} from 'react-native'
|
import {StyleProp, ViewStyle} from 'react-native'
|
||||||
import {BSKY_LABELER_DID, ModerationCause, ModerationUI} from '@atproto/api'
|
import {ModerationUI} from '@atproto/api'
|
||||||
|
|
||||||
import {getModerationCauseKey} from '#/lib/moderation'
|
import {getModerationCauseKey} from '#/lib/moderation'
|
||||||
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
|
import * as Pills from '#/components/Pills'
|
||||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
|
||||||
import {Button} from '#/components/Button'
|
|
||||||
import {
|
|
||||||
ModerationDetailsDialog,
|
|
||||||
useModerationDetailsDialogControl,
|
|
||||||
} from '#/components/moderation/ModerationDetailsDialog'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
|
|
||||||
export function PostAlerts({
|
export function PostAlerts({
|
||||||
modui,
|
modui,
|
||||||
size,
|
size = 'sm',
|
||||||
style,
|
style,
|
||||||
}: {
|
}: {
|
||||||
modui: ModerationUI
|
modui: ModerationUI
|
||||||
size?: 'medium' | 'large'
|
size?: Pills.CommonProps['size']
|
||||||
includeMute?: boolean
|
includeMute?: boolean
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}) {
|
}) {
|
||||||
|
@ -28,90 +20,23 @@ export function PostAlerts({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.flex_col, a.gap_xs, style]}>
|
<Pills.Row size={size} style={[size === 'sm' && {marginLeft: -3}, style]}>
|
||||||
<View style={[a.flex_row, a.flex_wrap, a.gap_xs]}>
|
|
||||||
{modui.alerts.map(cause => (
|
{modui.alerts.map(cause => (
|
||||||
<PostLabel
|
<Pills.Label
|
||||||
key={getModerationCauseKey(cause)}
|
key={getModerationCauseKey(cause)}
|
||||||
cause={cause}
|
cause={cause}
|
||||||
size={size}
|
size={size}
|
||||||
|
noBg={size === 'sm'}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{modui.informs.map(cause => (
|
{modui.informs.map(cause => (
|
||||||
<PostLabel
|
<Pills.Label
|
||||||
key={getModerationCauseKey(cause)}
|
key={getModerationCauseKey(cause)}
|
||||||
cause={cause}
|
cause={cause}
|
||||||
size={size}
|
size={size}
|
||||||
|
noBg={size === 'sm'}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</View>
|
</Pills.Row>
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function PostLabel({
|
|
||||||
cause,
|
|
||||||
size,
|
|
||||||
}: {
|
|
||||||
cause: ModerationCause
|
|
||||||
size?: 'medium' | 'large'
|
|
||||||
}) {
|
|
||||||
const control = useModerationDetailsDialogControl()
|
|
||||||
const desc = useModerationCauseDescription(cause)
|
|
||||||
const t = useTheme()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
label={desc.name}
|
|
||||||
onPress={e => {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
control.open()
|
|
||||||
}}>
|
|
||||||
{({hovered, pressed}) => (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.gap_xs,
|
|
||||||
a.rounded_sm,
|
|
||||||
hovered || pressed
|
|
||||||
? size === 'large'
|
|
||||||
? t.atoms.bg_contrast_50
|
|
||||||
: t.atoms.bg_contrast_25
|
|
||||||
: size === 'large'
|
|
||||||
? t.atoms.bg_contrast_25
|
|
||||||
: undefined,
|
|
||||||
size === 'large'
|
|
||||||
? {paddingLeft: 4, paddingRight: 6, paddingVertical: 2}
|
|
||||||
: {paddingRight: 4, paddingVertical: 1},
|
|
||||||
]}>
|
|
||||||
{desc.sourceType === 'labeler' &&
|
|
||||||
desc.sourceDid !== BSKY_LABELER_DID ? (
|
|
||||||
<UserAvatar
|
|
||||||
avatar={desc.sourceAvi}
|
|
||||||
size={size === 'large' ? 16 : 12}
|
|
||||||
type="labeler"
|
|
||||||
shape="circle"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<desc.icon size="sm" fill={t.atoms.text_contrast_medium.color} />
|
|
||||||
)}
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_left,
|
|
||||||
a.leading_snug,
|
|
||||||
size === 'large' ? {fontSize: 13} : a.text_xs,
|
|
||||||
size === 'large' ? t.atoms.text : t.atoms.text_contrast_high,
|
|
||||||
]}>
|
|
||||||
{desc.name}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<ModerationDetailsDialog control={control} modcause={cause} />
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleProp, View, ViewStyle} from 'react-native'
|
import {StyleProp, ViewStyle} from 'react-native'
|
||||||
import {
|
import {ModerationDecision} from '@atproto/api'
|
||||||
BSKY_LABELER_DID,
|
|
||||||
ModerationCause,
|
|
||||||
ModerationDecision,
|
|
||||||
} from '@atproto/api'
|
|
||||||
|
|
||||||
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
|
|
||||||
import {getModerationCauseKey} from 'lib/moderation'
|
import {getModerationCauseKey} from 'lib/moderation'
|
||||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
import * as Pills from '#/components/Pills'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
|
||||||
import {Button} from '#/components/Button'
|
|
||||||
import {
|
|
||||||
ModerationDetailsDialog,
|
|
||||||
useModerationDetailsDialogControl,
|
|
||||||
} from '#/components/moderation/ModerationDetailsDialog'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
|
|
||||||
export function ProfileHeaderAlerts({
|
export function ProfileHeaderAlerts({
|
||||||
moderation,
|
moderation,
|
||||||
style,
|
|
||||||
}: {
|
}: {
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
|
@ -30,73 +17,21 @@ export function ProfileHeaderAlerts({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.flex_col, a.gap_xs, style]}>
|
<Pills.Row size="lg">
|
||||||
<View style={[a.flex_row, a.flex_wrap, a.gap_xs]}>
|
|
||||||
{modui.alerts.map(cause => (
|
{modui.alerts.map(cause => (
|
||||||
<ProfileLabel key={getModerationCauseKey(cause)} cause={cause} />
|
<Pills.Label
|
||||||
|
size="lg"
|
||||||
|
key={getModerationCauseKey(cause)}
|
||||||
|
cause={cause}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
{modui.informs.map(cause => (
|
{modui.informs.map(cause => (
|
||||||
<ProfileLabel key={getModerationCauseKey(cause)} cause={cause} />
|
<Pills.Label
|
||||||
|
size="lg"
|
||||||
|
key={getModerationCauseKey(cause)}
|
||||||
|
cause={cause}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</View>
|
</Pills.Row>
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ProfileLabel({
|
|
||||||
cause,
|
|
||||||
disableDetailsDialog,
|
|
||||||
}: {
|
|
||||||
cause: ModerationCause
|
|
||||||
disableDetailsDialog?: boolean
|
|
||||||
}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const control = useModerationDetailsDialogControl()
|
|
||||||
const desc = useModerationCauseDescription(cause)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
disabled={disableDetailsDialog}
|
|
||||||
label={desc.name}
|
|
||||||
onPress={() => {
|
|
||||||
control.open()
|
|
||||||
}}>
|
|
||||||
{({hovered, pressed}) => (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
{paddingLeft: 6, paddingRight: 8, paddingVertical: 4},
|
|
||||||
a.gap_xs,
|
|
||||||
a.rounded_md,
|
|
||||||
hovered || pressed
|
|
||||||
? t.atoms.bg_contrast_50
|
|
||||||
: t.atoms.bg_contrast_25,
|
|
||||||
]}>
|
|
||||||
{desc.sourceType === 'labeler' &&
|
|
||||||
desc.sourceDid !== BSKY_LABELER_DID ? (
|
|
||||||
<UserAvatar avatar={desc.sourceAvi} size={16} />
|
|
||||||
) : (
|
|
||||||
<desc.icon size="sm" fill={t.atoms.text_contrast_medium.color} />
|
|
||||||
)}
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_left,
|
|
||||||
a.leading_snug,
|
|
||||||
a.text_sm,
|
|
||||||
t.atoms.text_contrast_medium,
|
|
||||||
a.font_semibold,
|
|
||||||
]}>
|
|
||||||
{desc.name}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{!disableDetailsDialog && (
|
|
||||||
<ModerationDetailsDialog control={control} modcause={cause} />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,7 +315,7 @@ function ChatListItemReady({
|
||||||
|
|
||||||
<PostAlerts
|
<PostAlerts
|
||||||
modui={moderation.ui('contentList')}
|
modui={moderation.ui('contentList')}
|
||||||
size="large"
|
size="lg"
|
||||||
style={[a.pt_xs]}
|
style={[a.pt_xs]}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -313,7 +313,7 @@ let PostThreadItemLoaded = ({
|
||||||
childContainerStyle={styles.contentHiderChild}>
|
childContainerStyle={styles.contentHiderChild}>
|
||||||
<PostAlerts
|
<PostAlerts
|
||||||
modui={moderation.ui('contentView')}
|
modui={moderation.ui('contentView')}
|
||||||
size="large"
|
size="lg"
|
||||||
includeMute
|
includeMute
|
||||||
style={[a.pt_2xs, a.pb_sm]}
|
style={[a.pt_2xs, a.pb_sm]}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -3,13 +3,11 @@ import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
|
||||||
import {
|
import {
|
||||||
AppBskyActorDefs,
|
AppBskyActorDefs,
|
||||||
moderateProfile,
|
moderateProfile,
|
||||||
ModerationCause,
|
|
||||||
ModerationDecision,
|
ModerationDecision,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {Trans} from '@lingui/macro'
|
import {Trans} from '@lingui/macro'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
|
|
||||||
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {Shadow} from '#/state/cache/types'
|
import {Shadow} from '#/state/cache/types'
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
|
@ -26,6 +24,8 @@ import {Text} from '../util/text/Text'
|
||||||
import {PreviewableUserAvatar} from '../util/UserAvatar'
|
import {PreviewableUserAvatar} from '../util/UserAvatar'
|
||||||
import {FollowButton} from './FollowButton'
|
import {FollowButton} from './FollowButton'
|
||||||
import hairlineWidth = StyleSheet.hairlineWidth
|
import hairlineWidth = StyleSheet.hairlineWidth
|
||||||
|
import {atoms as a} from '#/alf'
|
||||||
|
import * as Pills from '#/components/Pills'
|
||||||
|
|
||||||
export function ProfileCard({
|
export function ProfileCard({
|
||||||
testID,
|
testID,
|
||||||
|
@ -137,58 +137,21 @@ export function ProfileCardPills({
|
||||||
followedBy: boolean
|
followedBy: boolean
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
|
||||||
|
|
||||||
const modui = moderation.ui('profileList')
|
const modui = moderation.ui('profileList')
|
||||||
if (!followedBy && !modui.inform && !modui.alert) {
|
if (!followedBy && !modui.inform && !modui.alert) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.pills}>
|
<Pills.Row style={[a.pt_xs]}>
|
||||||
{followedBy && (
|
{followedBy && <Pills.FollowsYou />}
|
||||||
<View style={[s.mt5, pal.btn, styles.pill]}>
|
|
||||||
<Text type="xs" style={pal.text}>
|
|
||||||
<Trans>Follows You</Trans>
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
{modui.alerts.map(alert => (
|
{modui.alerts.map(alert => (
|
||||||
<ProfileCardPillModerationCause
|
<Pills.Label key={getModerationCauseKey(alert)} cause={alert} />
|
||||||
key={getModerationCauseKey(alert)}
|
|
||||||
cause={alert}
|
|
||||||
severity="alert"
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
{modui.informs.map(inform => (
|
{modui.informs.map(inform => (
|
||||||
<ProfileCardPillModerationCause
|
<Pills.Label key={getModerationCauseKey(inform)} cause={inform} />
|
||||||
key={getModerationCauseKey(inform)}
|
|
||||||
cause={inform}
|
|
||||||
severity="inform"
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</View>
|
</Pills.Row>
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ProfileCardPillModerationCause({
|
|
||||||
cause,
|
|
||||||
severity,
|
|
||||||
}: {
|
|
||||||
cause: ModerationCause
|
|
||||||
severity: 'alert' | 'inform'
|
|
||||||
}) {
|
|
||||||
const pal = usePalette('default')
|
|
||||||
const {name} = useModerationCauseDescription(cause)
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style={[s.mt5, pal.btn, styles.pill]}
|
|
||||||
key={getModerationCauseKey(cause)}>
|
|
||||||
<Text type="xs" style={pal.text}>
|
|
||||||
{severity === 'alert' ? '⚠ ' : ''}
|
|
||||||
{name}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,6 +285,7 @@ const styles = StyleSheet.create({
|
||||||
paddingBottom: 10,
|
paddingBottom: 10,
|
||||||
},
|
},
|
||||||
pills: {
|
pills: {
|
||||||
|
alignItems: 'flex-start',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
columnGap: 6,
|
columnGap: 6,
|
||||||
|
|
Loading…
Reference in New Issue