Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
23 changes: 21 additions & 2 deletions app/src/main/java/dev/debene/gopher/ui/browser/TextViewer.kt
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 },
Expand All @@ -84,10 +90,23 @@ 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,
modifier = content,
)
}
}

/**
* 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)
5 changes: 5 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/4.txt
Original file line number Diff line number Diff line change
@@ -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.
Loading