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
10 changes: 9 additions & 1 deletion Strand/Screens/StressView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,15 @@ struct StressView: View {
private func markerTile(label: LocalizedStringKey, value: String, delta: Double?, accent: Color, higherIsStress: Bool) -> some View {
let deltaText: String?
let deltaColor: Color
if let delta, abs(delta) >= 0.5 {
// NO CHIP for a missing delta, rather than a claim we cannot make (#2145). It is nil when
// today has no reading or there is no 30-day baseline to stand one against, and both fell
// through to the at-baseline chip: a tile with no reading read "— at baseline", and a
// first-week tile put a reading exactly on a baseline that did not exist yet. StatTile draws
// the pill only for a non-nil delta, so nil is already the way to say nothing here.
if delta == nil {
deltaText = nil
deltaColor = StrandPalette.textTertiary
} else if let delta, abs(delta) >= 0.5 {
let up = delta > 0
let isStressful = (up == higherIsStress)
deltaText = String(localized: "\(up ? "+" : "−")\(Int(abs(delta).rounded())) vs base")
Expand Down
6 changes: 6 additions & 0 deletions android/app/src/main/java/com/noop/ui/Components.kt
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,12 @@ fun StatTile(
// intrinsic size. Used by narrow two-column tiles where a wide chip (e.g. "1234 kcal" or
// "+10 vs base") would otherwise starve the reading column and clip its value. The default
// keeps callers that have enough width exactly as they were.
//
// NO CALLER PASSES TRUE ANY MORE, and reach for a shorter chip before reaching for this (#2145).
// It splits the row evenly, which starves BOTH sides once the chip is wide: the value is weighted
// with fill = true, so it is held to exactly its share however little the chip turns out to need.
// The stress marker tiles clipped their reading AND their chip this way. The workouts feed went
// full width, the stress tiles shortened the chip; both then wanted the natural-width path.
compactDelta: Boolean = false,
) {
// Each tile borrows its accent as a faint card wash, so a metric reads as part of its
Expand Down
35 changes: 27 additions & 8 deletions android/app/src/main/java/com/noop/ui/StressScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1199,15 +1199,29 @@ private fun MarkerTile(
higherIsStress: Boolean,
modifier: Modifier = Modifier,
) {
val deltaText: String
val deltaText: String?
val deltaColor: Color
if (delta != null && kotlin.math.abs(delta) >= 0.5) {
if (delta == null) {
// NO CHIP, rather than a claim we cannot make. The delta is null when today has no reading or
// there is no 30-day baseline to stand it against, and both of those used to render the
// at-baseline chip: a tile with no reading read "— at baseline", and a first-week tile said a
// reading sat exactly on a baseline that did not exist yet. StatTile draws no chip for null.
deltaText = null
deltaColor = Palette.textTertiary
} else if (kotlin.math.abs(delta) >= 0.5) {
val up = delta > 0
val isStressful = (up == higherIsStress)
deltaText = "${if (up) "+" else "−"}${kotlin.math.abs(delta).roundToInt()} vs base"
// The magnitude alone, signed. TrendChip reads the sign to pick its ▲/▼, and the section
// header two lines up already says "vs 30-day baseline", so spelling "vs base" again inside
// the chip spent width on a word the reader has just been given (#2145).
deltaText = "${if (up) "+" else "−"}${kotlin.math.abs(delta).roundToInt()}"
deltaColor = if (isStressful) Palette.statusWarning else Palette.statusPositive
} else {
deltaText = "at baseline"
// "at baseline" shortens the same way: the header supplies "baseline", the chip supplies the
// distance from it, which is none. No glyph, TrendChip showing one only for a signed value.
// Reached only with a real delta now, so it says "measured, and it is zero" rather than
// standing in for "nothing to measure".
deltaText = "±0"
deltaColor = Palette.textTertiary
}
StatTile(
Expand All @@ -1217,10 +1231,15 @@ private fun MarkerTile(
accent = accent,
delta = deltaText,
deltaColor = deltaColor,
// #492 item 5: on narrow two-column cards the intrinsic-width "vs base" chip used to consume
// nearly the whole row and leave the reading as "4…" / "73…". Share the row evenly so the real
// physiological value stays intact; the explanatory chip is the element allowed to ellipsize.
compactDelta = true,
// NO compactDelta, deliberately (#2145). #492 item 5 added it because the intrinsic-width
// "vs base" chip ate the row and left the reading as "4…", and an even split then starved
// BOTH sides on a two-up tile: "53 bpm" and "+7 vs base" each want more than half, so the
// field saw "53 …" beside "▲ +7 vs …". An even split cannot be the answer, because a weighted
// child with fill = true is held to exactly its share, so the value stays at half however
// little the chip needs. The chip is now the sign and at most three digits at 12sp, so it
// measures under 45dp including its pill padding, and the weighted value takes everything
// else. The old chip wanted about 90dp of a row that has about 140dp to give, which is what
// made it starve the reading in the first place.
)
}

Expand Down