Collection of moderation fixes (#4566)
* Fix: dont blur parents in threads that embed blocks * After tapping 'Show hidden replies', show the individual hider cards * Add shape override to UserAvatar and fix the fallback avi for labelers * Fix precedence * Detect shape for DefaultAvatar --------- Co-authored-by: Dan Abramov <dan.abramov@gmail.com>zio/stable
parent
ac08c76168
commit
07c2be255f
|
@ -92,6 +92,8 @@ function PostLabel({
|
|||
<UserAvatar
|
||||
avatar={desc.sourceAvi}
|
||||
size={size === 'large' ? 16 : 12}
|
||||
type="labeler"
|
||||
shape="circle"
|
||||
/>
|
||||
) : (
|
||||
<desc.icon size="sm" fill={t.atoms.text_contrast_medium.color} />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {ComponentProps} from 'react'
|
||||
import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
|
||||
import {AppBskyActorDefs, ModerationUI} from '@atproto/api'
|
||||
import {AppBskyActorDefs, ModerationCause, ModerationUI} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
@ -45,7 +45,8 @@ export function PostHider({
|
|||
const [override, setOverride] = React.useState(false)
|
||||
const control = useModerationDetailsDialogControl()
|
||||
const blur =
|
||||
modui.blurs[0] || (interpretFilterAsBlur ? modui.filters[0] : undefined)
|
||||
modui.blurs[0] ||
|
||||
(interpretFilterAsBlur ? getBlurrableFilter(modui) : undefined)
|
||||
const desc = useModerationCauseDescription(blur)
|
||||
|
||||
const onBeforePress = React.useCallback(() => {
|
||||
|
@ -134,6 +135,13 @@ export function PostHider({
|
|||
)
|
||||
}
|
||||
|
||||
function getBlurrableFilter(modui: ModerationUI): ModerationCause | undefined {
|
||||
// moderation causes get "downgraded" when they originate from embedded content
|
||||
// a downgraded cause should *only* drive filtering in feeds, so we want to look
|
||||
// for filters that arent downgraded
|
||||
return modui.filters.find(filter => !filter.downgraded)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
child: {
|
||||
borderWidth: 0,
|
||||
|
|
|
@ -331,7 +331,11 @@ export function PostThread({
|
|||
<PostThreadShowHiddenReplies
|
||||
type={item === SHOW_HIDDEN_REPLIES ? 'hidden' : 'muted'}
|
||||
onPress={() =>
|
||||
setHiddenRepliesState(HiddenRepliesState.ShowAndOverridePostHider)
|
||||
setHiddenRepliesState(
|
||||
item === SHOW_HIDDEN_REPLIES
|
||||
? HiddenRepliesState.Show
|
||||
: HiddenRepliesState.ShowAndOverridePostHider,
|
||||
)
|
||||
}
|
||||
hideTopBorder={index === 0}
|
||||
/>
|
||||
|
|
|
@ -35,6 +35,7 @@ export type UserAvatarType = 'user' | 'algo' | 'list' | 'labeler'
|
|||
|
||||
interface BaseUserAvatarProps {
|
||||
type?: UserAvatarType
|
||||
shape?: 'circle' | 'square'
|
||||
size: number
|
||||
avatar?: string | null
|
||||
}
|
||||
|
@ -60,12 +61,16 @@ const BLUR_AMOUNT = isWeb ? 5 : 100
|
|||
|
||||
let DefaultAvatar = ({
|
||||
type,
|
||||
shape: overrideShape,
|
||||
size,
|
||||
}: {
|
||||
type: UserAvatarType
|
||||
shape?: 'square' | 'circle'
|
||||
size: number
|
||||
}): React.ReactNode => {
|
||||
const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
|
||||
if (type === 'algo') {
|
||||
// TODO: shape=circle
|
||||
// Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
|
||||
return (
|
||||
<Svg
|
||||
|
@ -84,6 +89,7 @@ let DefaultAvatar = ({
|
|||
)
|
||||
}
|
||||
if (type === 'list') {
|
||||
// TODO: shape=circle
|
||||
// Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
|
||||
return (
|
||||
<Svg
|
||||
|
@ -117,14 +123,18 @@ let DefaultAvatar = ({
|
|||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
stroke="none">
|
||||
<Rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="32"
|
||||
height="32"
|
||||
rx="3"
|
||||
fill={tokens.color.temp_purple}
|
||||
/>
|
||||
{finalShape === 'square' ? (
|
||||
<Rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="32"
|
||||
height="32"
|
||||
rx="3"
|
||||
fill={tokens.color.temp_purple}
|
||||
/>
|
||||
) : (
|
||||
<Circle cx="16" cy="16" r="16" fill={tokens.color.temp_purple} />
|
||||
)}
|
||||
<Path
|
||||
d="M24 9.75L16 7L8 9.75V15.9123C8 20.8848 12 23 16 25.1579C20 23 24 20.8848 24 15.9123V9.75Z"
|
||||
stroke="white"
|
||||
|
@ -135,6 +145,7 @@ let DefaultAvatar = ({
|
|||
</Svg>
|
||||
)
|
||||
}
|
||||
// TODO: shape=square
|
||||
return (
|
||||
<Svg
|
||||
testID="userAvatarFallback"
|
||||
|
@ -159,6 +170,7 @@ export {DefaultAvatar}
|
|||
|
||||
let UserAvatar = ({
|
||||
type = 'user',
|
||||
shape: overrideShape,
|
||||
size,
|
||||
avatar,
|
||||
moderation,
|
||||
|
@ -166,9 +178,10 @@ let UserAvatar = ({
|
|||
}: UserAvatarProps): React.ReactNode => {
|
||||
const pal = usePalette('default')
|
||||
const backgroundColor = pal.colors.backgroundLight
|
||||
const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
|
||||
|
||||
const aviStyle = useMemo(() => {
|
||||
if (type === 'algo' || type === 'list' || type === 'labeler') {
|
||||
if (finalShape === 'square') {
|
||||
return {
|
||||
width: size,
|
||||
height: size,
|
||||
|
@ -182,7 +195,7 @@ let UserAvatar = ({
|
|||
borderRadius: Math.floor(size / 2),
|
||||
backgroundColor,
|
||||
}
|
||||
}, [type, size, backgroundColor])
|
||||
}, [finalShape, size, backgroundColor])
|
||||
|
||||
const alert = useMemo(() => {
|
||||
if (!moderation?.alert) {
|
||||
|
@ -224,7 +237,7 @@ let UserAvatar = ({
|
|||
</View>
|
||||
) : (
|
||||
<View style={{width: size, height: size}}>
|
||||
<DefaultAvatar type={type} size={size} />
|
||||
<DefaultAvatar type={type} shape={finalShape} size={size} />
|
||||
{alert}
|
||||
</View>
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue