From 64d210af5c3d7808512a709531ee052a0b1522c3 Mon Sep 17 00:00:00 2001 From: Mikkeli Matlock Date: Mon, 9 Feb 2026 19:14:32 +0900 Subject: [PATCH] docs: initialize project Restructure GPS speedometer: modular architecture, Provider state management, overlay reliability fixes, speed-adaptive GPS precision, cooperative Android GPS access. --- .planning/PROJECT.md | 102 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 .planning/PROJECT.md diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md new file mode 100644 index 0000000..f85d6c1 --- /dev/null +++ b/.planning/PROJECT.md @@ -0,0 +1,102 @@ +# GPS Speedometer — Restructure & Android QoL + +## What this is + +A restructure of the existing Flutter GPS speedometer app, splitting a 1,075-line monolithic `main.dart` into a modular architecture with proper state management, and improving Android quality of life — particularly the floating window overlay reliability, GPS response latency, and power behavior. This is not a feature expansion. It is a foundation rebuild for the same app. + +## Core value + +Reliable, lag-free GPS speed display that coexists politely with other Android apps. + +## Requirements + +### Validated + +These exist and work in the current codebase. + +- ✓ Real-time GPS speed tracking with accuracy monitoring — existing +- ✓ Speed units (km/h, mph, knots) with quick selector — existing +- ✓ Dual display styles: digital speedometer + analog gauge — existing +- ✓ Dark/light theme support with cycling — existing +- ✓ Optional metrics panel: coordinates, distance, trip time, accuracy — existing +- ✓ Trip reset functionality — existing +- ✓ Portrait/landscape orientation support — existing +- ✓ Android permissions handling (FINE_LOCATION, COARSE_LOCATION, SYSTEM_ALERT_WINDOW) — existing +- ✓ Floating window overlay showing speed + heading — existing (buggy) +- ✓ GpsDataManager singleton for centralized GPS processing — existing +- ✓ Haptic feedback on main UI interactions — existing +- ✓ Heading display with compass bearing — existing + +### Active + +Architecture: + +- [ ] Modularize code into `screens/`, `widgets/`, `services/`, `providers/`, `models/` directories +- [ ] Replace raw `setState()` with proper Provider pattern (ChangeNotifier/Consumer) +- [ ] Extract overlay management from SpeedometerScreen into dedicated controller/service +- [ ] Define typed message schema for main↔overlay communication (replace unvalidated Maps) +- [ ] Replace unconditional `print()` calls with conditional debug logging (`customDebugPrint`) + +Overlay reliability: + +- [ ] Fix overlay data pipeline — data stops updating after running for a while +- [ ] Surface overlay errors to user (snackbar/toast instead of silent catch) +- [ ] Verify overlay creation succeeded before setting `_isOverlayActive = true` +- [ ] Remove or fix unreliable overlay status polling (1-second timer workaround) + +GPS performance: + +- [ ] Eliminate lag between GPS hardware fix and display update +- [ ] Speed-adaptive GPS precision: HIGH_ACCURACY above ~10 km/h, BALANCED_POWER below, with hysteresis (~8/12 km/h thresholds) +- [ ] Non-exclusive, non-locking GPS access — other apps use location normally + +Power & background: + +- [ ] Smart background GPS: active when overlay is visible, stopped when not +- [ ] Stop heartbeat timer when not needed (foreground + no overlay) +- [ ] Remove unnecessary wake locks — only hold when actively tracking with overlay +- [ ] Cache overlay size calculation instead of recalculating on every build + +### Out of scope + +- New features or UI additions — this is a restructure, not a feature release +- Dedicated settings screen — inline toggles stay as-is +- GPS interpolation or prediction between hardware fixes — display what hardware gives, instantly +- iOS testing or optimization — Android primary +- New overlay content — speed + unit + heading stays +- Comprehensive unit/integration test suite — important but separate milestone +- Dependency version upgrades — keep current versions stable + +## Context + +The app is a working GPS speedometer at v2.3.0-dev on the `feature/gps-manager-architecture` branch. The core problem is architectural: `main.dart` is a monolith where `SpeedometerScreen` alone is ~780 lines managing GPS subscriptions, overlay lifecycle, theme cycling, unit cycling, haptic feedback, background heartbeat, overlay status polling, and gesture handling. This makes every fix a surgical operation in a crowded file. + +The `flutter_overlay_window` package has known limitations — bidirectional communication is unreliable, and the current heartbeat/polling approach is a workaround for message-based detection failures. The data pipeline going stale is likely related to timer lifecycle and stream subscription management. + +Provider is already a dependency but unused — the app relies on `setState()` throughout. The restructure should wire Provider properly so state flows reactively across extracted widgets. + +The GPS cooperative access constraint is important: the app uses Android's Fused Location Provider (via geolocator), which is inherently shared. But holding continuous HIGH_ACCURACY streams with wake locks is aggressive. Speed-adaptive precision reduces this to "high when actually moving, balanced when not." + +SharedPreferences is mentioned in CLAUDE.md as implemented but is not actually integrated — settings reset on app restart. This is a known gap but out of scope for this restructure. + +## Constraints + +- **Platform**: Android primary — iOS exists but is untested and not a target +- **GPS bus**: Must be non-exclusive, non-locking — other apps access location normally +- **Power**: Mixed use — sometimes charging (car), sometimes battery (cycling, walking) +- **Overlay library**: `flutter_overlay_window 0.5.0` has known bidirectional communication issues — design around them +- **Tech stack**: Flutter/Dart, keep existing dependency set — no new major dependencies +- **Backward compatibility**: All current features must continue to work after restructure + +## Key decisions + +| Decision | Rationale | Outcome | +|----------|-----------|---------| +| Speed-adaptive GPS precision (~10 km/h threshold with hysteresis) | Balances responsiveness when moving with cooperative behavior when stationary | — Pending | +| Provider pattern for state management | Already a dependency, fits Flutter idiom, enables reactive updates across extracted widgets | — Pending | +| Background GPS only when overlay visible | No reason to track location if user can't see the data | — Pending | +| Directory structure: screens/, widgets/, services/, providers/, models/ | Standard Flutter convention, separates concerns cleanly | — Pending | +| No new dependencies | Stability — restructure existing code, don't introduce new moving parts | — Pending | + +--- +*Last updated: 2026-02-09 after initialization*