summaryrefslogtreecommitdiff
path: root/android/app/src
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-06-29 07:09:43 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-06-29 07:09:43 +0000
commitdacb710fc4ea63baa05cc47016def3849b9db5fa (patch)
treecc86831a3a9c950ec0909975ce77bdb485cf5589 /android/app/src
parent3b632feb80a1d6c95836981aad602e2dff4f6b63 (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.kt32
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) {