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.