diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-06-29 07:09:43 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-06-29 07:09:43 +0000 |
| commit | dacb710fc4ea63baa05cc47016def3849b9db5fa (patch) | |
| tree | cc86831a3a9c950ec0909975ce77bdb485cf5589 /android/app/src | |
| parent | 3b632feb80a1d6c95836981aad602e2dff4f6b63 (diff) | |
feat: add standalone task detail page for Android widget deep-links
Adds GET /task?id=xxx&source=xxx route that renders a full mobile-friendly
task detail page (session-protected). Widget task rows now open this page
when tapped. HandleUpdateTask redirects back to the page after a non-HTMX
save. Android: threads serverUrl through composable chain to TaskRow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'android/app/src')
| -rw-r--r-- | android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt b/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt index f8d8ae1..dcb73d5 100644 --- a/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt +++ b/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt @@ -46,9 +46,10 @@ class DootWidget : GlanceAppWidget() { val items = parseItems(prefs) val now = prefs[Keys.NOW]?.let { runCatching { Instant.parse(it) }.getOrNull() } ?: Instant.now() + val serverUrl = prefs[Keys.SERVER_URL]?.trimEnd('/') ?: "" provideContent { - WidgetRoot(items, now) + WidgetRoot(items, now, serverUrl) } } @@ -59,7 +60,7 @@ class DootWidget : GlanceAppWidget() { } @Composable -fun WidgetRoot(items: List<WidgetItem>, now: Instant) { +fun WidgetRoot(items: List<WidgetItem>, now: Instant, serverUrl: String = "") { val zone = ZoneId.systemDefault() val nowZoned: ZonedDateTime = now.atZone(zone) val allScheduled = items.filter { it.start != null }.sortedBy { Instant.parse(it.start!!) } @@ -89,7 +90,7 @@ fun WidgetRoot(items: List<WidgetItem>, now: Instant) { } for (hour in gridStart..gridEnd) { - HourRow(hour, nowZoned, scheduledEvents, fragments, zone) + HourRow(hour, nowZoned, scheduledEvents, fragments, zone, serverUrl) } } } @@ -100,7 +101,8 @@ fun HourRow( nowZoned: ZonedDateTime, scheduled: List<WidgetItem>, fragments: List<TaskFragment>, - @Suppress("UNUSED_PARAMETER") zone: ZoneId + @Suppress("UNUSED_PARAMETER") zone: ZoneId, + serverUrl: String = "" ) { val hourStart = nowZoned.withHour(hour).withMinute(0).withSecond(0).withNano(0).toInstant() val hourEnd = hourStart.plus(1, ChronoUnit.HOURS) @@ -147,7 +149,7 @@ fun HourRow( } fragsHere.forEach { frag -> - TaskFragmentBlock(frag) + TaskFragmentBlock(frag, serverUrl) } } } @@ -183,7 +185,7 @@ fun EventBlock(event: WidgetItem, isPast: Boolean) { } @Composable -fun TaskFragmentBlock(fragment: TaskFragment) { +fun TaskFragmentBlock(fragment: TaskFragment, serverUrl: String = "") { Column( modifier = GlanceModifier .fillMaxWidth() @@ -199,17 +201,25 @@ fun TaskFragmentBlock(fragment: TaskFragment) { modifier = GlanceModifier.padding(start = 8.dp, top = 3.dp, bottom = 1.dp) ) fragment.slots.forEach { slot -> - TaskRow(slot.task) + TaskRow(slot.task, serverUrl) } } } @Composable -fun TaskRow(task: WidgetItem) { +fun TaskRow(task: WidgetItem, serverUrl: String = "") { + val tapAction = if (serverUrl.isNotEmpty()) { + val url = "$serverUrl/task?id=${task.id}&source=${task.source}" + actionStartActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) + } else { + null + } + val rowModifier = GlanceModifier + .fillMaxWidth() + .padding(horizontal = 8.dp, vertical = 5.dp) + .let { if (tapAction != null) it.clickable(tapAction) else it } Row( - modifier = GlanceModifier - .fillMaxWidth() - .padding(horizontal = 8.dp, vertical = 5.dp), + modifier = rowModifier, verticalAlignment = Alignment.CenterVertically ) { if (task.completable) { |
