mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
fix: don't offer to re-share an already-published workout
My Fitness builds its log from both Health Connect and the user's own kind 1301 events, but every row in Recent workouts carried a "Share this workout" button. On a relay-sourced entry that opened the composer prefilled and one tap from publishing a second kind 1301 for the same effort. WorkoutOrigin already recorded where each workout came from and nothing read it; the button is now gated on it. Also tidies the dashboard's copy and its empty cells: - This week showed "0 kcal" (and would show "0.0 mi" for a strength-only week) where the weekly-average card already omits metrics the window has none of. Distance and calories now appear only when this week or last week has one, so a drop to zero still renders its trend. - The footer note explained the four-week window as a Health Connect limit and claimed nothing leaves the phone. Neither holds once the log is fed by published events, which by definition already left. - Drops my_fitness_unavailable, unused since the log stopped depending on Health Connect, so it isn't sent out for translation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c5526f3575
commit
ec8a5fa573
+62
-38
@@ -56,6 +56,7 @@ import androidx.lifecycle.compose.LifecycleResumeEffect
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.commons.fitness.DetectedWorkout
|
||||
import com.vitorpamplona.amethyst.commons.fitness.WorkoutOrigin
|
||||
import com.vitorpamplona.amethyst.commons.fitness.WorkoutStats
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
@@ -284,34 +285,50 @@ private fun ThisWeekCard(
|
||||
miles: Boolean,
|
||||
) {
|
||||
SectionCard(stringRes(Res.string.my_fitness_this_week)) {
|
||||
StatGrid(
|
||||
listOf(
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_workouts),
|
||||
report.thisWeek.workoutCount.toString(),
|
||||
null,
|
||||
WorkoutStats.percentChange(report.thisWeek.workoutCount.toDouble(), report.previousWeek.workoutCount.toDouble()),
|
||||
),
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_time),
|
||||
formatDuration(report.thisWeek.durationSeconds),
|
||||
null,
|
||||
WorkoutStats.percentChange(report.thisWeek.durationSeconds.toDouble(), report.previousWeek.durationSeconds.toDouble()),
|
||||
),
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_distance),
|
||||
formatDistanceValue(report.thisWeek.distanceMeters, miles),
|
||||
distanceUnit(miles),
|
||||
WorkoutStats.percentChange(report.thisWeek.distanceMeters, report.previousWeek.distanceMeters),
|
||||
),
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_calories),
|
||||
report.thisWeek.calories.toString(),
|
||||
stringRes(Res.string.my_fitness_unit_kcal),
|
||||
WorkoutStats.percentChange(report.thisWeek.calories.toDouble(), report.previousWeek.calories.toDouble()),
|
||||
),
|
||||
),
|
||||
)
|
||||
// Workouts and time are always worth a cell. Distance and calories are not: a week of
|
||||
// strength work has neither, and a column of zeroes reads as missing data rather than
|
||||
// as "this activity doesn't have that metric". Last week still counts, so a drop to
|
||||
// zero keeps its cell and shows the fall.
|
||||
val cells =
|
||||
buildList {
|
||||
add(
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_workouts),
|
||||
report.thisWeek.workoutCount.toString(),
|
||||
null,
|
||||
WorkoutStats.percentChange(report.thisWeek.workoutCount.toDouble(), report.previousWeek.workoutCount.toDouble()),
|
||||
),
|
||||
)
|
||||
add(
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_time),
|
||||
formatDuration(report.thisWeek.durationSeconds),
|
||||
null,
|
||||
WorkoutStats.percentChange(report.thisWeek.durationSeconds.toDouble(), report.previousWeek.durationSeconds.toDouble()),
|
||||
),
|
||||
)
|
||||
if (report.thisWeek.distanceMeters > 0 || report.previousWeek.distanceMeters > 0) {
|
||||
add(
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_distance),
|
||||
formatDistanceValue(report.thisWeek.distanceMeters, miles),
|
||||
distanceUnit(miles),
|
||||
WorkoutStats.percentChange(report.thisWeek.distanceMeters, report.previousWeek.distanceMeters),
|
||||
),
|
||||
)
|
||||
}
|
||||
if (report.thisWeek.calories > 0 || report.previousWeek.calories > 0) {
|
||||
add(
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_calories),
|
||||
report.thisWeek.calories.toString(),
|
||||
stringRes(Res.string.my_fitness_unit_kcal),
|
||||
WorkoutStats.percentChange(report.thisWeek.calories.toDouble(), report.previousWeek.calories.toDouble()),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
StatGrid(cells)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,14 +350,16 @@ private fun WindowTotalsCard(
|
||||
val cells =
|
||||
buildList {
|
||||
add(StatCell(stringRes(Res.string.my_fitness_time), formatDuration(report.weeklyAverage.durationSeconds), null, null))
|
||||
add(
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_distance),
|
||||
formatDistanceValue(report.weeklyAverage.distanceMeters, miles),
|
||||
distanceUnit(miles),
|
||||
null,
|
||||
),
|
||||
)
|
||||
if (report.windowTotals.distanceMeters > 0) {
|
||||
add(
|
||||
StatCell(
|
||||
stringRes(Res.string.my_fitness_distance),
|
||||
formatDistanceValue(report.weeklyAverage.distanceMeters, miles),
|
||||
distanceUnit(miles),
|
||||
null,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (report.windowTotals.steps > 0) {
|
||||
add(StatCell(stringRes(Res.string.my_fitness_steps), report.weeklyAverage.steps.toString(), null, null))
|
||||
}
|
||||
@@ -492,8 +511,13 @@ private fun RecentWorkouts(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
TextButton(onClick = { onShare(workout, label) }) {
|
||||
Text(stringRes(Res.string.my_fitness_share), style = MaterialTheme.typography.labelMedium)
|
||||
// Only what is still unpublished can be shared. A workout that came
|
||||
// back from the relays is already posted: offering to share it again
|
||||
// would publish a second kind 1301 for the same effort.
|
||||
if (workout.origin != WorkoutOrigin.PUBLISHED) {
|
||||
TextButton(onClick = { onShare(workout, label) }) {
|
||||
Text(stringRes(Res.string.my_fitness_share), style = MaterialTheme.typography.labelMedium)
|
||||
}
|
||||
}
|
||||
}
|
||||
Text(
|
||||
|
||||
@@ -685,7 +685,7 @@
|
||||
<string name="health_connect_rationale_privacy_policy">Read the full privacy policy</string>
|
||||
<string name="my_fitness_title">My Fitness</string>
|
||||
<string name="my_fitness_window">Last 4 weeks</string>
|
||||
<string name="my_fitness_window_note">Health Connect serves the last 30 days, so Amethyst summarises four whole weeks. Nothing here leaves your phone.</string>
|
||||
<string name="my_fitness_window_note">The last four whole weeks of your training: the workouts you have published, plus anything Health Connect records on this phone. Amethyst works the summary out on the device and publishes none of it.</string>
|
||||
<string name="my_fitness_this_week">This week</string>
|
||||
<string name="my_fitness_vs_last_week">vs last week</string>
|
||||
<string name="my_fitness_weekly_average">Weekly average</string>
|
||||
@@ -708,7 +708,6 @@
|
||||
<string name="my_fitness_best_highest_heart_rate">Highest heart rate</string>
|
||||
<string name="my_fitness_recent">Recent workouts</string>
|
||||
<string name="my_fitness_empty">Nothing logged in the last 4 weeks. Workouts you post, and any your watch records, show up here.</string>
|
||||
<string name="my_fitness_unavailable">Health Connect is not available on this device, so Amethyst has no workouts to summarise.</string>
|
||||
<string name="my_fitness_connect_title">Track your training</string>
|
||||
<string name="my_fitness_connect_message">Connect Health Connect to see your weekly totals, week-over-week trend, best efforts and training streak. Everything stays on your phone.</string>
|
||||
<string name="my_fitness_connect_banner">Connect Health Connect to add the workouts your watch records, with heart rate, steps and climb.</string>
|
||||
|
||||
Reference in New Issue
Block a user