Loosen buffer line spacing for all fonts

Add extra vertical space to every buffer line (LINE_SPACING_EXTRA, 30% of font size) on top of the font natural line height. The same style measures and draws rows so whole-line snapping stays in step.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JW57ZwRSygeowNBguQEUUB
This commit is contained in:
2026-10-29 02:30:39 +00:00
co-authored by Claude Sonnet 5.5
parent 78bd235a48
commit 03964ca313
+31 -11
View File
@@ -1,3 +1,5 @@
@file:OptIn(androidx.compose.ui.text.ExperimentalTextApi::class)
package ui
import androidx.compose.animation.core.animateFloatAsState
@@ -847,14 +849,30 @@ fun MessageScrollback(
// then converts that now-stale pixel value using the NEW density, so the
// two silently disagreed until the window (and this remember scope) was
// recreated by closing and reopening it.
val lineHeightPx = remember(displaySettings.fontSize, displaySettings.fontId, density) {
textMeasurer.measure(
text = "Mg",
style = androidx.compose.ui.text.TextStyle(
fontFamily = AppFonts.familyFor(displaySettings.fontId),
fontSize = displaySettings.fontSize.sp
// The buffer text style gets extra vertical air on top of the font's own natural
// line height (every bundled font has different metrics, so a fixed multiplier
// would loosen some fonts and tighten others). The same style is used to measure
// the line height below AND to draw every row, so the whole-line snapping stays
// exactly in step with what is on screen. LineHeightStyle with Trim.None and a
// centered alignment makes each line exactly lineHeight tall, with the extra
// space split above and below the text.
val bufferTextStyle = remember(displaySettings.fontSize, displaySettings.fontId, density) {
val base = androidx.compose.ui.text.TextStyle(
fontFamily = AppFonts.familyFor(displaySettings.fontId),
fontSize = displaySettings.fontSize.sp
)
val naturalPx = textMeasurer.measure(text = "Mg", style = base).size.height
val spacedLine = with(density) { naturalPx.toSp() } + (displaySettings.fontSize * LINE_SPACING_EXTRA).sp
base.copy(
lineHeight = spacedLine,
lineHeightStyle = androidx.compose.ui.text.style.LineHeightStyle(
alignment = androidx.compose.ui.text.style.LineHeightStyle.Alignment.Center,
trim = androidx.compose.ui.text.style.LineHeightStyle.Trim.None
)
).size.height
)
}
val lineHeightPx = remember(bufferTextStyle, density) {
textMeasurer.measure(text = "Mg", style = bufferTextStyle).size.height
}
val lineHeightDp = with(density) { lineHeightPx.toDp() }
// Ruled out (see task: newest-message-missing investigation) as the
@@ -885,10 +903,7 @@ fun MessageScrollback(
// offset correction through stickToBottom's own effect instead of a
// second independent one.
val textStyle = androidx.compose.ui.text.TextStyle(
fontFamily = AppFonts.familyFor(displaySettings.fontId),
fontSize = displaySettings.fontSize.sp
)
val textStyle = bufferTextStyle
val selection = selectionState.selection
Column(modifier = Modifier.fillMaxSize()) {
@@ -1114,6 +1129,11 @@ fun MessageScrollback(
}
}
// Extra vertical space added to every buffer line, as a fraction of the font size, on top of
// the font's natural line height. 0.30 is a modest loosening; raise it for more air between
// lines (0.45 is roomy), lower it for less. Applies to every font in the font list.
private const val LINE_SPACING_EXTRA = 0.30f
// Reports this element's height as a whole number of text lines ([linePx] each): rounded up
// for image slots (the picture is never cut), to the nearest line for text rows (a wrapped
// message can measure a pixel or two off an exact multiple). Content is drawn from the top.