Files
Siro/siro_driver/lib/services/offline_map_service.dart
2026-06-09 08:40:31 +03:00

120 lines
3.9 KiB
Dart
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:io';
import 'package:get/get.dart';
import 'package:intaleq_maps/intaleq_maps.dart';
import 'dart:math' as math;
import '../main.dart';
import '../print.dart';
class OfflineMapService {
static final OfflineMapService instance = OfflineMapService._();
OfflineMapService._();
final _offlineRegionName = "UserRegion";
bool _isDownloading = false;
LatLng? _lastDownloadedCenter;
/// Calculate bounding box for a given center and radius in km
LatLngBounds _calculateBounds(LatLng center, double radiusKm) {
const double earthRadius = 6371.0;
// Latitude degrees per km
double latDelta = (radiusKm / earthRadius) * (180 / math.pi);
// Longitude degrees per km at given latitude
double lngDelta = (radiusKm / earthRadius) *
(180 / math.pi) /
math.cos(center.latitude * math.pi / 180);
return LatLngBounds(
southwest:
LatLng(center.latitude - latDelta, center.longitude - lngDelta),
northeast:
LatLng(center.latitude + latDelta, center.longitude + lngDelta),
);
}
/// Downloads a specified radius around a coordinate
Future<void> downloadRegion(LatLng center,
{double radiusKm = 10.0,
double minZoom = 6.0,
double maxZoom = 15.0}) async {
if (_isDownloading) return;
// Avoid re-downloading if the user hasn't moved significantly (e.g. > 5km)
if (_lastDownloadedCenter != null) {
double distance = _calculateDistance(center, _lastDownloadedCenter!);
if (distance < 5.0) return; // skip if close to previously downloaded
}
_isDownloading = true;
try {
final bounds = _calculateBounds(center, radiusKm);
// Select style based on current theme
final String styleStr =
Get.isDarkMode ? "assets/style_dark.json" : "assets/style.json";
// iOS native crash guard: MLNTilePyramidOfflineRegion does not support relative asset URLs.
// We skip native offline registration on iOS if using local assets to ensure stability.
if (Platform.isIOS && !styleStr.startsWith('http')) {
Log.print(
" Skipping native offline registration on iOS for asset-based style to prevent crash.");
return;
}
final regionDefinition = OfflineRegionDefinition(
bounds: bounds,
mapStyleUrl: styleStr,
minZoom: minZoom,
maxZoom: maxZoom,
);
// We'll update the last downloaded center immediately
_lastDownloadedCenter = center;
// MapLibre standard API for offline downloads
await downloadOfflineRegion(regionDefinition, metadata: {
'name': '$_offlineRegionName-${center.latitude}-${center.longitude}',
'downloadDate': DateTime.now().toIso8601String(),
});
// Reassurance log for the user
Log.print("📍 Map Ready: Service is utilizing local tile cache.");
Log.print(
"✅ Offline Map Cached for Region: $center (radius: ${radiusKm}km, style: $styleStr)");
} catch (e) {
Log.print("⚠️ Offline Map Download Failed: $e");
} finally {
_isDownloading = false;
}
}
/// Helper to calculate distance in km
double _calculateDistance(LatLng p1, LatLng p2) {
var p = 0.017453292519943295;
var c = math.cos;
var a = 0.5 -
c((p2.latitude - p1.latitude) * p) / 2 +
c(p1.latitude * p) *
c(p2.latitude * p) *
(1 - c((p2.longitude - p1.longitude) * p)) /
2;
return 12742 * math.asin(math.sqrt(a));
}
/// Clears all offline map regions and tiles from local storage
Future<void> clearCache() async {
try {
Log.print("♻️ Purging MapLibre Offline Cache...");
final List<OfflineRegion> regions = await getListOfRegions();
for (var region in regions) {
await deleteOfflineRegion(region.id);
}
Log.print("✅ Map cache cleared successfully. ${regions.length} regions removed.");
} catch (e) {
Log.print("⚠️ Failed to clear map cache: $e");
}
}
}