diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index a1010f4..e45b245 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -33,8 +33,8 @@ android {
targetSdk = 35
// Bump both for every release installed on the phone — versionName for
// humans, versionCode so dumpsys/install history can tell builds apart.
- versionCode = 3
- versionName = "0.3.0"
+ versionCode = 4
+ versionName = "0.4.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/app/src/main/java/no/naiv/meddetsamme/ui/HistoryScreen.kt b/app/src/main/java/no/naiv/meddetsamme/ui/HistoryScreen.kt
index f2a9efa..ecd7c69 100644
--- a/app/src/main/java/no/naiv/meddetsamme/ui/HistoryScreen.kt
+++ b/app/src/main/java/no/naiv/meddetsamme/ui/HistoryScreen.kt
@@ -37,11 +37,21 @@ import java.time.format.DateTimeFormatter
import java.util.Locale
import no.naiv.meddetsamme.R
import no.naiv.meddetsamme.data.DoseLog
+import no.naiv.meddetsamme.data.DoseStatus
import no.naiv.meddetsamme.data.MedDatabase
import no.naiv.meddetsamme.domain.ScheduleEngine
private const val HISTORY_DAYS = 30L
+/**
+ * Status text in a *past* context. Differs from [label] only for PENDING: on
+ * the Today screen a due dose is legitimately "Venter", but a dose from days
+ * ago that was never acted on was simply not taken — "Venter" there is the
+ * nonsense this screen used to show.
+ */
+private val DoseStatus.historyLabel: String
+ get() = if (this == DoseStatus.PENDING) "Ikke tatt" else label
+
/**
* Adherence history: the last 30 days of dose logs, newest first, with
* 7- and 30-day adherence percentages on top. Read-only — corrections happen
@@ -130,22 +140,36 @@ fun HistoryScreen(nav: Nav) {
}
items(dayLogs, key = { it.first.id }) { (log, medName) ->
val time = timeFmt.format(Instant.ofEpochMilli(log.scheduledAtMillis).atZone(zone))
+ val taken = log.status == DoseStatus.TAKEN
Card(
modifier = Modifier.fillMaxWidth().semantics(mergeDescendants = true) {
- contentDescription = "$time, $medName, ${log.status.label}"
+ contentDescription = "$time, $medName, ${log.status.historyLabel}"
},
) {
Row(
Modifier.padding(horizontal = 12.dp, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically,
) {
+ // Green ✓ taken / red ✕ not-taken, first on the line for an
+ // at-a-glance scan down the day. Decorative here — the row's
+ // merged contentDescription already speaks the status.
+ Icon(
+ painterResource(if (taken) R.drawable.ic_check else R.drawable.ic_close),
+ contentDescription = null,
+ tint = if (taken) takenGreen() else missedRed(),
+ modifier = Modifier.padding(end = 12.dp),
+ )
Text(time, style = MaterialTheme.typography.titleSmall)
Text(
medName,
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.padding(start = 12.dp).weight(1f),
)
- DoseStatusBadge(log.status)
+ Text(
+ log.status.historyLabel,
+ style = MaterialTheme.typography.labelMedium,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
}
}
}
diff --git a/app/src/main/java/no/naiv/meddetsamme/ui/Theme.kt b/app/src/main/java/no/naiv/meddetsamme/ui/Theme.kt
index 1b0086f..2151745 100644
--- a/app/src/main/java/no/naiv/meddetsamme/ui/Theme.kt
+++ b/app/src/main/java/no/naiv/meddetsamme/ui/Theme.kt
@@ -37,6 +37,19 @@ fun MedDetSammeTheme(content: @Composable () -> Unit) {
MaterialTheme(colorScheme = scheme, typography = AppTypography, content = content)
}
+/**
+ * Fixed adherence semantics for the history glance icons: green = taken,
+ * red = not taken. Deliberately *not* derived from the (possibly dynamic)
+ * brand palette — a wallpaper-blue "primary" must never make a "taken" tick
+ * read as anything but green. Paired with a distinct shape (✓ vs ✕) and text
+ * so meaning never rests on colour alone (WCAG 1.4.1).
+ */
+@Composable
+fun takenGreen(): Color = if (isSystemInDarkTheme()) Color(0xFF7CC97F) else Color(0xFF2E7D32)
+
+@Composable
+fun missedRed(): Color = if (isSystemInDarkTheme()) Color(0xFFFFB4AB) else Color(0xFFBA1A1A)
+
// Manrope for headings/titles (friendly, confident), Inter for body/labels
// (built for UI legibility at small sizes). Both OFL, full æøå/µ coverage.
private val Manrope = FontFamily(
diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml
new file mode 100644
index 0000000..8b4fd8d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check.xml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_close.xml b/app/src/main/res/drawable/ic_close.xml
new file mode 100644
index 0000000..7184acd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_close.xml
@@ -0,0 +1,9 @@
+
+
+
+