Files
rippr/docs/v3/V3-05-mounted-mode.md
Dylan 342a8f8382 Break v3 into 16 tickets
One file per feature, in the v2 shape that worked: goal, context, design,
implementation, acceptance criteria, tests, risks, out of scope -- written before
implementing so the risks are on paper rather than walked into.

Three carry more weight than their size suggests. V3-01 ships the port's first
real migration, and since the destructive fallback is gone, getting addColumn and
a v1-database test right matters more than the feature. V3-08 forces a
routing-engine decision with ongoing cost, so it sits behind a RoutingService
interface mirroring what LocationSource did for GPS. V3-13 is not code at all --
it answers the three questions open since v2, and V3-15 may close unbuilt as a
result, which is a legitimate outcome.

Several tickets record constraints that are easy to lose: no activity picker in
front of Start, because the founding premise is press-and-go with gloves; the
Route-to-Trip foreign key must not cascade, or deleting an old plan deletes the
ride; V3-14 will deliberately break the parity harness by adding GPX <type>, and
that expectation should be updated rather than the check dropped; and V3-16 must
not regress the explicit text colours that exist because of the black-on-black bug.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 10:41:35 -05:00

2.4 KiB

V3-05 — Mounted (handlebar) mode

Phase Live map · Depends on V3-04 · Size M · Status Not started

Goal

Make the app usable on handlebars in daylight, at speed, with gloves — as an explicit mode rather than an accident.

Context

v1 and v2 were built entirely around "start it, pocket it, stop it". A mounted phone is a different product. Treating it as a mode makes the differences deliberate instead of half-met.

Design

A toggle that changes several things at once:

  • Keep the screen awake for the whole ride (wakelock_plus). Currently the screen sleeps and recording continues; mounted, that is wrong.
  • Sunlight legibility. The dark theme was chosen for glanceability at night and in a pocket-glance. Behind a visor in daylight it is the wrong choice — a high-contrast variant with larger figures is needed. This is not the same as V3-16's visual identity.
  • Larger touch targets still. 72 dp works stopped; at speed with gloves it does not.
  • Interruptions. What happens on an incoming call or a notification — the recording must survive and the screen must come back.

Implementation

  1. mountedMode in Config, surfaced in settings and as a quick toggle on the record screen
  2. wakelock_plus, acquired on start when mounted, released on stop/pause — and released on dispose, or the screen stays lit after the app closes
  3. A high-contrast text scale applied when mounted
  4. Handle AppLifecycleState.inactive (a call arriving) distinctly from paused

Acceptance criteria

  • Mounted: the screen never sleeps during a ride
  • Un-mounted: behaviour is exactly as today
  • The wake lock is released on stop, on discard, and on app exit
  • An incoming call does not stop recording
  • Battery cost of mounted mode is measured and written down (V3-13)

Tests

  • Widget: mounted toggle changes text scale and requests the wake lock (fake the plugin)
  • Widget: the lock is released on stop
  • Manual, on a real bike — legibility in daylight cannot be tested any other way

Risks

  • A leaked wake lock flattens the battery, silently and after the app is closed. Test the release path harder than the acquire path.
  • Legibility is a judgement call that needs a real ride in real sun.

Out of scope

A dedicated mounted layout with different information architecture — start by scaling what exists and see what the ride teaches.