Commit Graph

597 Commits

Author SHA1 Message Date
Doug Borg
e72d557d2a chore(android): bump AGP to 8.9.1 and Java compatibility to 17
Transitive AndroidX dependencies (browser:1.9.0, core-ktx:1.17.0,
core:1.17.0) pulled in by the pub upgrade now require AGP 8.9.1+.

- AGP: 8.7.3 → 8.9.1
- Java source/target compatibility: 11 → 17
- Gradle 8.12 already satisfies AGP 8.9.1's minimum of 8.11.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:45:38 -07:00
Doug Borg
25a34aab0b chore(deps): upgrade minor/patch dependencies within existing constraints
Run `flutter pub upgrade` to pull in 42 dependency updates within
existing ^constraints. No pubspec.yaml changes needed.

Notable updates: flutter_map 8.2.1→8.2.2, flutter_svg 2.2.0→2.2.3,
http 1.5.0-beta.2→1.6.0, provider 6.1.5→6.1.5+1,
shared_preferences 2.5.3→2.5.4, uuid 4.5.1→4.5.2, xml 6.5.0→6.6.1,
flutter_native_splash 2.4.6→2.4.7, plus many transitive deps.

Closes #78

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:45:38 -07:00
stopflock
610c5c71b1 Merge pull request #127 from dougborg/hybrid-tile-provider
Delegate network tile fetching to NetworkTileProvider
v2.7.2-rc v2.7.2-release
2026-02-24 21:31:11 -06:00
Doug Borg
8983939b05 Delegate network tile fetching to NetworkTileProvider
Replace our custom tile pipeline (fetchRemoteTile / _SimpleSemaphore /
exponential backoff) with flutter_map's built-in NetworkTileProvider,
gaining persistent disk cache, ETag revalidation, RetryClient, and
obsolete request aborting for free.

DeflockTileProvider now extends NetworkTileProvider and overrides
getTileUrl() to route through TileType.getTileUrl() (quadkey,
subdomains, API keys). getImageWithCancelLoadingSupport() routes
between two paths at runtime: the common network path (super) when
no offline areas exist, and a DeflockOfflineTileImageProvider for
offline-first when they do.

- Delete tiles_from_remote.dart (semaphore, retry loop, spatial helpers)
- Simplify MapDataProvider._fetchRemoteTileFromCurrentProvider to plain
  http.get (only used by offline area downloader now)
- Remove dead clearTileQueue/clearTileQueueSelective from MapDataProvider
- Remove 7 tile fetch constants from dev_config.dart
- TileLayerManager now disposes provider on cache clear and uses actual
  urlTemplate for cache key generation
- 9 new tests covering URL delegation, routing, and equality

Closes #87 Phase 2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 20:07:56 -07:00
stopflock
9448305738 Merge pull request #123 from dougborg/feat/consistent-user-agent
Add consistent User-Agent header to all HTTP clients
2026-02-24 20:37:49 -06:00
Doug Borg
775148cfb7 Bump version to 2.7.2+48
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:31:31 -07:00
Doug Borg
0137fd66aa Add consistent User-Agent header to all HTTP clients
Create UserAgentClient (http.BaseClient wrapper) that injects a
User-Agent header into every request, reading app name and version
from VersionService and contact/homepage from dev_config.dart.

