Commit Graph

622 Commits

Author SHA1 Message Date
Doug Borg
ba80b88595 Update lib/widgets/map/map_data_manager.dart
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-11 22:06:52 -06:00
Doug Borg
ebb7fd090f Address review: stable tie-breaker and accurate log message
- Add node id tie-breaker to sort comparator so equal-distance nodes
  have deterministic ordering across renders (prevents flicker)
- Log validNodesCount instead of allNodes.length so the message
  reflects the actual post-filter count

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:38:58 -06:00
Doug Borg
fe401cc04b Prioritize closest nodes to viewport center when render limit is active
Sort nodes by squared distance from viewport center before applying the
render limit, so visible nodes always make the cut instead of arbitrary
selection causing gaps that shift as you pan.

Also: inject node provider for testability, deduplicate validity filter,
and reduce debug log spam to state transitions only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 15:09:37 -06:00
stopflock
de65cecc6a bump ver v2.9.0-release v2.9.0-beta 2026-03-07 16:51:38 -06:00
stopflock
122b303378 Merge pull request #132 from dougborg/fix/tile-retry-on-error
I think this finally has online, offline, proper caching, tile types, all working correctly.
2026-03-07 16:33:42 -06:00
Doug Borg
91e5177056 Detect config drift in cached tile providers and replace stale instances
When a user edits a tile type's URL template, max zoom, or API key
without changing IDs, the cached DeflockTileProvider would keep the old
frozen config. Now _getOrCreateProvider() computes a config fingerprint
and replaces the provider when drift is detected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:34:01 -07:00
Doug Borg
f3f40f36ef Allow OSM offline downloads, disable button for restricted providers
Allow offline area downloads for OSM tile server. Move the "downloads
not permitted" check from inside the download dialog to the download
button itself — the button is now disabled (greyed out) when the
current tile type doesn't support offline downloads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:34:01 -07:00
Doug Borg
2d92214bed Add offline-first tile system with per-provider caching and error retry
- Add ServicePolicy framework with OSM-specific rate limiting and TTL
- Add per-provider disk tile cache (ProviderTileCacheStore) with O(1)
  lookup, oldest-modified eviction, and ETag/304 revalidation
- Rewrite DeflockTileProvider with two paths: common (NetworkTileProvider)
  and offline-first (disk cache -> local tiles -> network with caching)
- Add zoom-aware offline routing so tiles outside offline area zoom ranges
  use the efficient common path instead of the overhead-heavy offline path
- Fix HTTP client lifecycle: dispose() is now a no-op for flutter_map
  widget recycling; shutdown() handles permanent teardown
- Add TileLayerManager with exponential backoff retry (2s->60s cap),
  provider switch detection, and backoff reset
- Guard null provider/tileType in download dialog with localized error
- Fix Nominatim cache key to use normalized viewbox values
- Comprehensive test coverage (1800+ lines across 6 test files)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:34:01 -07:00
stopflock
be446fbcbc Merge pull request #140 from FoggedLens/fix/force-simulate-without-secrets
Force simulate mode when OAuth secrets are missing
2026-03-07 12:34:42 -06:00
Doug Borg
5728b4f70f Force simulate mode when OSM OAuth secrets are missing
Preview/PR builds don't have access to GitHub Secrets, so the OAuth
client IDs are empty. Previously this caused a runtime crash from
keys.dart throwing on empty values. Now we detect missing secrets
and force simulate mode, which already fully supports fake auth
and uploads.

Also fixes a latent bug where forceLogin() would crash with
LateInitializationError in simulate mode since _helper is never
initialized when OAuth setup is skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:25:17 -07:00
stopflock
aeb1903bbc Merge pull request #135 from subfloor201/chore/update-do_builds.sh
Don't require trailing new line in build.keys.conf
2026-03-03 16:04:03 -06:00
stopflock
57df8e83a7 fix tests for profile order, add correct migration 2026-03-02 13:56:07 -06:00
stopflock
bc671c4efe Fix phantom FOVs, reorderable profiles 2026-03-02 12:38:49 -06:00
jay
4941c2726d don't require trailing new line in build.keys.conf 2026-02-27 23:59:16 -06:00
stopflock
b56e9325b3 Update changelog.json
280
2026-02-25 19:28:48 -06:00
stopflock
30f546be29 Update pubspec.yaml
bump version
2026-02-25 19:27:59 -06:00
stopflock
dc817e5eb7 Merge pull request #115 from dougborg/chore/ios26-sdk
Build with iOS 26 SDK for App Store deadline
v2.8.0-rc
2026-02-25 17:07:23 -06:00
stopflock
e1cca2f503 Merge pull request #85 from dougborg/chore/deps-applinks-packageinfo
chore(deps): Update app_links and package_info_plus to latest majors
2026-02-25 16:38:05 -06:00
Doug Borg
abd8682b49 Build with iOS 26 SDK to meet App Store deadline
Apple requires all iOS/iPadOS apps to be built with the iOS 26 SDK
(Xcode 26+) starting April 28, 2026. Switch the build-ios and
upload-to-stores jobs from macos-latest (macOS 15 / Xcode 16) to
macos-26 (macOS 26 / Xcode 26).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:32:16 -07:00
Doug Borg
90a806a10d chore(deps): upgrade minor/patch dependencies within existing constraints
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:32:00 -07:00
Doug Borg
b6bcd23667 chore(android): bump Dart SDK floor, desugar_jdk_libs, and fix Kotlin DSL deprecation
- Bump Dart SDK constraint from >=3.8.0 to >=3.10.3 to match resolved dependency floor
- Upgrade desugar_jdk_libs from 2.0.4 to 2.1.5 (adds Stream.toList(), better locale support)
- Migrate deprecated kotlinOptions { jvmTarget } to kotlin { compilerOptions { jvmTarget } }
- Remove stale comments and non-breaking space characters

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:32:00 -07:00
Doug Borg
dba375c63d chore(deps): update app_links and package_info_plus to latest major versions
Upgrade packages:
- app_links: ^6.1.4 → ^7.0.0 (backward compatible with v6)
- package_info_plus: ^8.0.0 → ^9.0.0 (build tooling only, no Dart API changes)

Bump Android build tooling to latest Flutter 3.38-compatible versions:
- AGP: 8.9.1 → 8.11.1
- Gradle: 8.12 → 8.14
- Kotlin: 2.1.0 → 2.2.20

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:20:50 -07:00
stopflock
6c52541361 Merge pull request #84 from dougborg/chore/deps-auth-stable
chore(deps): Move auth packages to stable releases
2026-02-25 15:11:10 -06:00
stopflock
fcf7ff7a98 Merge pull request #82 from dougborg/chore/deps-minor-patch
chore(deps): Upgrade minor/patch dependencies
2026-02-25 15:07:58 -06:00
Doug Borg
206b3afe9d chore(deps): move flutter_web_auth_2 and flutter_secure_storage to stable releases
Move auth-critical packages from pre-release pins to stable:
- flutter_web_auth_2: 5.0.0-alpha.3 → ^5.0.1
- flutter_secure_storage: 10.0.0-beta.4 → ^10.0.0
- oauth2_client: 4.2.0 → 4.2.3 (auto-resolved, was blocked by pre-release pins)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:45:38 -07:00
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