Fix Android thread number alignment across font scales (#11667)
This commit is contained in:
@@ -2,13 +2,35 @@ import {Text, View} from 'react-native'
|
|||||||
import {Trans, useLingui} from '@lingui/react/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
|
|
||||||
import {atoms as a, ios, platform, useTheme} from '#/alf'
|
import {atoms as a, ios, platform, useTheme} from '#/alf'
|
||||||
|
import {useNativeFontScale} from '#/alf/util/dimensions'
|
||||||
import {type app} from '#/lexicons'
|
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`.
|
* 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<
|
export type ThreadItemPostNumbering = Pick<
|
||||||
app.bsky.unspecced.defs.ThreadItemPost,
|
app.bsky.unspecced.defs.ThreadItemPost,
|
||||||
@@ -39,6 +61,7 @@ export function ThreadItemPostNumber({
|
|||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {t: l} = useLingui()
|
const {t: l} = useLingui()
|
||||||
|
const nativeFontScale = useNativeFontScale()
|
||||||
const shouldRender = useHasThreadItemPostNumber(value)
|
const shouldRender = useHasThreadItemPostNumber(value)
|
||||||
const index = value?.opThreadPostIndex
|
const index = value?.opThreadPostIndex
|
||||||
const count = value?.opThreadPostCount
|
const count = value?.opThreadPostCount
|
||||||
@@ -61,11 +84,27 @@ export function ThreadItemPostNumber({
|
|||||||
},
|
},
|
||||||
inline
|
inline
|
||||||
? platform({
|
? platform({
|
||||||
android: {transform: [{translateY: POST_NUMBER_INLINE_OFFSET}]},
|
android: {
|
||||||
ios: {transform: [{translateY: a.py_2xs.paddingBottom}]},
|
/*
|
||||||
|
* 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: {
|
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,
|
lineHeight: a.text_xs.fontSize * a.leading_normal.lineHeight,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user