OXYGENHUB

The widget's counts sit in its header, beside the title, so the lines below cannot push them off (refs #33) fb420bbdb058

Author
Andy McCall @andymccall <[email protected]>
via
agent agent:claude@andymccall <[email protected]> · keyless, under your grant for changes,refs,seal · key df1de709439e
When
· 2026-11-01 21:36 UTC
Signature
◈ sealed by agent:claude@andymccall
Hash
fb420bbdb05847be50532b6e23a7fa3d081b95072e36733a6eb14545bc06452f
Depends on
1b7703ec4b02 57c0824300db 6823c243eaac 943c54cf6a56 aa627197ec18 b610bc6eeab7
Depended on by
d2e553089d82 739d58b12359
In bookmarks
main
In tags
v0.1.6 v0.1.7 v0.1.8 v0.1.9
Edits
11 atoms, 0 tree operations, 2 files

Browse the tree at this change

modified CHANGELOG.md +4 −0
1 1
# Changelog
2 2
3 +
## Unreleased
4 +
5 +
- **The widget's counts move to its header (#33):** with Needs you and Flow health below the runs, the row of counts at the foot was pushed out of the widget; unread messages, reviews and assigned issues now sit right of the title, where nothing can push them off, and the phone's runner job (while it serves) has the foot.
6 +
3 7
## 0.1.5 (2026-11-01)
4 8
5 9
- **Needs you and Flow health on the widget (#33):** the space under the runs shows the proposal at the head of your reviews and your newest assigned issue, a line each that opens it, and a strip of your last 30 runs (oldest on the left, each bar in its outcome's colour) with how many of the finished ones passed. The OxygenHub mark keeps its own colours again; only the word is white.
…
51 unchanged lines
modified app/src/main/java/io/oxygenhub/android/widget/HubWidget.kt +23 −18
…
142 unchanged lines
143 143
/**
144 144
 * A home screen widget (#28): your latest runs, unread notifications and
145 145
 * reviews waiting; a tap opens the app. The OxygenHub mark heads it and Your
146 -
 * sky is drawn behind it, at the widget's own size (#30); a row of counts
147 -
 * and the phone's runner job runs along its foot (#31).
146 +
 * sky is drawn behind it, at the widget's own size (#30); its counts sit
147 +
 * in its header, and the phone's runner job at its foot (#31, #33).
148 148
 */
149 149
class HubWidget : GlanceAppWidget() {
150 150
    /** Composed for each size the launcher shows it at, so the sky fits exactly. */
…
89 unchanged lines
240 240
@Composable
241 241
private fun Body(d: WidgetData, title: TextStyle, body: TextStyle, mute: TextStyle) {
242 242
    Column(GlanceModifier.fillMaxSize()) {
243 -
        Row(verticalAlignment = Alignment.CenterVertically) {
243 +
        // The counts sit in the header, right of the title, so the lines below can never push them off (#33).
244 +
        Row(GlanceModifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
244 245
            Image(ImageProvider(R.drawable.mark), contentDescription = null, modifier = GlanceModifier.size(width = 28.dp, height = 14.dp))
245 246
            Spacer(GlanceModifier.width(6.dp))
246 -
            Text("OxygenHub", style = title)
247 +
            Text("OxygenHub", style = title, modifier = GlanceModifier.defaultWeight())
248 +
            if (d.signedIn) Counts(d)
247 249
        }
248 250
        Spacer(GlanceModifier.height(6.dp))
249 251
        if (!d.signedIn) {
…
12 unchanged lines
262 264
        NeedsYou(d, body)
263 265
        Spacer(GlanceModifier.defaultWeight())
264 266
        Health(d, mute)
265 -
        Spacer(GlanceModifier.height(6.dp))
266 -
        Counts(d)
267 +
        Runner(d)
267 268
    }
268 269
}
269 270
270 271
/**
271 -
 * The row along the bottom (#31): unread messages, proposals to review and
272 +
 * The counts in the header (#31, #33): unread messages, proposals to review and
272 273
 * issues assigned, each an icon and its number (dimmed at zero, left out
273 -
 * when the hub cannot say), then what the phone runs while it serves as a
274 -
 * runner. Each opens its screen in the app.
274 +
 * when the hub cannot say). Each opens its screen in the app.
275 275
 */
276 276
@Composable
277 277
private fun Counts(d: WidgetData) {
278 -
    Row(GlanceModifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
278 +
    Row(verticalAlignment = Alignment.CenterVertically) {
279 279
        d.unread?.let { Count(R.drawable.widget_inbox, "unread", it, WidgetTaps.action("inbox")) }
280 280
        d.reviews?.let { n ->
281 281
            val r = d.onlyReview
…
3 unchanged lines
285 285
            val i = d.onlyAssigned
286 286
            Count(R.drawable.widget_issue, "assigned", n.toLong(), if (i != null) WidgetTaps.action("issue", i.repository, i.number) else WidgetTaps.action("dashboard"))
287 287
        }
288 -
        d.runnerJobs?.let { jobs ->
289 -
            Row(GlanceModifier.defaultWeight().clickable(WidgetTaps.action("account")), verticalAlignment = Alignment.CenterVertically) {
290 -
                Image(ImageProvider(R.drawable.widget_runner), contentDescription = "This phone runs", colorFilter = ColorFilter.tint(ok), modifier = GlanceModifier.size(14.dp))
291 -
                Spacer(GlanceModifier.width(4.dp))
292 -
                Text(runnerLine(jobs), style = TextStyle(color = GlanceTheme.colors.onSurface, fontSize = 12.sp), maxLines = 1)
293 -
            }
294 -
        }
288 +
    }
289 +
}
290 +
291 +
/** While the phone serves as a runner (#31): what it runs, under the health strip. */
292 +
@Composable
293 +
private fun Runner(d: WidgetData) {
294 +
    val jobs = d.runnerJobs ?: return
295 +
    Spacer(GlanceModifier.height(4.dp))
296 +
    Row(GlanceModifier.fillMaxWidth().clickable(WidgetTaps.action("account")), verticalAlignment = Alignment.CenterVertically) {
297 +
        Image(ImageProvider(R.drawable.widget_runner), contentDescription = "This phone runs", colorFilter = ColorFilter.tint(ok), modifier = GlanceModifier.size(13.dp))
298 +
        Spacer(GlanceModifier.width(6.dp))
299 +
        Text(runnerLine(jobs), style = TextStyle(color = GlanceTheme.colors.onSurface, fontSize = 12.sp), maxLines = 1)
295 300
    }
296 301
}
297 302
…
49 unchanged lines
347 352
@Composable
348 353
private fun Count(icon: Int, what: String, n: Long, open: Action) {
349 354
    val colour = if (n == 0L) GlanceTheme.colors.onSurfaceVariant else headline
350 -
    Row(GlanceModifier.padding(end = 14.dp).clickable(open), verticalAlignment = Alignment.CenterVertically) {
355 +
    Row(GlanceModifier.padding(start = 12.dp).clickable(open), verticalAlignment = Alignment.CenterVertically) {
351 356
        Image(ImageProvider(icon), contentDescription = "$n $what", colorFilter = ColorFilter.tint(colour), modifier = GlanceModifier.size(14.dp))
352 357
        Spacer(GlanceModifier.width(4.dp))
353 358
        Text("$n", style = TextStyle(color = colour, fontSize = 13.sp, fontWeight = FontWeight.Bold))
…
9 unchanged lines