Add the Rippr Flutter port: source, history bundle, and installable APK
The port runs on Android and iOS and is feature-complete; the native Android app is superseded but kept, since it is still the only version that has recorded real rides. rippr-flutter-1.0-debug.apk is package com.rippr.port, deliberately different from the native com.rippr so both install side by side. Recording the same ride on both at once is the strongest available check that the port is faithful. Added INSTALL.md covering both platforms. Android is a one-line adb install; iOS has no APK equivalent and must be built and signed through Xcode with a free Apple ID, which gives a 7-day profile. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
102
rippr-flutter-src/README.md
Normal file
102
rippr-flutter-src/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Rippr
|
||||
|
||||
A GPS ride recorder for motorcycles, on **Android and iOS**. Records telemetry into a
|
||||
local SQLite database, renders the traversed path on a map afterwards, and exports to
|
||||
GPX/GeoJSON.
|
||||
|
||||
Built for one specific use: **hit start, put the phone in a pocket, ride, hit stop.**
|
||||
Most of the design follows from that.
|
||||
|
||||
This is a Flutter port of the native Android app in `~/dojo/rippr` (v1 → v2.0.1). The port
|
||||
is feature-complete; see [docs/port/PARITY-AUDIT.md](docs/port/PARITY-AUDIT.md) for
|
||||
exactly what is verified and what is not.
|
||||
|
||||
```
|
||||
Flutter 3.47 · Dart 3.13 Android minSdk 26 · iOS 12+
|
||||
~4,600 lines Dart 175 tests (171 unit/widget, 4 integration)
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
| Feature | Status |
|
||||
|---|---|
|
||||
| GPS recording, foreground on Android / background mode on iOS | Implemented; **not yet ridden** |
|
||||
| Trips with pause / resume / stop / discard | Working, 50 tests |
|
||||
| Live speed + elapsed clock | Working |
|
||||
| Path on OpenStreetMap, per-segment, speed-coloured | Working; colouring unverifiable without a real ride |
|
||||
| Ride statistics + charts | Working; bit-identical to the Kotlin original |
|
||||
| Rename / delete / merge rides | Working |
|
||||
| GPX + GeoJSON export | Working; byte-identical to the Kotlin original |
|
||||
| Upload to a REST endpoint | Implemented, **no UI** (as in the native app) |
|
||||
| Notification actions (Pause/Resume in the shade) | **Absent** — the one capability lost |
|
||||
| Live map while recording · group ride | Deferred to v3 |
|
||||
|
||||
> **The port has never recorded a real ride.** No simulator produces velocity, so max
|
||||
> speed, moving time, speed colouring, elevation against real GPS error, battery, and iOS
|
||||
> stationary suspension are all unverified. That is
|
||||
> [docs/port/REAL-RIDE-CHECKLIST.md](docs/port/REAL-RIDE-CHECKLIST.md), and it is the next
|
||||
> thing that should happen.
|
||||
|
||||
## Quick start
|
||||
|
||||
Requires **JDK 17–21** for Android (AGP rejects 25) and Xcode for iOS.
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
dart run build_runner build # Drift codegen
|
||||
flutter analyze && flutter test
|
||||
flutter test integration_test -d <device-id>
|
||||
flutter run
|
||||
```
|
||||
|
||||
**Watch the disk.** A full dual-platform build cycle costs roughly 10 GB, and the Android
|
||||
emulator needs 7.4 GB free just to boot. Run `flutter clean` before booting it.
|
||||
|
||||
## Cross-language parity
|
||||
|
||||
The strongest guarantee in this repo. It compiles the **real Kotlin sources** from the
|
||||
native app and diffs them against the Dart port across twenty fixtures:
|
||||
|
||||
```bash
|
||||
brew install kotlin
|
||||
JAVA_HOME=<jdk-21> ./tool/parity/run.sh
|
||||
```
|
||||
|
||||
Everything matches to the last digit — including the elevation accumulator at
|
||||
`38.959594555022136` and byte-identical GPX/GeoJSON. The single expected difference is
|
||||
speed-derived values, where Kotlin's 32-bit `Float` widens with artefacts Dart's uniform
|
||||
`double` does not reproduce.
|
||||
|
||||
## Documentation
|
||||
|
||||
| Document | Contents |
|
||||
|---|---|
|
||||
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Why it is built this way, and what changed from the native app |
|
||||
| [docs/port/PLAN.md](docs/port/PLAN.md) | The 28-task migration plan |
|
||||
| [docs/port/PROGRESS.md](docs/port/PROGRESS.md) | What actually happened, including every bug found |
|
||||
| [docs/port/PARITY-AUDIT.md](docs/port/PARITY-AUDIT.md) | Feature-by-feature, with the evidence behind each claim |
|
||||
| [docs/port/REAL-RIDE-CHECKLIST.md](docs/port/REAL-RIDE-CHECKLIST.md) | **The outstanding work** |
|
||||
| [docs/port/RELEASE-IOS.md](docs/port/RELEASE-IOS.md) | App Review readiness |
|
||||
| [docs/PORT_RESEARCH.md](docs/PORT_RESEARCH.md) | The original research this plan was built on |
|
||||
|
||||
The native repo's `docs/v1/`, `docs/v2/` and `docs/v3/BACKLOG.md` remain the record of how
|
||||
the app got here and where it is going.
|
||||
|
||||
## Two bugs this port found in the native app
|
||||
|
||||
**Crash recovery measured the dead time as distance.** `restoreAfterProcessDeath` says it
|
||||
resumes into a new segment; it actually adopts the segment a crash left open, so the
|
||||
authoritative recomputation measures straight through the gap. Reproduced at **111 km** of
|
||||
phantom distance. Fixed here.
|
||||
|
||||
**The elevation regression guard passes on seed luck.** On a shared fixture the algorithm
|
||||
yields ~39 m, which would fail the native test's own 35 m bound. It passes only because
|
||||
`kotlin.random.Random(42)` happens to draw a benign sequence.
|
||||
|
||||
## Before shipping
|
||||
|
||||
- Switch the application id from `com.rippr.port` back to `com.rippr`. The suffix exists
|
||||
so the native app can be installed alongside during the port — **keep it until the real
|
||||
ride comparison is done**.
|
||||
- Replace the default Flutter app icon; the native artwork is in `~/dojo/rippr/design/`.
|
||||
- Build and test a release build. Everything so far has been debug.
|
||||
Reference in New Issue
Block a user