Fix Android thread number alignment across font scales (#11667)

This commit is contained in:
DS Boyce
2026-09-04 20:09:42 -07:00
committed by GitHub
parent c9a96859d1
commit 5091e4e25a
@@ -2,13 +2,35 @@ import {Text, View} from 'react-native'
import {Trans, useLingui} from '@lingui/react/macro'
import {atoms as a, ios, platform, useTheme} from '#/alf'
import {useNativeFontScale} from '#/alf/util/dimensions'
import {type app} from '#/lexicons'
/**
* How far the inline badge is nudged below the text baseline. Android's
* Map of Android font scale values to inline offsets.
*/
const ANDROID_INLINE_OFFSETS = [
[0.85, 2],
[1, 4],
[1.15, 6],
[1.3, 8],
[1.5, 10],
[1.8, 12],
[2, 14],
] as const
/**
* Max amount the inline badge is nudged below the text baseline. Android's
* containing `RichText` reserves matching room via `suffixOffset`.
*/
export const POST_NUMBER_INLINE_OFFSET = 6
export const POST_NUMBER_INLINE_OFFSET = 14
function getAndroidInlineOffset(fontScale: number) {
return ANDROID_INLINE_OFFSETS.reduce((nearest, candidate) =>
Math.abs(candidate[0] - fontScale) < Math.abs(nearest[0] - fontScale)
? candidate
: nearest,
)[1]
}
export type ThreadItemPostNumbering = Pick<
app.bsky.unspecced.defs.ThreadItemPost,
@@ -39,6 +61,7 @@ export function ThreadItemPostNumber({
}) {
const t = useTheme()
const {t: l} = useLingui()
const nativeFontScale = useNativeFontScale()
const shouldRender = useHasThreadItemPostNumber(value)
const index = value?.opThreadPostIndex
const count = value?.opThreadPostCount
@@ -61,11 +84,27 @@ export function ThreadItemPostNumber({
},
inline
? platform({
android: {transform: [{translateY: POST_NUMBER_INLINE_OFFSET}]},
ios: {transform: [{translateY: a.py_2xs.paddingBottom}]},
android: {
/*
* Android aligns the inline view's bottom to the surrounding
* text baseline.
* We want it to align the inline view's child/text baseline.
*/
transform: [
{translateY: getAndroidInlineOffset(nativeFontScale)},
],
},
ios: {
/*
* For iOS, we just need to offset the padding we applied.
*/
transform: [{translateY: a.py_2xs.paddingBottom}],
},
web: {
// Inline views inherit the surrounding line height on web. Keep
// the badge at its usual size when emoji-only text enlarges it.
/*
* Inline views inherit the surrounding line height on web. Keep
* the badge at its usual size when emoji-only text enlarges it.
*/
lineHeight: a.text_xs.fontSize * a.leading_normal.lineHeight,
},
})