Scaffold Flutter port: toolchain, project, and Geo
T00 — toolchain green on both platforms. flutter doctor reports no issues. Pinned Flutter to Temurin 21 (AGP rejects the default JDK 25, same constraint as the native build) and installed Android cmdline-tools with an explicit --sdk_root, the trap already documented in the native DEVELOPMENT.md. No caches were deleted: the 16 GiB disk reading that drove the cleanup plan re-measured at 36 GiB before anything was removed. T01 — flutter create for android+ios. applicationId is com.rippr.port, not com.rippr, so the native app stays installable alongside it during the port; T27 switches it at cutover. T02 — geo/geo.dart ported from com.rippr.geo.Geo with all 23 tests, tolerances and comments carried over unchanged. Kotlin's object namespace became top-level functions; LatLon stays our own type so the pure layer never depends on flutter_map. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
107
docs/port/PROGRESS.md
Normal file
107
docs/port/PROGRESS.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Port progress log
|
||||
|
||||
Running record of what actually happened, task by task — including what went wrong.
|
||||
The v2 equivalent of this file caught real bugs by making risks explicit before they
|
||||
were walked into, so the practice carries over.
|
||||
|
||||
Plan: [PLAN.md](PLAN.md) · Source of truth for *why*: the native repo's
|
||||
`docs/ARCHITECTURE.md`, `docs/TESTING.md`, `docs/v2/PROGRESS.md`.
|
||||
|
||||
---
|
||||
|
||||
## T00 — Disk space + toolchain · **complete**
|
||||
|
||||
**Outcome:** `flutter doctor` reports no issues in any category. Flutter 3.47.0 (Dart
|
||||
3.13.0), Xcode 26.0.1, CocoaPods 1.17.0, Android SDK 36.0.0, iOS 26.0.1 simulator runtime.
|
||||
|
||||
### The disk panic was largely a false alarm — but measure twice
|
||||
|
||||
Planning measured **16 GiB free at 92%**, which drove a whole cleanup strategy. A second
|
||||
measurement minutes later, before deleting anything, showed **36 GiB free at 81%**. Most
|
||||
likely APFS local snapshots aging out.
|
||||
|
||||
**Nothing was deleted.** Gradle caches, AVDs, and `~/.cargo` were all left intact.
|
||||
Post-install the machine sits at ~22 GiB free.
|
||||
|
||||
**Lesson:** re-measure immediately before acting on a disk-space number. Had the plan been
|
||||
followed literally, ~9 GB of still-useful caches would have been destroyed for no reason.
|
||||
|
||||
### Things that actually needed fixing
|
||||
|
||||
| Problem | Fix |
|
||||
|---|---|
|
||||
| `cmdline-tools component is missing` | `sdkmanager --sdk_root=$ANDROID_HOME "cmdline-tools;latest"` — the exact trap already documented in the native repo's `DEVELOPMENT.md`: brew's `sdkmanager` resolves its own SDK root and does not see `~/Library/Android/sdk` unless `--sdk_root` is passed explicitly |
|
||||
| Android licenses unaccepted | `yes \| sdkmanager --sdk_root=$ANDROID_HOME --licenses` |
|
||||
| Default JDK is 25, which AGP rejects | `flutter config --jdk-dir=<temurin-21>` — same constraint as the native build, now pinned in Flutter's config rather than relying on an exported `JAVA_HOME` |
|
||||
| No iOS simulator runtime installed | `xcodebuild -downloadPlatform iOS` (8.05 GB). Note simulator *devices* already existed for a runtime that did not — `simctl list devices` looked populated while `list runtimes` was empty |
|
||||
| CocoaPods absent, system Ruby 2.6.10 | `brew install cocoapods`, deliberately not `gem install` |
|
||||
|
||||
---
|
||||
|
||||
## T01 — Repo scaffold · **complete**
|
||||
|
||||
`~/dojo/rippr-flutter`, `flutter create --org com.rippr --project-name rippr`.
|
||||
|
||||
### Two deliberate deviations from the generated defaults
|
||||
|
||||
**Bundle id is `com.rippr.port`, not `com.rippr`.** `--org com.rippr` + name `rippr`
|
||||
produces `com.rippr.rippr`, which is wrong either way. The choice of `com.rippr.port` is
|
||||
deliberate and temporary: the plan requires the native app to stay installable as a
|
||||
reference and fallback, and **two apps cannot share an applicationId**. Keeping them
|
||||
distinct means both can sit on the same phone — which also enables the strongest possible
|
||||
validation in T25: record the same ride on both simultaneously and compare the numbers.
|
||||
|
||||
> **T27 must switch this to `com.rippr`** at cutover. Recorded here because it is exactly
|
||||
> the kind of temporary decision that silently becomes permanent.
|
||||
|
||||
The Android `namespace` stays `com.rippr` and the Kotlin source was moved from
|
||||
`kotlin/com/rippr/rippr/` to `kotlin/com/rippr/` to match.
|
||||
|
||||
### Dependencies
|
||||
|
||||
`flutter_riverpod` · `go_router` · `drift` + `drift_flutter` · `path_provider` ·
|
||||
`geolocator` · `flutter_foreground_task` · `permission_handler` · `flutter_map` +
|
||||
`latlong2` · `share_plus` · `shared_preferences` · `http` · `synchronized`.
|
||||
Dev: `drift_dev`, `build_runner`, `mocktail`, `integration_test`.
|
||||
|
||||
**`sqlite3_flutter_libs` resolves to an `+eol`-tagged release (0.6.0+eol).** It was added
|
||||
explicitly at first, then removed — `drift_flutter` depends on it transitively regardless,
|
||||
so the pin belongs to drift, not to us. Worth watching when drift next majors, but not
|
||||
actionable now.
|
||||
|
||||
---
|
||||
|
||||
## T02 — Geo utilities · **complete**
|
||||
|
||||
`lib/src/geo/geo.dart` + `test/geo_test.dart`. **23/23 passing.**
|
||||
|
||||
Ported structurally faithfully from `com.rippr.geo.Geo`: haversine (with the
|
||||
`asin(sqrt(a))` conditioning note), iterative Douglas–Peucker with an explicit stack,
|
||||
equirectangular perpendicular distance with clamped projection, null-on-empty bounds,
|
||||
path length. Every test case and tolerance carried over unchanged, including the
|
||||
Calgary–Edmonton 280.9 km figure that was corrected during v2 after the *test* proved
|
||||
wrong rather than the code.
|
||||
|
||||
**Deliberate API divergence:** Kotlin's `object Geo` namespace became top-level functions,
|
||||
which is idiomatic Dart. `LatLon` is our own type rather than `latlong2`'s `LatLng` — the
|
||||
pure layer must not depend on the map package; conversion happens at the render boundary.
|
||||
|
||||
### Two things went wrong
|
||||
|
||||
**`library;` after the import.** Dart requires the library directive before all other
|
||||
directives. Caught immediately by the compiler — noted only because a file-level doc
|
||||
comment is otherwise easy to attach wrongly.
|
||||
|
||||
**A hang that was not a hang.** `flutter test` and `flutter build ios` were run
|
||||
concurrently and both sat at 0% CPU for minutes. The suspicion was Rosetta, because
|
||||
`flutter_tester` lives under `artifacts/engine/darwin-x64/` — **that was wrong**: the
|
||||
binary there is arm64 and the directory name is legacy. The real cause was
|
||||
`ibtool`/`actool` spawning `IBAgent-iOS` and `AssetCatalogSimulatorAgent`, which deadlock
|
||||
against a booted simulator. Run alone with simulators shut down, the same suite finishes
|
||||
in under a second.
|
||||
|
||||
Two lessons, both echoing v2's harness troubles:
|
||||
- **Do not run an iOS build against a booted simulator** if anything else needs it.
|
||||
- **A killed background job still reports exit code 0.** Both jobs "completed
|
||||
successfully" *because they were killed*. Never read a success code from a process you
|
||||
terminated — re-run it cleanly.
|
||||
Reference in New Issue
Block a user