Skip to content

Commit 2356726

Browse files
committed
fix(overview): Call an empty case not enough on older models
AirPods Gen 1 and Gen 2 publish their case capacity as a lower bound, and the adequacy check let that guard run before any zero-reading check. At a 0% case those two models rendered the definite "no charges left" text in the neutral uncertainty colour while the screen reader hedged with "may not be enough", contradicting the same node three ways. The empty reading is now handled before the lower-bound guard. It sits after the "enough" branch, which a zero reading can never satisfy, so it cannot mask a positive claim. The lower-bound rule exists to avoid underselling a case whose published capacity is only a floor, and an empty case has nothing to undersell. Fixes review finding F4
1 parent 03c0991 commit 2356726

3 files changed

Lines changed: 23 additions & 5 deletions

File tree

app/src/main/java/eu/darken/capod/monitor/core/battery/CaseCharges.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ data class CaseCharges(
3333
*
3434
* The interval excludes its upper end, so an upper end of exactly one charge is still short of one.
3535
*
36-
* A spec that is itself a lower bound has no upper end, so it can never claim "not enough".
36+
* A spec that is itself a lower bound has no upper end, so it can never claim "not enough" — except
37+
* at an empty reading, where a floor on the published capacity has nothing left to undersell.
3738
*
3839
* The wording follows the whole interval, not its pessimistic end: an uncertain one rounds to a
3940
* single charge, or names no number at all ([CaseCharges.Display.UNCERTAIN]) when the spec is a
@@ -52,6 +53,7 @@ fun caseCharges(spec: PodModel.CaseSpec?, reading: BatteryReading?): CaseCharges
5253

5354
val adequacy = when {
5455
lowest >= 1f -> CaseCharges.Adequacy.ENOUGH
56+
reading.percent == 0f -> CaseCharges.Adequacy.NOT_ENOUGH
5557
spec.isLowerBound -> CaseCharges.Adequacy.UNCERTAIN
5658
highest <= 1f -> CaseCharges.Adequacy.NOT_ENOUGH
5759
else -> CaseCharges.Adequacy.UNCERTAIN

app/src/test/java/eu/darken/capod/main/ui/overview/cards/CaseChargesLineTest.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ class CaseChargesLineTest : BaseComposeRobolectricTest() {
128128
.assertCountEquals(0)
129129
}
130130

131+
@Test
132+
fun `an empty case on an open ended spec still reads as not enough`() {
133+
setCard(device(case = 0f, model = PodModel.AIRPODS_GEN1))
134+
135+
assertAdequacy(
136+
context.getString(R.string.battery_case_charges_empty),
137+
R.string.battery_case_charges_state_not_enough_cd,
138+
)
139+
}
140+
131141
@Test
132142
fun `the line survives a right-to-left layout`() {
133143
setCard(device(case = 0.60f)) { card ->

app/src/test/java/eu/darken/capod/monitor/core/battery/CaseChargesTest.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class CaseChargesTest : BaseTest() {
8282
}
8383

8484
@Test
85-
fun `a lower bound spec never claims not enough`() {
85+
fun `a lower bound spec above empty never claims not enough`() {
8686
// 3.8 x 0.25 = 0.95 — a confident "not enough" for a case that may well hold more
8787
charges(lowerBound, 0.25f, percent)!!.adequacy shouldBe CaseCharges.Adequacy.UNCERTAIN
8888
charges(lowerBound, 0.01f, percent)!!.adequacy shouldBe CaseCharges.Adequacy.UNCERTAIN
@@ -138,8 +138,14 @@ class CaseChargesTest : BaseTest() {
138138
}
139139

140140
@Test
141-
fun `an empty case renders as empty`() {
142-
charges(exact, 0f, percent)!!.display shouldBe CaseCharges.Display.EMPTY
143-
charges(lowerBound, 0f, decile)!!.display shouldBe CaseCharges.Display.EMPTY
141+
fun `an empty case renders as empty and claims not enough`() {
142+
val exactly = charges(exact, 0f, percent)!!
143+
exactly.display shouldBe CaseCharges.Display.EMPTY
144+
exactly.adequacy shouldBe CaseCharges.Adequacy.NOT_ENOUGH
145+
146+
// an empty case holds nothing for the open ended spec to undersell
147+
val floored = charges(lowerBound, 0f, decile)!!
148+
floored.display shouldBe CaseCharges.Display.EMPTY
149+
floored.adequacy shouldBe CaseCharges.Adequacy.NOT_ENOUGH
144150
}
145151
}

0 commit comments

Comments
 (0)