Use consistent avatar shape/defaults for labelers (#3257)

* Add type: labeler to easy spots

* Search and ProfileCard

* Filter out of suggested follows

* ComposeReplyTo

* PReviewable avatar in posts

* Lists

* PostMeta

* Notifications

* Autocomplete

* Straggler

* Bump sdk
zio/stable
Eric Bailey 2024-03-19 14:18:57 -05:00 committed by GitHub
parent b9474a5d55
commit dfe88e1656
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 87 additions and 58 deletions

View File

@ -46,7 +46,7 @@
"make-deploy-bundle": "bash scripts/bundleUpdate.sh"
},
"dependencies": {
"@atproto/api": "^0.12.0",
"@atproto/api": "^0.12.1",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@braintree/sanitize-url": "^6.0.2",
"@emoji-mart/react": "^1.1.1",

View File

@ -101,13 +101,7 @@ function computeSuggestions(
}
for (const item of searched) {
if (!items.find(item2 => item2.handle === item.handle)) {
items.push({
did: item.did,
handle: item.handle,
displayName: item.displayName,
avatar: item.avatar,
labels: item.labels,
})
items.push(item)
}
}
return items.filter(profile => {

View File

@ -3,6 +3,7 @@ import {
AppBskyEmbedRecord,
AppBskyRichtextFacet,
ModerationDecision,
AppBskyActorDefs,
} from '@atproto/api'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
@ -10,11 +11,7 @@ export interface ComposerOptsPostRef {
uri: string
cid: string
text: string
author: {
handle: string
displayName?: string
avatar?: string
}
author: AppBskyActorDefs.ProfileViewBasic
embed?: AppBskyEmbedRecord.ViewRecord['embed']
moderation?: ModerationDecision
}

View File

@ -45,7 +45,11 @@ function AccountItem({
accessibilityHint={_(msg`Double tap to sign in`)}>
<View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
<View style={s.p10}>
<UserAvatar avatar={profile?.avatar} size={30} />
<UserAvatar
avatar={profile?.avatar}
size={30}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
<Text style={styles.accountText}>
<Text type="lg-bold" style={pal.text}>

View File

@ -415,7 +415,11 @@ export const ComposePost = observer(function ComposePost({
styles.textInputLayout,
isNative && styles.textInputLayoutMobile,
]}>
<UserAvatar avatar={currentProfile?.avatar} size={50} />
<UserAvatar
avatar={currentProfile?.avatar}
size={50}
type={currentProfile?.associated?.labeler ? 'labeler' : 'user'}
/>
<TextInput
ref={textInput}
richtext={richtext}

View File

@ -87,6 +87,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
avatar={replyTo.author.avatar}
size={50}
moderation={replyTo.moderation?.ui('avatar')}
type={replyTo.author.associated?.labeler ? 'labeler' : 'user'}
/>
<View style={styles.replyToPost}>
<Text type="xl-medium" style={[pal.text]}>

View File

@ -23,7 +23,11 @@ export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
accessibilityRole="button"
accessibilityLabel={_(msg`Compose reply`)}
accessibilityHint={_(msg`Opens composer`)}>
<UserAvatar avatar={profile?.avatar} size={38} />
<UserAvatar
avatar={profile?.avatar}
size={38}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
<Text
type="xl"
style={[

View File

@ -78,7 +78,11 @@ export function Autocomplete({
accessibilityLabel={`Select ${item.handle}`}
accessibilityHint="">
<View style={styles.avatarAndHandle}>
<UserAvatar avatar={item.avatar ?? null} size={24} />
<UserAvatar
avatar={item.avatar ?? null}
size={24}
type={item.associated?.labeler ? 'labeler' : 'user'}
/>
<Text type="md-medium" style={pal.text}>
{displayName}
</Text>

View File

@ -175,7 +175,11 @@ const MentionList = forwardRef<MentionListRef, SuggestionProps>(
}}
accessibilityRole="button">
<View style={styles.avatarAndDisplayName}>
<UserAvatar avatar={item.avatar ?? null} size={26} />
<UserAvatar
avatar={item.avatar ?? null}
size={26}
type={item.associated?.labeler ? 'labeler' : 'user'}
/>
<Text style={pal.text} numberOfLines={1}>
{displayName}
</Text>

View File

@ -231,7 +231,11 @@ function UserResult({
width: 54,
paddingLeft: 4,
}}>
<UserAvatar size={40} avatar={profile.avatar} />
<UserAvatar
size={40}
avatar={profile.avatar}
type={profile.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
<View
style={{

View File

@ -45,7 +45,11 @@ function SwitchAccountCard({account}: {account: SessionAccount}) {
const contents = (
<View style={[pal.view, styles.linkCard]}>
<View style={styles.avi}>
<UserAvatar size={40} avatar={profile?.avatar} />
<UserAvatar
size={40}
avatar={profile?.avatar}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
<View style={[s.flex1]}>
<Text type="md-bold" style={pal.text} numberOfLines={1}>

View File

@ -180,7 +180,7 @@ function ListItem({
},
]}>
<View style={styles.listItemAvi}>
<UserAvatar size={40} avatar={list.avatar} />
<UserAvatar size={40} avatar={list.avatar} type="list" />
</View>
<View style={styles.listItemContent}>
<Text

View File

@ -14,6 +14,7 @@ import {
ModerationDecision,
moderateProfile,
AppBskyEmbedRecordWithMedia,
AppBskyActorDefs,
} from '@atproto/api'
import {AtUri} from '@atproto/api'
import {
@ -55,6 +56,7 @@ interface Author {
displayName?: string
avatar?: string
moderation: ModerationDecision
associated?: AppBskyActorDefs.ProfileAssociated
}
let FeedItem = ({
@ -100,6 +102,7 @@ let FeedItem = ({
displayName: item.notification.author.displayName,
avatar: item.notification.author.avatar,
moderation: moderateProfile(item.notification.author, moderationOpts),
associated: item.notification.author.associated,
},
...(item.additional?.map(({author}) => {
return {
@ -109,6 +112,7 @@ let FeedItem = ({
displayName: author.displayName,
avatar: author.avatar,
moderation: moderateProfile(author, moderationOpts),
associated: author.associated,
}
}) || []),
]
@ -337,6 +341,7 @@ function CondensedAuthorsList({
handle={authors[0].handle}
avatar={authors[0].avatar}
moderation={authors[0].moderation.ui('avatar')}
type={authors[0].associated?.labeler ? 'labeler' : 'user'}
/>
</View>
)
@ -355,6 +360,7 @@ function CondensedAuthorsList({
size={35}
avatar={author.avatar}
moderation={author.moderation.ui('avatar')}
type={author.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
))}
@ -413,6 +419,7 @@ function ExpandedAuthorsList({
size={35}
avatar={author.avatar}
moderation={author.moderation.ui('avatar')}
type={author.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
<View style={s.flex1}>

View File

@ -205,11 +205,7 @@ let PostThreadItemLoaded = ({
uri: post.uri,
cid: post.cid,
text: record.text,
author: {
handle: post.author.handle,
displayName: post.author.displayName,
avatar: post.author.avatar,
},
author: post.author,
embed: post.embed,
moderation,
},
@ -256,6 +252,7 @@ let PostThreadItemLoaded = ({
handle={post.author.handle}
avatar={post.author.avatar}
moderation={moderation.ui('avatar')}
type={post.author.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
<View style={styles.layoutContent}>
@ -452,6 +449,7 @@ let PostThreadItemLoaded = ({
handle={post.author.handle}
avatar={post.author.avatar}
moderation={moderation.ui('avatar')}
type={post.author.associated?.labeler ? 'labeler' : 'user'}
/>
{showChildReplyLine && (

View File

@ -118,11 +118,7 @@ function PostInner({
uri: post.uri,
cid: post.cid,
text: record.text,
author: {
handle: post.author.handle,
displayName: post.author.displayName,
avatar: post.author.avatar,
},
author: post.author,
embed: post.embed,
moderation,
},
@ -144,6 +140,7 @@ function PostInner({
handle={post.author.handle}
avatar={post.author.avatar}
moderation={moderation.ui('avatar')}
type={post.author.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
<View style={styles.layoutContent}>

View File

@ -126,11 +126,7 @@ let FeedItemInner = ({
uri: post.uri,
cid: post.cid,
text: record.text || '',
author: {
handle: post.author.handle,
displayName: post.author.displayName,
avatar: post.author.avatar,
},
author: post.author,
embed: post.embed,
moderation,
},
@ -243,6 +239,7 @@ let FeedItemInner = ({
handle={post.author.handle}
avatar={post.author.avatar}
moderation={moderation.ui('avatar')}
type={post.author.associated?.labeler ? 'labeler' : 'user'}
/>
{isThreadParent && (
<View

View File

@ -49,6 +49,7 @@ export function ProfileCard({
const pal = usePalette('default')
const profile = useProfileShadow(profileUnshadowed)
const moderationOpts = useModerationOpts()
const isLabeler = profile?.associated?.labeler
if (!moderationOpts) {
return null
}
@ -79,6 +80,7 @@ export function ProfileCard({
size={40}
avatar={profile.avatar}
moderation={moderation.ui('avatar')}
type={isLabeler ? 'labeler' : 'user'}
/>
</View>
<View style={styles.layoutContent}>
@ -101,7 +103,7 @@ export function ProfileCard({
/>
{!!profile.viewer?.followedBy && <View style={s.flexRow} />}
</View>
{renderButton ? (
{renderButton && !isLabeler ? (
<View style={styles.layoutButton}>{renderButton(profile)}</View>
) : undefined}
</View>
@ -223,6 +225,7 @@ function FollowersList({
avatar={f.avatar}
size={32}
moderation={mod.ui('avatar')}
type={f.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
</View>

View File

@ -98,9 +98,11 @@ export function ProfileHeaderSuggestedFollows({
<SuggestedFollowSkeleton />
</>
) : data ? (
data.suggestions.map(profile => (
<SuggestedFollow key={profile.did} profile={profile} />
))
data.suggestions
.filter(s => (s.associated?.labeler ? false : true))
.map(profile => (
<SuggestedFollow key={profile.did} profile={profile} />
))
) : (
<View />
)}

View File

@ -11,16 +11,11 @@ import {sanitizeHandle} from 'lib/strings/handles'
import {isAndroid, isWeb} from 'platform/detection'
import {TimeElapsed} from './TimeElapsed'
import {makeProfileLink} from 'lib/routes/links'
import {ModerationDecision, ModerationUI} from '@atproto/api'
import {AppBskyActorDefs, ModerationDecision, ModerationUI} from '@atproto/api'
import {usePrefetchProfileQuery} from '#/state/queries/profile'
interface PostMetaOpts {
author: {
avatar?: string
did: string
handle: string
displayName?: string | undefined
}
author: AppBskyActorDefs.ProfileViewBasic
moderation: ModerationDecision | undefined
authorHasWarning: boolean
postHref: string
@ -47,6 +42,7 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
avatar={opts.author.avatar}
size={opts.avatarSize || 16}
moderation={opts.avatarModeration}
type={opts.author.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
)}

View File

@ -59,11 +59,7 @@ export function PostThreadScreen({route}: Props) {
uri: thread.post.uri,
cid: thread.post.cid,
text: thread.record.text,
author: {
handle: thread.post.author.handle,
displayName: thread.post.author.displayName,
avatar: thread.post.author.avatar,
},
author: thread.post.author,
embed: thread.post.embed,
},
onPost: () =>

View File

@ -141,6 +141,7 @@ function SearchScreenSuggestedFollows() {
friends.slice(0, 4).map(friend =>
getSuggestedFollowsByActor(friend.did).then(foafsRes => {
for (const user of foafsRes.suggestions) {
if (user.associated?.labeler) continue
friendsOfFriends.set(user.did, user)
}
}),

View File

@ -82,7 +82,11 @@ function SettingsAccountCard({account}: {account: SessionAccount}) {
const contents = (
<View style={[pal.view, styles.linkCard]}>
<View style={styles.avi}>
<UserAvatar size={40} avatar={profile?.avatar} />
<UserAvatar
size={40}
avatar={profile?.avatar}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
<View style={[s.flex1]}>
<Text type="md-bold" style={pal.text}>

View File

@ -75,6 +75,7 @@ let DrawerProfileCard = ({
avatar={profile?.avatar}
// See https://github.com/bluesky-social/social-app/pull/1801:
usePlainRNImage={true}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
<Text
type="title-lg"

View File

@ -229,6 +229,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
size={27}
// See https://github.com/bluesky-social/social-app/pull/1801:
usePlainRNImage={true}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
) : (
@ -238,6 +239,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
size={28}
// See https://github.com/bluesky-social/social-app/pull/1801:
usePlainRNImage={true}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
</View>
)}

View File

@ -64,7 +64,11 @@ function ProfileCard() {
style={[styles.profileCard, !isDesktop && styles.profileCardTablet]}
title={_(msg`My Profile`)}
asAnchor>
<UserAvatar avatar={profile.avatar} size={size} />
<UserAvatar
avatar={profile.avatar}
size={size}
type={profile?.associated?.labeler ? 'labeler' : 'user'}
/>
</Link>
) : (
<View style={[styles.profileCard, !isDesktop && styles.profileCardTablet]}>

View File

@ -112,6 +112,7 @@ export function SearchProfileCard({
size={40}
avatar={profile.avatar}
moderation={moderation.ui('avatar')}
type={profile.associated?.labeler ? 'labeler' : 'user'}
/>
<View style={{flex: 1}}>
<Text

View File

@ -34,10 +34,10 @@
jsonpointer "^5.0.0"
leven "^3.1.0"
"@atproto/api@^0.12.0":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.0.tgz#69e52f8761dc7d76c675fa7284bd49240bb0df64"
integrity sha512-nSWiad1Z6IC/oVFSVxD5gZLhkD+J4EW2CFqAqIhklJNc0cjFKdmf8D56Pac6Ktm1sJoM6TVZ8GEeuEG6bJS/aQ==
"@atproto/api@^0.12.1":
version "0.12.1"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.1.tgz#3340cbbd6a51a8c2f3248dae55a01415ab71084e"
integrity sha512-Grigs9neuQxytXr2yHq/IfNlgXQVptWDO9KTQr5FDmgMY4Zly2X7Sa99u9c1CW9auwUTbcd+yRFBNEtbA3n3qg==
dependencies:
"@atproto/common-web" "^0.3.0"
"@atproto/lexicon" "^0.4.0"