From bb3502ed26953412a9d54f7358cab8b52cbc15e2 Mon Sep 17 00:00:00 2001 From: claude Date: Sat, 25 Jul 2026 17:00:23 +0200 Subject: [PATCH] =?UTF-8?q?Passhistoriken=20visar=20passl=C3=A4ngden=20i?= =?UTF-8?q?=20b=C3=A5de=20listan=20och=20detaljvyn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Manuell tidsrättning (durationSecondsOverride) vinner, annars slut − start. Format: '47 min' eller '1h 12m'. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Kf4MAbZ3c3B4Xy5XfuGsCP --- .../fitnessdroid/data/GymRepository.kt | 27 +++++++++++++++++-- .../ui/history/HistoryDetailScreen.kt | 5 +++- .../fitnessdroid/ui/history/HistoryScreen.kt | 4 +++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/eu/brassepc/fitnessdroid/data/GymRepository.kt b/app/src/main/java/eu/brassepc/fitnessdroid/data/GymRepository.kt index 60aabde..fd2301e 100644 --- a/app/src/main/java/eu/brassepc/fitnessdroid/data/GymRepository.kt +++ b/app/src/main/java/eu/brassepc/fitnessdroid/data/GymRepository.kt @@ -420,7 +420,7 @@ class GymRepository( /** Full detalj för ett avslutat pass. */ suspend fun fetchSessionDetail(id: Int): SessionDetail { val data = client.execute( - "query(\$id:Int!){gymSession(id:\$id){id name notes date startTime estimatedCalories gymSessionExercises{order exerciseType{name} sets{order reps weight distanceMeters durationSeconds rpe isWarmup}}}}", + "query(\$id:Int!){gymSession(id:\$id){id name notes date startTime endTime durationSecondsOverride estimatedCalories gymSessionExercises{order exerciseType{name} sets{order reps weight distanceMeters durationSeconds rpe isWarmup}}}}", buildJsonObject { put("id", id) }, auth.bearerToken(), ) @@ -432,6 +432,11 @@ class GymRepository( ?: o["startTime"]?.jsonPrimitive?.contentOrNull()).orEmpty(), notes = o["notes"]?.jsonPrimitive?.contentOrNull(), calories = o["estimatedCalories"]?.jsonPrimitive?.doubleOrNull, + durationMinutes = durationMinutes( + o["durationSecondsOverride"]?.jsonPrimitive?.intOrNull, + o["startTime"]?.jsonPrimitive?.contentOrNull(), + o["endTime"]?.jsonPrimitive?.contentOrNull(), + ), exercises = o["gymSessionExercises"]!!.jsonArray .sortedBy { it.jsonObject["order"]?.jsonPrimitive?.intOrNull ?: 0 } .map { e -> @@ -621,7 +626,7 @@ class GymRepository( /** Historik hämtas direkt (ingen offline-garanti i v1). */ suspend fun fetchHistory(limit: Int = 30): List { val data = client.execute( - "query(\$s:String,\$l:Int){gymSessions(status:\$s,limit:\$l){id name date startTime durationSecondsOverride estimatedCalories gymSessionExercises{id sets{id weight reps}}}}", + "query(\$s:String,\$l:Int){gymSessions(status:\$s,limit:\$l){id name date startTime endTime durationSecondsOverride estimatedCalories gymSessionExercises{id sets{id weight reps}}}}", buildJsonObject { put("s", "completed"); put("l", limit) }, auth.bearerToken(), ) @@ -641,9 +646,25 @@ class GymRepository( setCount = sets.size, volumeKg = volume, calories = o["estimatedCalories"]?.jsonPrimitive?.doubleOrNull, + durationMinutes = durationMinutes( + o["durationSecondsOverride"]?.jsonPrimitive?.intOrNull, + o["startTime"]?.jsonPrimitive?.contentOrNull(), + o["endTime"]?.jsonPrimitive?.contentOrNull(), + ), ) } } + + /** Passlängd i minuter: manuell rättning vinner, annars slut − start. */ + private fun durationMinutes(overrideSeconds: Int?, start: String?, end: String?): Int? { + overrideSeconds?.let { return it / 60 } + if (start == null || end == null) return null + return runCatching { + val s = java.time.OffsetDateTime.parse(start) + val e = java.time.OffsetDateTime.parse(end) + java.time.Duration.between(s, e).toMinutes().toInt().takeIf { it >= 0 } + }.getOrNull() + } } data class HistoryItem( @@ -654,6 +675,7 @@ data class HistoryItem( val setCount: Int, val volumeKg: Double, val calories: Double?, + val durationMinutes: Int? = null, ) data class HistorySet( @@ -672,6 +694,7 @@ data class SessionDetail( val date: String, val notes: String?, val calories: Double?, + val durationMinutes: Int? = null, val exercises: List, ) diff --git a/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryDetailScreen.kt b/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryDetailScreen.kt index f11801e..bef99e7 100644 --- a/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryDetailScreen.kt +++ b/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryDetailScreen.kt @@ -162,7 +162,10 @@ fun HistoryDetailScreen( Text( buildString { append(d.date.take(10)) - stats?.durationMinutes?.let { append(" · $it min") } + (d.durationMinutes ?: stats?.durationMinutes)?.let { + append(" · ") + append(if (it >= 60) "${it / 60}h ${it % 60}m" else "$it min") + } if (stats != null) { append(" · ${stats.totalSets} set · ${stats.totalVolumeKg.toInt()} kg volym") } diff --git a/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryScreen.kt b/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryScreen.kt index 16f2e7c..416e717 100644 --- a/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryScreen.kt +++ b/app/src/main/java/eu/brassepc/fitnessdroid/ui/history/HistoryScreen.kt @@ -116,6 +116,10 @@ fun HistoryScreen( } Text( buildString { + item.durationMinutes?.let { + append(if (it >= 60) "${it / 60}h ${it % 60}m" else "$it min") + append(" · ") + } append("${item.exerciseCount} övningar · ${item.setCount} set") if (item.volumeKg > 0) append(" · ${item.volumeKg.toInt()} kg volym") item.calories?.let { append(" · ${it.toInt()} kcal") }