From f6f59216663d80c6a0c1408a2db569b3d32bb53a Mon Sep 17 00:00:00 2001 From: Felipe Benedet Date: Wed, 29 Jul 2026 14:28:58 -0500 Subject: [PATCH] fix(ui): render ANSI pages on a black backdrop, bump to 2.0.4 AnsiParser emits the fixed xterm palette regardless of the app theme, and TextViewer painted it onto the Material surface. On the light theme the light end of that palette -- grey argb(229,229,229) and white argb(255,255,255) -- came out white-on-near-white; an F-Droid reviewer found the station labels on a colour CTA map effectively invisible (fdroiddata!41663). Dark mode was fine. Give ANSI content the background its colours were chosen against instead of remapping the palette, which would distort the art and would need separate handling for the 256-colour and truecolour paths. Pure black rather than a dark grey because it matches the palette's own colour 0, so ESC[40m fills blend instead of showing as boxes. Uncoloured runs now default to xterm colour 7 rather than Material onSurface, which would be dark-on-black. Plain text pages are untouched and still follow the theme. --- app/build.gradle.kts | 4 ++-- .../debene/gopher/ui/browser/TextViewer.kt | 23 +++++++++++++++++-- .../metadata/android/en-US/changelogs/4.txt | 5 ++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/4.txt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ac4e667..4407614 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { applicationId = "dev.debene.gopher" minSdk = 24 targetSdk = 35 - versionCode = 3 - versionName = "2.0.3" + versionCode = 4 + versionName = "2.0.4" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/dev/debene/gopher/ui/browser/TextViewer.kt b/app/src/main/java/dev/debene/gopher/ui/browser/TextViewer.kt index 537cab1..f2da3a7 100644 --- a/app/src/main/java/dev/debene/gopher/ui/browser/TextViewer.kt +++ b/app/src/main/java/dev/debene/gopher/ui/browser/TextViewer.kt @@ -1,5 +1,6 @@ package dev.debene.gopher.ui.browser +import androidx.compose.foundation.background import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize @@ -35,7 +36,8 @@ import androidx.compose.ui.unit.dp * - Long lines **wrap** by default (readable prose). A toggle switches to no-wrap + * horizontal scroll for fixed-width ASCII art / maps. * - **ANSI** color codes (`ESC[…m`) in `.ansi` files are parsed into colored text instead - * of showing as escape-sequence gibberish. + * of showing as escape-sequence gibberish. ANSI pages render on a forced black backdrop + * (see [AnsiBackground]) rather than the Material surface. */ @Composable fun TextViewer(text: String, modifier: Modifier = Modifier) { @@ -64,7 +66,11 @@ fun TextViewer(text: String, modifier: Modifier = Modifier) { val vScroll = rememberScrollState() val hScroll = rememberScrollState() - Column(modifier.fillMaxSize()) { + Column( + modifier + .fillMaxSize() + .then(if (isAnsi) Modifier.background(AnsiBackground) else Modifier) + ) { FilledIconToggleButton( checked = wrap, onCheckedChange = { wrap = it }, @@ -84,6 +90,7 @@ fun TextViewer(text: String, modifier: Modifier = Modifier) { Text( text = annotated, + color = if (isAnsi) AnsiForeground else Color.Unspecified, fontFamily = FontFamily.Monospace, style = MaterialTheme.typography.bodySmall, softWrap = wrap, @@ -91,3 +98,15 @@ fun TextViewer(text: String, modifier: Modifier = Modifier) { ) } } + +/** + * ANSI art is authored for a black terminal, and [AnsiParser] emits the fixed xterm palette + * (unaware of the app theme). Painting that onto the light Material surface makes the light end + * of the palette — grey `argb(229,229,229)` and white `argb(255,255,255)` — near-invisible, so + * ANSI pages get the background their colors were chosen against. Pure black matches the + * palette's own color 0, so `ESC[40m` fills blend instead of showing as boxes. + */ +private val AnsiBackground = Color(0xFF000000) + +/** Terminal default foreground (xterm color 7) for runs with no explicit SGR color. */ +private val AnsiForeground = Color(0xFFE5E5E5) diff --git a/fastlane/metadata/android/en-US/changelogs/4.txt b/fastlane/metadata/android/en-US/changelogs/4.txt new file mode 100644 index 0000000..36e0250 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/4.txt @@ -0,0 +1,5 @@ +Readable ANSI art on the light theme. + +ANSI pages now render on a black backdrop, the background the xterm palette +they use was drawn against. Previously the light end of that palette (grey and +white text) was painted onto the light Material surface and was near-invisible.