Format follows OSM tile usage policy:
  DeFlock/<version> (+https://deflock.org; contact: admin@stopflock.com)

Replaces 4 inconsistent hardcoded UA strings and adds UA to the 9
call sites that previously sent none.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:31:27 -07:00
Doug Borg
fe20356734 Merge branch 'main' of github.com:dougborg/deflock-app
* 'main' of github.com:dougborg/deflock-app:
  Comment on commit c7cfdc471c by dougborg on 2026-02-11 02:14:40 UTC
2026-02-24 18:59:03 -07:00
stopflock
14d7c10ca6 Merge pull request #116 from dougborg/ci/pr-build-artifacts
Add debug build artifacts to PR workflow
2026-02-24 19:44:15 -06:00
Doug Borg
348256270d Cache Flutter SDK, Gradle, and CocoaPods in CI
Cold Gradle builds were taking ~8.5 min for the APK job. Add
caching for Flutter/pub (via flutter-action), Gradle deps, and
CocoaPods to speed up subsequent runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 18:29:02 -07:00
Doug Borg
8a759e88e9 Add debug build artifacts and download links to PR workflow
Let reviewers download and test PR changes on a device without building
locally. A sticky PR comment links directly to the artifacts page.

Closes #52

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 18:29:02 -07:00
stopflock
e168b6e19c Dutch, Polish, Turkish, Ukrainian 2026-02-15 13:20:15 -06:00
stopflock
f78ea1a300 no dev mode - publishing v2.7.1-release 2026-02-14 14:50:38 -06:00
stopflock
2dca311d2a changelog, version 2026-02-14 14:42:39 -06:00
stopflock
7470b14e38 Merge pull request #113 from dougborg/fix/overpass-out-skel
Use out skel for Overpass way/relation pass
2026-02-14 14:30:08 -06:00
Doug Borg
5df0170344 Use out skel for Overpass way/relation pass and add service tests
Switch the second Overpass pass (ways/relations) from out meta to out skel,
dropping unused tags/version/changeset fields from the response. The app only
reads structural references (node lists, relation members) from these elements.

Also inject http.Client into OverpassService for testability (matching
RoutingService pattern) and add close() for client lifecycle management.

14 tests covering query building, constraint detection, and error handling.

Fixes #108

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 13:26:22 -07:00
stopflock
1429f1d02b Merge pull request #41 from dougborg/fix/map-jitter-on-touch
Fix map jitter/wiggle when touching at low zoom
2026-02-14 13:17:43 -06:00
Doug Borg
f0f23489b5 Fix map jitter when touching map during follow-me animations
Cancel in-progress follow-me animations on pointer-down and suppress
new ones while any pointer is on the map. Without this, GPS position
updates trigger 600ms animateTo() calls that fight with the user's
stationary finger, causing visible wiggle — especially at low zoom
where small geographic shifts cover more pixels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 02:02:51 -07:00
Doug Borg
9ae7d9c894 Merge branch 'main' of github.com:FoggedLens/deflock-app
* 'main' of github.com:FoggedLens/deflock-app:
  Remove simulation tests that don't exercise production code
  Guard onFieldSubmitted on non-empty text to prevent cleared values reappearing
  Add tests demonstrating RawAutocomplete onSubmitted bug
  no longer lose operator profile selection when making other changes to a node
  bump version
  Move README roadmap items to GitHub Issues
  Address PR review: truncate error response logs and close http client
  Fix route calculation HTTP 400 by filtering empty profile tags
  Add tests for routing service and node profile serialization
  Make suggestion limit configurable and remove redundant .take(10) from widget
  Materialize options iterable to list in optionsViewBuilder
  Fix dropdown dismiss by replacing manual overlay with RawAutocomplete
  Address Copilot review feedback on PR #46
  Bump Dart SDK constraint to >=3.8.0 and document Flutter 3.35+ requirement
  Rewrite dev setup docs with tested, copy-pasteable instructions
2026-02-11 11:13:53 -07:00
stopflock
c8e396a6eb Merge pull request #104 from dougborg/fix/tag-value-clear-on-done
Fix tag value reappearing after clearing and pressing Done
v2.7.0-rc
2026-02-10 20:31:25 -06:00
Doug Borg
97675f9f48 Comment on commit c7cfdc471c by dougborg on 2026-02-11 02:14:40 UTC 2026-02-10 19:14:52 -07:00
Doug Borg
75014be485 Remove simulation tests that don't exercise production code
The RawAutocomplete tests proved the pattern and fix but never
instantiated NSITagValueField itself — no actual coverage gained.
PR #36 replaces the widget entirely, so investing in testability
here isn't worthwhile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 19:01:09 -07:00
Doug Borg
af42e18f6e Guard onFieldSubmitted on non-empty text to prevent cleared values reappearing
When a user clears a tag value and presses Done, RawAutocomplete's
onFieldSubmitted auto-selects the first option from the suggestions
list. Since optionsBuilder returns all suggestions for empty text,
this causes the cleared value to reappear. Guarding the call on
non-empty text prevents the auto-selection while preserving
autocomplete behavior when the user has typed a partial match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 18:56:28 -07:00
Doug Borg
c7cfdc471c Add tests demonstrating RawAutocomplete onSubmitted bug
RawAutocomplete.onFieldSubmitted auto-selects the first option when
called, which means pressing "Done" on an empty tag value field
re-populates it with the first NSI suggestion. These tests prove the
bug exists (unguarded path) and verify the fix (guarded path).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 18:56:18 -07:00
stopflock
19b3ca236e no longer lose operator profile selection when making other changes to a node 2026-02-10 18:28:07 -06:00
stopflock
2e0dcb1b2b bump version 2026-02-09 23:59:08 -06:00
stopflock
59afd75887 Merge pull request #42 from dougborg/fix/routing-empty-tags
Fix route calculation HTTP 400 caused by empty profile tag values
2026-02-09 18:26:12 -06:00
stopflock
83370fba7e Merge pull request #77 from dougborg/chore/roadmap-to-issues
Move README roadmap to GitHub Issues
2026-02-09 18:23:52 -06:00
stopflock
ba6c7cdbda Merge pull request #40 from dougborg/investigate/dropdown-dismiss
Fix suggestion dropdown dismiss on tap outside
2026-02-09 18:17:53 -06:00
Doug Borg
311125e1f5 Move README roadmap items to GitHub Issues
Replace the inline roadmap section with a link to GitHub Issues.
Each roadmap item has been created as a proper issue (#55-#76) for
better tracking, discussion, and prioritization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:53:45 -07:00
Doug Borg
5abcc58a78 Address PR review: truncate error response logs and close http client
- Gate full error response body logging behind kDebugMode; truncate to
  500 chars in release builds to avoid log noise and data exposure
- Add RoutingService.close() and call from NavigationState.dispose()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:32:34 -07:00
Doug Borg
71776ee8f0 Fix route calculation HTTP 400 by filtering empty profile tags
Built-in profiles (Flock, Motorola, etc.) include placeholder empty
values like camera:mount: '' for user refinement. When these get
serialized into the routing request body, the alprwatch API rejects
them with HTTP 400.

Fix: strip empty-valued tags from enabled_profiles before sending
the routing request. Also refactor RoutingService to accept an
injectable http.Client for testability, and log error response
bodies for easier debugging of future API issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:32:34 -07:00
Doug Borg
6607e30038 Add tests for routing service and node profile serialization
Route calculation to alprwatch API fails with HTTP 400 because
built-in profiles include empty tag values (e.g. camera:mount: '')
that get serialized into the request body and rejected by the API.

Add routing_service_test.dart with 5 tests:
- Empty tags filtered from request (reproduces the bug)
- Successful route parsing
- HTTP error handling
- Network error wrapping
- API-level error surfacing

Add node_profile_test.dart with 4 tests:
- toJson/fromJson round-trip
- getDefaults returns expected profiles
- Empty tag values exist in defaults (documents bug origin)
- Equality based on id

Tests require RoutingService to accept an injectable http.Client,
which will be added in the next commit along with the fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:32:34 -07:00
Doug Borg
ef4205f4bd Make suggestion limit configurable and remove redundant .take(10) from widget
Move hardcoded suggestion limit to kNSIMaxSuggestions in dev_config, and remove
the redundant .take(10) from optionsBuilder since the fetch stage already caps
results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:32:18 -07:00
Doug Borg
ef6fc1c9c8 Materialize options iterable to list in optionsViewBuilder
Avoids repeated iteration of the lazy .where().take() iterable on each
call to .length and .elementAt() in ListView.builder.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:31:37 -07:00
Doug Borg
26c85df7e8 Fix dropdown dismiss by replacing manual overlay with RawAutocomplete
NSITagValueField used raw OverlayEntry + CompositedTransformFollower
with no tap-outside dismiss mechanism, causing suggestion dropdowns to
stay visible when tapping elsewhere. Replace with Flutter's
RawAutocomplete which handles dismiss, keyboard navigation, and
accessibility out of the box.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:31:37 -07:00
stopflock
20c1b9b108 Merge pull request #46 from dougborg/docs/dev-setup-guide
Rewrite dev setup docs with tested instructions
2026-02-09 15:18:58 -06:00
Doug Borg
0207f999ee Address Copilot review feedback on PR #46
- build.gradle.kts: use maxOf(flutter.minSdkVersion, 23) to preserve
  the floor required by oauth2_client/flutter_web_auth_2
- DEVELOPER.md: replace hardcoded /opt/homebrew paths with
  $(brew --prefix) for Intel Mac compatibility, use $HOME instead
  of /Users/$USER for --sdk_root
- README.md: label quick-start as macOS-specific, add cross-platform
  pointer to DEVELOPER.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 13:59:11 -07:00
Doug Borg
4a342aee9d Bump Dart SDK constraint to >=3.8.0 and document Flutter 3.35+ requirement
The RadioGroup widget (merged via PR #35) requires Flutter 3.35+ /
Dart 3.8+. The old constraint (>=3.5.0) allowed older SDKs that don't
have RadioGroup, causing cryptic build errors instead of a clear
version mismatch from pub get.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 13:54:42 -07:00
Doug Borg
3827a6fa1d Rewrite dev setup docs with tested, copy-pasteable instructions
Replaces the vague "Latest stable version" prerequisites in DEVELOPER.md
with concrete commands tested on a fresh macOS machine. Adds Android SDK
setup without Android Studio, documents the gen_icons_splashes.sh
requirement, and fixes the OAuth2 config to reference build_keys.conf
instead of the removed keys.dart.example. Also includes Flutter SDK
auto-migrations (iOS 13.0 min, gradle minSdk).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 13:54:42 -07:00
stopflock
ed38e9467c Merge pull request #47 from dougborg/fix/map-bounds-null-safety
Fix null-safety issue with mapBounds in getNearbyNodes
2026-02-09 14:52:26 -06:00
Doug Borg
d124cee9b3 Fix null-safety issue with mapBounds in getNearbyNodes
Change mapBounds from LatLngBounds? to final LatLngBounds so the
compiler can prove it's non-null after the inner try-catch. Addresses
review comment on PR #45.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 13:47:15 -07:00
stopflock
c13dd8e58a Merge pull request #45 from dougborg/pr/fix-upstream-lint
Fix lint warnings after RadioGroup migration
2026-02-09 14:42:25 -06:00
Doug Borg
037165653c Fix lint warnings and cleanup unused code after RadioGroup migration
Remove unused imports, fields, variables, and dead code introduced
during the RadioGroup widget migration and prior changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 13:36:18 -07:00
stopflock
98b73fe019 Merge pull request #35 from dougborg/pr/03-radiogroup
Migrate Radio to RadioGroup widget
2026-02-09 14:26:34 -06:00
stopflock
86e0d656d3 Merge pull request #34 from dougborg/pr/02-lint-cleanup
Add flutter_lints and fix all analyzer warnings
2026-02-09 11:43:48 -06:00
stopflock
a149562001 Merge pull request #38 from dougborg/pr/add-pr-validation-workflow
Add PR validation workflow
2026-02-08 20:19:13 -06:00
Doug Borg
e4b36719d7 Migrate Radio groupValue/onChanged to RadioGroup widget 2026-02-08 14:23:37 -07:00
Doug Borg
3570104800 Add mounted guards for BuildContext use across async gaps 2026-02-08 14:23:07 -07:00
Doug Borg
4fddd8e807 Replace print() with debugPrint() across codebase
Fixes avoid_print lint warnings by using debugPrint which respects
release mode and avoids console overflow on mobile platforms.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 14:23:07 -07:00