Skip to content

Add a Distance field to the manual add/edit workout sheet (#1195) - #1203

Merged
ryanbr merged 1 commit into
mainfrom
manual-workout-distance-1195
Aug 10, 2026
Merged

ryanbr merged 1 commit into
mainfrom
manual-workout-distance-1195

Conversation

@ryanbr

@ryanbr ryanbr commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Second follow-up from #1195 (after #1202 added live distance/pace). The issue asks for manual distance editing — "manually add or edit the total distance after a workout is completed." The manual add/edit sheet already edits sport / start / duration / avg HR / calories, and the workout row already stores distanceM and shows it in the detail view — it just wasn't editable. This adds the field.

What changed

  • buildManualRow (both platforms) — accepts an optional distanceM (default nil), validated 0–1,000 km (covers any single session; an Ironman bike is 180 km). preservingCaptured now takes distanceM from the freshly-built row instead of force-carrying the old value: the sheet pre-fills the field from the edited row, so an untouched edit round-trips the stored distance, a changed value overrides, and a cleared field clears. The captured route polyline is still preserved.
  • iOS ManualWorkoutSheet — a Distance field beside Duration; entered in the user's unit (km/mi), stored as metres. New strings localized in all 8 catalog locales.
  • Android ManualWorkoutDialog — the same field, matching the dialog's existing plain-field style.
  • Unit tests both platforms — distance bounds + the preservingCaptured override/clear behavior.

No migration (the distanceM column already exists). The Kotlin distanceM param is trailing so existing positional callers are untouched; the one caller that sets it passes it by name.

Verification

  • Android: compileFullDebugKotlin clean; WorkoutEditingTest (new distance cases) + UnitFormatterTest green.
  • i18n: Tools/i18n_audit.py --ci clean (new iOS strings added to the catalog; the Android dialog matches its siblings' baselined plain-field pattern).
  • iOS app-target (WorkoutSource, ManualWorkoutSheet, Units) compiled via app-build.yml. StrandTests has no CI, so the Swift test mirrors the passing Kotlin one verbatim.

Scope vs #1195

Live distance/pace shipped in #1202; HC distance import shipped in #215. Remaining after this: route import (HC ExerciseRoute / Apple Health), and splits (needs per-point timestamps, which the stored track lacks) — both better as their own issues.

Manual workouts (and detected/imported ones opened for edit) could set sport,
start, duration, avg HR and calories — but not distance, even though the
workout row already stores distanceM and shows it in the detail view. This adds
a unit-aware Distance field to the sheet on both platforms, so a session tracked
elsewhere (or one where GPS was off/denied) can carry a real distance.

- WorkoutSource.buildManualRow / WorkoutEditing.buildManualRow: accept an
  optional distanceM (default nil), validated 0–1,000 km. preservingCaptured now
  takes distanceM from the freshly built row instead of force-carrying the old
  one — the sheet pre-fills the field from the edited row, so an untouched edit
  round-trips the stored distance, a changed value overrides, and a cleared field
  clears. The captured route polyline is still preserved.
- iOS ManualWorkoutSheet: a Distance field beside Duration; enter in the user's
  unit (km/mi), stored as metres. New strings localized in all 8 catalog locales.
- Android ManualWorkoutDialog: the same field, matching the dialog's existing
  plain-field style.
- Unit tests both platforms: distance bounds + the preservingCaptured override.

The Kotlin distanceM param is trailing so the existing positional callers are
unaffected. No migration (the column already exists). App-target Swift compiled
via app-build; StrandTests has no CI so the Swift test mirrors the Kotlin one
verbatim.
@ryanbr
ryanbr merged commit 9cf1956 into main Aug 10, 2026
5 checks passed
@ryanbr
ryanbr deleted the manual-workout-distance-1195 branch August 10, 2026 03:40
ryanbr pushed a commit that referenced this pull request Aug 15, 2026
…fting it

Rebased onto current main: applied the ScrollView refactor to the current
formContent (which now carries the #1203 distance row) and kept the
NoopChromeSurface() background (main changed it from surfaceOverlay since
this branch was opened). Logic/structure otherwise unchanged from #521.

#450 raised the sheet to .large but left a bare fixed-height VStack, so iOS
keyboard-avoidance rigidly shifts the whole block (clipping the header/Sport
field + its suggestion overlay off-screen, and colliding the footer with the
system Done accessory). Wrapping the iOS body in a ScrollView gives avoidance
somewhere to scroll instead. macOS's fixed 420pt panel is untouched.
ryanbr added a commit that referenced this pull request Aug 15, 2026
…fting it (#1336)

Rebased onto current main: applied the ScrollView refactor to the current
formContent (which now carries the #1203 distance row) and kept the
NoopChromeSurface() background (main changed it from surfaceOverlay since
this branch was opened). Logic/structure otherwise unchanged from #521.

#450 raised the sheet to .large but left a bare fixed-height VStack, so iOS
keyboard-avoidance rigidly shifts the whole block (clipping the header/Sport
field + its suggestion overlay off-screen, and colliding the footer with the
system Done accessory). Wrapping the iOS body in a ScrollView gives avoidance
somewhere to scroll instead. macOS's fixed 420pt panel is untouched.

Co-authored-by: Max Schädlich <schaedlich.max@gmail.com>
simoncad7 pushed a commit to simoncad7/noop that referenced this pull request Aug 17, 2026
… (ryanbr#1203)

Manual workouts (and detected/imported ones opened for edit) could set sport,
start, duration, avg HR and calories — but not distance, even though the
workout row already stores distanceM and shows it in the detail view. This adds
a unit-aware Distance field to the sheet on both platforms, so a session tracked
elsewhere (or one where GPS was off/denied) can carry a real distance.

- WorkoutSource.buildManualRow / WorkoutEditing.buildManualRow: accept an
  optional distanceM (default nil), validated 0–1,000 km. preservingCaptured now
  takes distanceM from the freshly built row instead of force-carrying the old
  one — the sheet pre-fills the field from the edited row, so an untouched edit
  round-trips the stored distance, a changed value overrides, and a cleared field
  clears. The captured route polyline is still preserved.
- iOS ManualWorkoutSheet: a Distance field beside Duration; enter in the user's
  unit (km/mi), stored as metres. New strings localized in all 8 catalog locales.
- Android ManualWorkoutDialog: the same field, matching the dialog's existing
  plain-field style.
- Unit tests both platforms: distance bounds + the preservingCaptured override.

The Kotlin distanceM param is trailing so the existing positional callers are
unaffected. No migration (the column already exists). App-target Swift compiled
via app-build; StrandTests has no CI so the Swift test mirrors the Kotlin one
verbatim.
simoncad7 pushed a commit to simoncad7/noop that referenced this pull request Aug 17, 2026
…fting it (ryanbr#1336)

Rebased onto current main: applied the ScrollView refactor to the current
formContent (which now carries the ryanbr#1203 distance row) and kept the
NoopChromeSurface() background (main changed it from surfaceOverlay since
this branch was opened). Logic/structure otherwise unchanged from ryanbr#521.

ryanbr#450 raised the sheet to .large but left a bare fixed-height VStack, so iOS
keyboard-avoidance rigidly shifts the whole block (clipping the header/Sport
field + its suggestion overlay off-screen, and colliding the footer with the
system Done accessory). Wrapping the iOS body in a ScrollView gives avoidance
somewhere to scroll instead. macOS's fixed 420pt panel is untouched.

Co-authored-by: Max Schädlich <schaedlich.max@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant