Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improve the visual clarity of labels on profiles and posts (#4262)

* Update PostAlerts rendering to show the avi of the labeler rather than the display name; also add size variations

* Update ProfileHeaderAlerts to match PostAlerts behavior

authored by

Paul Frazee and committed by
GitHub
5fe1e171 4cc55f05

+66 -23
+41 -12
src/components/moderation/PostAlerts.tsx
··· 1 1 import React from 'react' 2 2 import {StyleProp, View, ViewStyle} from 'react-native' 3 - import {ModerationCause, ModerationUI} from '@atproto/api' 3 + import {BSKY_LABELER_DID, ModerationCause, ModerationUI} from '@atproto/api' 4 4 5 5 import {getModerationCauseKey} from '#/lib/moderation' 6 6 import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' 7 + import {UserAvatar} from '#/view/com/util/UserAvatar' 7 8 import {atoms as a, useTheme} from '#/alf' 8 9 import {Button} from '#/components/Button' 9 10 import { ··· 14 15 15 16 export function PostAlerts({ 16 17 modui, 18 + size, 17 19 style, 18 20 }: { 19 21 modui: ModerationUI 22 + size?: 'medium' | 'large' 20 23 includeMute?: boolean 21 24 style?: StyleProp<ViewStyle> 22 25 }) { ··· 28 31 <View style={[a.flex_col, a.gap_xs, style]}> 29 32 <View style={[a.flex_row, a.flex_wrap, a.gap_xs]}> 30 33 {modui.alerts.map(cause => ( 31 - <PostLabel key={getModerationCauseKey(cause)} cause={cause} /> 34 + <PostLabel 35 + key={getModerationCauseKey(cause)} 36 + cause={cause} 37 + size={size} 38 + /> 32 39 ))} 33 40 {modui.informs.map(cause => ( 34 - <PostLabel key={getModerationCauseKey(cause)} cause={cause} /> 41 + <PostLabel 42 + key={getModerationCauseKey(cause)} 43 + cause={cause} 44 + size={size} 45 + /> 35 46 ))} 36 47 </View> 37 48 </View> 38 49 ) 39 50 } 40 51 41 - function PostLabel({cause}: {cause: ModerationCause}) { 52 + function PostLabel({ 53 + cause, 54 + size, 55 + }: { 56 + cause: ModerationCause 57 + size?: 'medium' | 'large' 58 + }) { 42 59 const control = useModerationDetailsDialogControl() 43 60 const desc = useModerationCauseDescription(cause) 44 61 const t = useTheme() ··· 55 72 style={[ 56 73 a.flex_row, 57 74 a.align_center, 58 - {paddingLeft: 4, paddingRight: 6, paddingVertical: 1}, 59 75 a.gap_xs, 60 76 a.rounded_sm, 61 77 hovered || pressed 62 - ? t.atoms.bg_contrast_50 63 - : t.atoms.bg_contrast_25, 78 + ? size === 'large' 79 + ? t.atoms.bg_contrast_50 80 + : t.atoms.bg_contrast_25 81 + : size === 'large' 82 + ? t.atoms.bg_contrast_25 83 + : undefined, 84 + size === 'large' 85 + ? {paddingLeft: 4, paddingRight: 6, paddingVertical: 2} 86 + : {paddingRight: 4, paddingVertical: 1}, 64 87 ]}> 65 - <desc.icon size="xs" fill={t.atoms.text_contrast_medium.color} /> 88 + {desc.sourceType === 'labeler' && 89 + desc.sourceDid !== BSKY_LABELER_DID ? ( 90 + <UserAvatar 91 + avatar={desc.sourceAvi} 92 + size={size === 'large' ? 16 : 12} 93 + /> 94 + ) : ( 95 + <desc.icon size="sm" fill={t.atoms.text_contrast_medium.color} /> 96 + )} 66 97 <Text 67 98 style={[ 68 99 a.text_left, 69 100 a.leading_snug, 70 - a.text_xs, 71 - t.atoms.text_contrast_medium, 72 - a.font_semibold, 101 + size === 'large' ? {fontSize: 13} : a.text_xs, 102 + size === 'large' ? t.atoms.text : t.atoms.text_contrast_high, 73 103 ]}> 74 104 {desc.name} 75 - {desc.source ? ` – ${desc.source}` : ''} 76 105 </Text> 77 106 </View> 78 107 )}
+12 -3
src/components/moderation/ProfileHeaderAlerts.tsx
··· 1 1 import React from 'react' 2 2 import {StyleProp, View, ViewStyle} from 'react-native' 3 - import {ModerationCause, ModerationDecision} from '@atproto/api' 3 + import { 4 + BSKY_LABELER_DID, 5 + ModerationCause, 6 + ModerationDecision, 7 + } from '@atproto/api' 4 8 5 9 import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' 6 10 import {getModerationCauseKey} from 'lib/moderation' 11 + import {UserAvatar} from '#/view/com/util/UserAvatar' 7 12 import {atoms as a, useTheme} from '#/alf' 8 13 import {Button} from '#/components/Button' 9 14 import { ··· 62 67 ? t.atoms.bg_contrast_50 63 68 : t.atoms.bg_contrast_25, 64 69 ]}> 65 - <desc.icon size="sm" fill={t.atoms.text_contrast_medium.color} /> 70 + {desc.sourceType === 'labeler' && 71 + desc.sourceDid !== BSKY_LABELER_DID ? ( 72 + <UserAvatar avatar={desc.sourceAvi} size={16} /> 73 + ) : ( 74 + <desc.icon size="sm" fill={t.atoms.text_contrast_medium.color} /> 75 + )} 66 76 <Text 67 77 style={[ 68 78 a.text_left, ··· 72 82 a.font_semibold, 73 83 ]}> 74 84 {desc.name} 75 - {desc.source ? ` – ${desc.source}` : ''} 76 85 </Text> 77 86 </View> 78 87 )}
+10 -6
src/lib/moderation/useModerationCauseDescription.ts
··· 6 6 } from '@atproto/api' 7 7 import {msg} from '@lingui/macro' 8 8 import {useLingui} from '@lingui/react' 9 - import {getDefinition, getLabelStrings} from './useLabelInfo' 9 + 10 10 import {useLabelDefinitions} from '#/state/preferences' 11 - import {useGlobalLabelStrings} from './useGlobalLabelStrings' 12 - 13 - import {Props as SVGIconProps} from '#/components/icons/common' 14 - import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning' 11 + import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign' 15 12 import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' 13 + import {Props as SVGIconProps} from '#/components/icons/common' 16 14 import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash' 17 - import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign' 15 + import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning' 16 + import {useGlobalLabelStrings} from './useGlobalLabelStrings' 17 + import {getDefinition, getLabelStrings} from './useLabelInfo' 18 18 19 19 export interface ModerationCauseDescription { 20 20 icon: React.ComponentType<SVGIconProps> ··· 22 22 description: string 23 23 source?: string 24 24 sourceType?: ModerationCauseSource['type'] 25 + sourceAvi?: string 26 + sourceDid?: string 25 27 } 26 28 27 29 export function useModerationCauseDescription( ··· 138 140 description: strings.description, 139 141 source, 140 142 sourceType: cause.source.type, 143 + sourceAvi: labeler?.creator.avatar, 144 + sourceDid: cause.label.src, 141 145 } 142 146 } 143 147 // should never happen
+2 -1
src/view/com/post-thread/PostThreadItem.tsx
··· 316 316 childContainerStyle={styles.contentHiderChild}> 317 317 <PostAlerts 318 318 modui={moderation.ui('contentView')} 319 + size="large" 319 320 includeMute 320 321 style={[a.pt_2xs, a.pb_sm]} 321 322 /> ··· 517 518 <LabelsOnMyPost post={post} /> 518 519 <PostAlerts 519 520 modui={moderation.ui('contentList')} 520 - style={[a.pt_xs, a.pb_sm]} 521 + style={[a.pt_2xs, a.pb_2xs]} 521 522 /> 522 523 {richText?.text ? ( 523 524 <View style={styles.postTextContainer}>
+1 -1
src/view/com/posts/FeedItem.tsx
··· 368 368 modui={moderation.ui('contentList')} 369 369 ignoreMute 370 370 childContainerStyle={styles.contentHiderChild}> 371 - <PostAlerts modui={moderation.ui('contentList')} style={[a.pb_xs]} /> 371 + <PostAlerts modui={moderation.ui('contentList')} style={[a.py_2xs]} /> 372 372 {richText.text ? ( 373 373 <View style={styles.postTextContainer}> 374 374 <RichText