Spot check each placement

This commit is contained in:
Eric Bailey
2026-03-10 12:06:44 -05:00
parent 179d64b95a
commit bdb251e5c6
15 changed files with 82 additions and 91 deletions
+20 -26
View File
@@ -51,26 +51,18 @@ export function AccountList({
a.border, a.border,
t.atoms.border_contrast_low, t.atoms.border_contrast_low,
]}> ]}>
{accounts {accounts.map(account => (
.map(account => ({ <React.Fragment key={account.did}>
account, <AccountItem
profile: profiles?.profiles.find(p => p.did === account.did), profile={profiles?.profiles.find(p => p.did === account.did)}
})) account={account}
.filter(item => { onSelect={onSelectAccount}
return !!item.profile isCurrentAccount={account.did === currentAccount?.did}
}) isPendingAccount={account.did === pendingDid}
.map(({account, profile}) => ( />
<React.Fragment key={account.did}> <View style={[a.border_b, t.atoms.border_contrast_low]} />
<AccountItem </React.Fragment>
profile={profile!} ))}
account={account}
onSelect={onSelectAccount}
isCurrentAccount={account.did === currentAccount?.did}
isPendingAccount={account.did === pendingDid}
/>
<View style={[a.border_b, t.atoms.border_contrast_low]} />
</React.Fragment>
))}
<Button <Button
testID="chooseAddAccountBtn" testID="chooseAddAccountBtn"
style={[a.flex_1]} style={[a.flex_1]}
@@ -115,7 +107,7 @@ function AccountItem({
isCurrentAccount, isCurrentAccount,
isPendingAccount, isPendingAccount,
}: { }: {
profile: AppBskyActorDefs.ProfileViewDetailed profile?: AppBskyActorDefs.ProfileViewDetailed
account: SessionAccount account: SessionAccount
onSelect: (account: SessionAccount) => void onSelect: (account: SessionAccount) => void
isCurrentAccount: boolean isCurrentAccount: boolean
@@ -170,11 +162,13 @@ function AccountItem({
profile?.displayName || profile?.handle || account.handle, profile?.displayName || profile?.handle || account.handle,
)} )}
</Text> </Text>
<ProfileBadges {profile && (
profile={profile} <ProfileBadges
size="sm" profile={profile}
style={[{marginTop: -2}]} size="sm"
/> style={[{marginTop: -2}]}
/>
)}
</View> </View>
<Text <Text
style={[ style={[
+5 -20
View File
@@ -11,24 +11,14 @@ import {Robot_Filled_Corner2_Rounded as RobotIcon} from '#/components/icons/Robo
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
import type * as bsky from '#/types/bsky' import type * as bsky from '#/types/bsky'
const sizes = {
xs: 10,
sm: 12,
md: 14,
lg: 18,
xl: 22,
} as const
export type Size = keyof typeof sizes
export function BotBadge({ export function BotBadge({
profile, profile,
alwaysShow = false, alwaysShow = false,
size = 'sm', size,
}: { }: {
profile: bsky.profile.AnyProfileView profile: bsky.profile.AnyProfileView
alwaysShow?: boolean alwaysShow?: boolean
size: Size size: number
}) { }) {
const t = useTheme() const t = useTheme()
@@ -38,20 +28,17 @@ export function BotBadge({
return ( return (
<View> <View>
<RobotIcon <RobotIcon width={size} fill={t.atoms.text_contrast_medium.color} />
width={sizes[size]}
fill={t.atoms.text_contrast_medium.color}
/>
</View> </View>
) )
} }
export function BotBadgeButton({ export function BotBadgeButton({
profile, profile,
size: _size, size,
}: { }: {
profile: bsky.profile.AnyProfileView profile: bsky.profile.AnyProfileView
size: Size size: number
}) { }) {
const t = useTheme() const t = useTheme()
const ax = useAnalytics() const ax = useAnalytics()
@@ -62,8 +49,6 @@ export function BotBadgeButton({
return null return null
} }
const size = sizes[_size]
return ( return (
<> <>
<Button <Button
@@ -139,7 +139,7 @@ function RecentChatItem({
numberOfLines={1}> numberOfLines={1}>
{name} {name}
</Text> </Text>
<ProfileBadges profile={profile} size="sm" style={[a.pl_xs]} /> <ProfileBadges profile={profile} size="xs" style={[a.pl_2xs]} />
</View> </View>
</Button> </Button>
) )
+35 -6
View File
@@ -3,12 +3,30 @@ import {View} from 'react-native'
import {isBotAccount} from '#/lib/bots' import {isBotAccount} from '#/lib/bots'
import {useProfileShadow} from '#/state/cache/profile-shadow' import {useProfileShadow} from '#/state/cache/profile-shadow'
import {atoms as a, type ViewStyleProp} from '#/alf' import {atoms as a, type ViewStyleProp} from '#/alf'
import {BotBadge, BotBadgeButton, type Size} from '#/components/BotBadge' import {BotBadge, BotBadgeButton} from '#/components/BotBadge'
import {useSimpleVerificationState} from '#/components/verification' import {useSimpleVerificationState} from '#/components/verification'
import {VerificationCheck} from '#/components/verification/VerificationCheck' import {VerificationCheck} from '#/components/verification/VerificationCheck'
import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton' import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton'
import type * as bsky from '#/types/bsky' import type * as bsky from '#/types/bsky'
export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
const verificationIconSizes: Record<Size, number> = {
xs: 10,
sm: 12,
md: 14,
lg: 18,
xl: 22,
} as const
const botIconSizes: Record<Size, number> = {
xs: 11,
sm: 13,
md: 15,
lg: 19,
xl: 23,
} as const
export function ProfileBadges({ export function ProfileBadges({
profile, profile,
interactive = false, interactive = false,
@@ -25,22 +43,33 @@ export function ProfileBadges({
// if nothing to show, don't render the container at all // if nothing to show, don't render the container at all
if (!verification.showBadge && !isBotAccount(shadowed)) return null if (!verification.showBadge && !isBotAccount(shadowed)) return null
const isOnTheSmallSide = size === 'xs' || size === 'sm'
return ( return (
<View style={[a.flex_row, a.align_center, a.gap_xs, style]}> <View
style={[
a.flex_row,
a.align_center,
isOnTheSmallSide ? a.gap_2xs : a.gap_xs,
style,
]}>
{interactive ? ( {interactive ? (
<> <>
<VerificationCheckButton profile={shadowed} size={size} /> <VerificationCheckButton
<BotBadgeButton profile={shadowed} size={size} /> profile={shadowed}
size={verificationIconSizes[size]}
/>
<BotBadgeButton profile={shadowed} size={botIconSizes[size]} />
</> </>
) : ( ) : (
<> <>
{verification.showBadge && ( {verification.showBadge && (
<VerificationCheck <VerificationCheck
verifier={verification.role === 'verifier'} verifier={verification.role === 'verifier'}
size={size} width={verificationIconSizes[size]}
/> />
)} )}
<BotBadge profile={shadowed} size={size} /> <BotBadge profile={shadowed} size={botIconSizes[size]} />
</> </>
)} )}
</View> </View>
+2 -2
View File
@@ -262,7 +262,7 @@ function InlineNameAndHandle({
</Text> </Text>
<ProfileBadges <ProfileBadges
profile={profile} profile={profile}
size="sm" size="md"
style={[ style={[
a.pl_2xs, a.pl_2xs,
a.self_center, a.self_center,
@@ -314,7 +314,7 @@ export function Name({
numberOfLines={1}> numberOfLines={1}>
{name} {name}
</Text> </Text>
<ProfileBadges profile={profile} size="sm" style={[a.pl_xs]} /> <ProfileBadges profile={profile} size="md" style={[a.pl_xs]} />
</View> </View>
) )
} }
@@ -531,7 +531,7 @@ function Inner({
style={[ style={[
a.pl_xs, a.pl_xs,
{ {
marginTop: -2, marginTop: -1,
}, },
]} ]}
/> />
+1 -1
View File
@@ -157,7 +157,7 @@ function HeaderReady({
numberOfLines={1}> numberOfLines={1}>
{displayName} {displayName}
</Text> </Text>
<ProfileBadges profile={profile} size="sm" style={[a.pl_xs]} /> <ProfileBadges profile={profile} size="md" style={[a.pl_xs]} />
</View> </View>
{!isDeletedAccount && ( {!isDeletedAccount && (
<Text <Text
@@ -14,16 +14,6 @@ import {VerifierDialog} from '#/components/verification/VerifierDialog'
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
import type * as bsky from '#/types/bsky' import type * as bsky from '#/types/bsky'
const sizes = {
xs: 10,
sm: 12,
md: 14,
lg: 18,
xl: 22,
} as const
export type Size = keyof typeof sizes
export function shouldShowVerificationCheckButton( export function shouldShowVerificationCheckButton(
state: FullVerificationState, state: FullVerificationState,
) { ) {
@@ -64,7 +54,7 @@ export function VerificationCheckButton({
size, size,
}: { }: {
profile: Shadow<bsky.profile.AnyProfileView> profile: Shadow<bsky.profile.AnyProfileView>
size: Size size: number
}) { }) {
const state = useFullVerificationState({ const state = useFullVerificationState({
profile, profile,
@@ -80,18 +70,17 @@ export function VerificationCheckButton({
function Badge({ function Badge({
profile, profile,
verificationState: state, verificationState: state,
size: _size, size,
}: { }: {
profile: Shadow<bsky.profile.AnyProfileView> profile: Shadow<bsky.profile.AnyProfileView>
verificationState: FullVerificationState verificationState: FullVerificationState
size: Size size: number
}) { }) {
const t = useTheme() const t = useTheme()
const ax = useAnalytics() const ax = useAnalytics()
const {_} = useLingui() const {_} = useLingui()
const verificationsDialogControl = useDialogControl() const verificationsDialogControl = useDialogControl()
const verifierDialogControl = useDialogControl() const verifierDialogControl = useDialogControl()
const size = sizes[_size]
const verifiedByHidden = !state.profile.showBadge && state.profile.isViewer const verifiedByHidden = !state.profile.showBadge && state.profile.isViewer
@@ -412,7 +412,7 @@ function ChatListItemReady({
</View> </View>
<ProfileBadges <ProfileBadges
profile={profile} profile={profile}
size="sm" size="md"
style={[a.pl_xs, a.self_center]} style={[a.pl_xs, a.self_center]}
/> />
{lastMessageSentAt && ( {lastMessageSentAt && (
@@ -163,7 +163,7 @@ function RecentProfileItem({
<Text emoji style={[a.text_xs, a.leading_snug]} numberOfLines={1}> <Text emoji style={[a.text_xs, a.leading_snug]} numberOfLines={1}>
{name} {name}
</Text> </Text>
<ProfileBadges profile={profile} size="sm" style={[a.pl_xs]} /> <ProfileBadges profile={profile} size="xs" style={[a.pl_xs]} />
</View> </View>
</Link> </Link>
<Button <Button
@@ -1,4 +1,3 @@
import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {type $Typed, ComAtprotoLabelDefs} from '@atproto/api' import {type $Typed, ComAtprotoLabelDefs} from '@atproto/api'
import {msg} from '@lingui/core/macro' import {msg} from '@lingui/core/macro'
@@ -139,7 +138,7 @@ export function AutomationLabelSettingsScreen({}: Props) {
size="xs" size="xs"
/> />
)} )}
<BotBadge profile={profile} alwaysShow size="md" /> <BotBadge profile={profile} alwaysShow size={16} />
</View> </View>
</View> </View>
<Text <Text
+1 -1
View File
@@ -359,7 +359,7 @@ function ProfilePreview({
</Text> </Text>
<ProfileBadges <ProfileBadges
profile={shadow} profile={shadow}
size="lg" size="xl"
interactive interactive
style={[ style={[
{ {
@@ -244,13 +244,14 @@ let NotificationFeedItem = ({
{forceLTR(firstAuthorName)} {forceLTR(firstAuthorName)}
<ProfileBadges <ProfileBadges
profile={firstAuthor.profile} profile={firstAuthor.profile}
size="sm" size="md"
style={[ style={[
a.relative, a.relative,
{ {
// weird stuff here
paddingTop: platform({android: 2}), paddingTop: platform({android: 2}),
marginBottom: platform({ios: -7}), marginBottom: platform({ios: -6}),
top: platform({web: 1}), top: platform({web: 2}),
paddingLeft: 3, paddingLeft: 3,
paddingRight: 2, paddingRight: 2,
}, },
@@ -1046,8 +1047,8 @@ function ExpandedAuthorCard({author}: {author: Author}) {
</Text> </Text>
<ProfileBadges <ProfileBadges
profile={author.profile} profile={author.profile}
size="sm" size="md"
style={[a.pl_xs, a.self_center]} style={[a.pl_2xs, a.self_center]}
/> />
<Text <Text
numberOfLines={1} numberOfLines={1}
+3 -9
View File
@@ -13,7 +13,7 @@ import {sanitizeHandle} from '#/lib/strings/handles'
import {niceDate} from '#/lib/strings/time' import {niceDate} from '#/lib/strings/time'
import {useProfileShadow} from '#/state/cache/profile-shadow' import {useProfileShadow} from '#/state/cache/profile-shadow'
import {unstableCacheProfileView} from '#/state/queries/profile' import {unstableCacheProfileView} from '#/state/queries/profile'
import {atoms as a, platform, useTheme, web} from '#/alf' import {atoms as a, useTheme, web} from '#/alf'
import {WebOnlyInlineLinkText} from '#/components/Link' import {WebOnlyInlineLinkText} from '#/components/Link'
import {ProfileBadges} from '#/components/ProfileBadges' import {ProfileBadges} from '#/components/ProfileBadges'
import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {ProfileHoverCard} from '#/components/ProfileHoverCard'
@@ -109,14 +109,8 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => {
</MaybeLinkText> </MaybeLinkText>
<ProfileBadges <ProfileBadges
profile={author} profile={author}
size="xs" size="sm"
style={[ style={[a.pl_2xs, a.self_center]}
a.pl_2xs,
a.self_center,
{
marginTop: platform({web: 0, ios: 0, android: -1}),
},
]}
/> />
<MaybeLinkText <MaybeLinkText
emoji emoji
+1 -1
View File
@@ -95,7 +95,7 @@ let DrawerProfileCard = ({
numberOfLines={1}> numberOfLines={1}>
{profile?.displayName || account.handle} {profile?.displayName || account.handle}
</Text> </Text>
{profile && <ProfileBadges profile={profile} size="md" />} {profile && <ProfileBadges profile={profile} size="lg" />}
</View> </View>
<Text <Text
emoji emoji