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>
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>
- 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>