ui: drop bio justification and normalize cached biographies

Read normalization heals biographies cached before line breaks were preserved, without waiting for a refresh.
This commit is contained in:
austinried
2026-10-19 13:55:16 +00:00
parent 028685d62b
commit 77190a2af1
4 changed files with 17 additions and 61 deletions
@@ -35,6 +35,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
@@ -360,7 +361,11 @@ class LibraryRepository(
fun artistBio(
sourceId: Long,
artistId: String,
): Flow<ArtistBio?> = db.libraryDao().artistBio(sourceId, artistId)
): Flow<ArtistBio?> =
db
.libraryDao()
.artistBio(sourceId, artistId)
.map { bio -> bio?.copy(biography = normalizeBiography(bio.biography)) }
suspend fun refreshArtistBio(
sourceId: Long,
@@ -605,16 +605,8 @@ private fun ArtistBio(
Column(Modifier.fillMaxWidth()) {
bioLines.lines.forEachIndexed { index, line ->
val isControl = index == bioLines.lines.lastIndex && (bioLines.more || bioLines.less)
val nextBlank = index == bioLines.lines.lastIndex || bioLines.lines[index + 1].text.isBlank()
val available = bioLineWidth(index, fullWidth, reserve, reserveLines)
val displayLine =
if (!nextBlank && line.text.isNotBlank() && line.spanStyles.isEmpty()) {
justifyBioLine(line, measurer, style, available)
} else {
line
}
Text(
text = displayLine,
text = line,
style = style,
color = color,
maxLines = 1,
@@ -737,35 +729,6 @@ private fun appendBioControl(
lines += control
}
internal fun justifyBioLine(
line: AnnotatedString,
measurer: TextMeasurer,
style: TextStyle,
available: Int,
): AnnotatedString {
if (line.spanStyles.isNotEmpty()) return line
val parts = line.text.split(' ')
if (parts.size < 2) return line
val spaceWidth = measurer.measure(AnnotatedString(" "), style, maxLines = 1).size.width
if (spaceWidth <= 0) return line
val extra = available - measurer.measure(line, style, maxLines = 1).size.width
val spaces = extra / spaceWidth
if (spaces <= 0) return line
val gaps = parts.size - 1
val perGap = spaces / gaps
val remainder = spaces % gaps
return AnnotatedString(
buildString {
parts.forEachIndexed { index, part ->
append(part)
if (index < gaps) {
repeat(1 + perGap + if (index < remainder) 1 else 0) { append(' ') }
}
}
},
)
}
internal data class BioLines(
val lines: List<AnnotatedString>,
val more: Boolean,