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>
- 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>
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>
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>
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>
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>
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>
- 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>
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>
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>
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>
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>
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>
Migrate all withOpacity() calls to withValues(alpha:) and
surfaceVariant to surfaceContainerHighest across the codebase.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use AssetManifest.loadFromAssetBundle instead of manually parsing the
deprecated AssetManifest.json. Fix a broken localization key reference
(queue.cameraWithIndex → queue.itemWithIndex).
Replace the standalone scripts/validate_localizations.dart with proper
flutter tests (11 tests across two groups): file integrity checks
(directory exists, en.json present, valid JSON structure, language code
file names, deep key-completeness across all locales) and t() lookup
tests (nested resolution, missing-key fallback, parameter substitution,
partial-path fallback).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
No CI currently runs on pull requests — the only workflow triggers on
releases. This adds a lightweight, secrets-free workflow that runs
flutter analyze and flutter test on PRs to main and pushes to main.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address PR review comments:
- Add mocktail and flutter_test to dev_dependencies in pubspec.yaml
- Add tearDown to reset AppState.instance between tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>