mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-05-24 09:04:11 +02:00
fixes tile re-rendering after long rate limit periods without having to zoom/pan
This commit is contained in:
@@ -6,6 +6,7 @@ import 'package:flutter_map/flutter_map.dart';
|
||||
import '../../models/camera_profile.dart';
|
||||
import '../../models/osm_camera_node.dart';
|
||||
import '../../app_state.dart';
|
||||
import '../network_status.dart';
|
||||
|
||||
/// Fetches cameras from the Overpass OSM API for the given bounds and profiles.
|
||||
/// If fetchAllPages is true, returns all possible cameras using multiple API calls (paging with pageSize).
|
||||
@@ -45,11 +46,13 @@ Future<List<OsmCameraNode>> camerasFromOverpass({
|
||||
print('[camerasFromOverpass] Status: ${resp.statusCode}, Length: ${resp.body.length}');
|
||||
if (resp.statusCode != 200) {
|
||||
print('[camerasFromOverpass] Overpass failed: ${resp.body}');
|
||||
NetworkStatus.instance.reportOverpassIssue();
|
||||
return [];
|
||||
}
|
||||
final data = jsonDecode(resp.body) as Map<String, dynamic>;
|
||||
final elements = data['elements'] as List<dynamic>;
|
||||
print('[camerasFromOverpass] Retrieved elements: ${elements.length}');
|
||||
NetworkStatus.instance.reportOverpassSuccess();
|
||||
return elements.whereType<Map<String, dynamic>>().map((e) {
|
||||
return OsmCameraNode(
|
||||
id: e['id'],
|
||||
@@ -59,6 +62,14 @@ Future<List<OsmCameraNode>> camerasFromOverpass({
|
||||
}).toList();
|
||||
} catch (e) {
|
||||
print('[camerasFromOverpass] Overpass exception: $e');
|
||||
|
||||
// Report network issues on connection errors
|
||||
if (e.toString().contains('Connection refused') ||
|
||||
e.toString().contains('Connection timed out') ||
|
||||
e.toString().contains('Connection reset')) {
|
||||
NetworkStatus.instance.reportOverpassIssue();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:async';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flock_map_app/dev_config.dart';
|
||||
import '../network_status.dart';
|
||||
|
||||
/// Global semaphore to limit simultaneous tile fetches
|
||||
final _tileFetchSemaphore = _SimpleSemaphore(4); // Max 4 concurrent
|
||||
@@ -33,13 +34,23 @@ Future<List<int>> fetchOSMTile({
|
||||
print('[fetchOSMTile] HTTP ${resp.statusCode} for $z/$x/$y, length=${resp.bodyBytes.length}');
|
||||
if (resp.statusCode == 200 && resp.bodyBytes.isNotEmpty) {
|
||||
print('[fetchOSMTile] SUCCESS $z/$x/$y');
|
||||
NetworkStatus.instance.reportOsmTileSuccess();
|
||||
return resp.bodyBytes;
|
||||
} else {
|
||||
print('[fetchOSMTile] FAIL $z/$x/$y: code=${resp.statusCode}, bytes=${resp.bodyBytes.length}');
|
||||
NetworkStatus.instance.reportOsmTileIssue();
|
||||
throw HttpException('Failed to fetch tile $z/$x/$y: status ${resp.statusCode}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('[fetchOSMTile] Exception $z/$x/$y: $e');
|
||||
|
||||
// Report network issues on connection errors
|
||||
if (e.toString().contains('Connection refused') ||
|
||||
e.toString().contains('Connection timed out') ||
|
||||
e.toString().contains('Connection reset')) {
|
||||
NetworkStatus.instance.reportOsmTileIssue();
|
||||
}
|
||||
|
||||
if (attempt >= maxAttempts) {
|
||||
print("[fetchOSMTile] Failed for $z/$x/$y after $attempt attempts: $e");
|
||||
rethrow;
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:async';
|
||||
|
||||
enum NetworkIssueType { osmTiles, overpassApi, both }
|
||||
|
||||
class NetworkStatus extends ChangeNotifier {
|
||||
static final NetworkStatus instance = NetworkStatus._();
|
||||
NetworkStatus._();
|
||||
|
||||
bool _osmTilesHaveIssues = false;
|
||||
bool _overpassHasIssues = false;
|
||||
Timer? _osmRecoveryTimer;
|
||||
Timer? _overpassRecoveryTimer;
|
||||
|
||||
// Getters
|
||||
bool get hasAnyIssues => _osmTilesHaveIssues || _overpassHasIssues;
|
||||
bool get osmTilesHaveIssues => _osmTilesHaveIssues;
|
||||
bool get overpassHasIssues => _overpassHasIssues;
|
||||
|
||||
NetworkIssueType? get currentIssueType {
|
||||
if (_osmTilesHaveIssues && _overpassHasIssues) return NetworkIssueType.both;
|
||||
if (_osmTilesHaveIssues) return NetworkIssueType.osmTiles;
|
||||
if (_overpassHasIssues) return NetworkIssueType.overpassApi;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Report OSM tile server issues
|
||||
void reportOsmTileIssue() {
|
||||
if (!_osmTilesHaveIssues) {
|
||||
_osmTilesHaveIssues = true;
|
||||
notifyListeners();
|
||||
debugPrint('[NetworkStatus] OSM tile server issues detected');
|
||||
}
|
||||
|
||||
// Reset recovery timer - if we keep getting errors, keep showing indicator
|
||||
_osmRecoveryTimer?.cancel();
|
||||
_osmRecoveryTimer = Timer(const Duration(minutes: 2), () {
|
||||
_osmTilesHaveIssues = false;
|
||||
notifyListeners();
|
||||
debugPrint('[NetworkStatus] OSM tile server issues cleared');
|
||||
});
|
||||
}
|
||||
|
||||
/// Report Overpass API issues
|
||||
void reportOverpassIssue() {
|
||||
if (!_overpassHasIssues) {
|
||||
_overpassHasIssues = true;
|
||||
notifyListeners();
|
||||
debugPrint('[NetworkStatus] Overpass API issues detected');
|
||||
}
|
||||
|
||||
// Reset recovery timer
|
||||
_overpassRecoveryTimer?.cancel();
|
||||
_overpassRecoveryTimer = Timer(const Duration(minutes: 2), () {
|
||||
_overpassHasIssues = false;
|
||||
notifyListeners();
|
||||
debugPrint('[NetworkStatus] Overpass API issues cleared');
|
||||
});
|
||||
}
|
||||
|
||||
/// Report successful operations to potentially clear issues faster
|
||||
void reportOsmTileSuccess() {
|
||||
// Don't immediately clear on single success, but reduce recovery time
|
||||
if (_osmTilesHaveIssues) {
|
||||
_osmRecoveryTimer?.cancel();
|
||||
_osmRecoveryTimer = Timer(const Duration(seconds: 30), () {
|
||||
_osmTilesHaveIssues = false;
|
||||
notifyListeners();
|
||||
debugPrint('[NetworkStatus] OSM tile server issues cleared after success');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void reportOverpassSuccess() {
|
||||
if (_overpassHasIssues) {
|
||||
_overpassRecoveryTimer?.cancel();
|
||||
_overpassRecoveryTimer = Timer(const Duration(seconds: 30), () {
|
||||
_overpassHasIssues = false;
|
||||
notifyListeners();
|
||||
debugPrint('[NetworkStatus] Overpass API issues cleared after success');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_osmRecoveryTimer?.cancel();
|
||||
_overpassRecoveryTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user