mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-03-21 02:13:39 +00:00
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>
This commit is contained in:
@@ -578,37 +578,41 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
flex: 3, // 30% for secondary action
|
||||
child: AnimatedBuilder(
|
||||
animation: LocalizationService.instance,
|
||||
builder: (context, child) => FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: ElevatedButton.icon(
|
||||
icon: Icon(Icons.download_for_offline),
|
||||
label: Text(LocalizationService.instance.download),
|
||||
onPressed: () {
|
||||
// Check minimum zoom level before opening download dialog
|
||||
final currentZoom = _mapController.mapController.camera.zoom;
|
||||
if (currentZoom < kMinZoomForOfflineDownload) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
LocalizationService.instance.t('download.areaTooBigMessage',
|
||||
params: [kMinZoomForOfflineDownload.toString()])
|
||||
builder: (context, child) {
|
||||
final appState = context.watch<AppState>();
|
||||
final canDownload = appState.selectedTileType?.allowsOfflineDownload ?? false;
|
||||
return FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: ElevatedButton.icon(
|
||||
icon: Icon(Icons.download_for_offline),
|
||||
label: Text(LocalizationService.instance.download),
|
||||
onPressed: canDownload ? () {
|
||||
// Check minimum zoom level before opening download dialog
|
||||
final currentZoom = _mapController.mapController.camera.zoom;
|
||||
if (currentZoom < kMinZoomForOfflineDownload) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
LocalizationService.instance.t('download.areaTooBigMessage',
|
||||
params: [kMinZoomForOfflineDownload.toString()])
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => DownloadAreaDialog(controller: _mapController.mapController),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => DownloadAreaDialog(controller: _mapController.mapController),
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: Size(0, 48),
|
||||
textStyle: TextStyle(fontSize: 16),
|
||||
} : null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: Size(0, 48),
|
||||
textStyle: TextStyle(fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -70,13 +70,13 @@ class ServicePolicy {
|
||||
attributionUrl = null;
|
||||
|
||||
/// OSM tile server (tile.openstreetmap.org)
|
||||
/// Policy: no offline/bulk downloading, min 7-day cache, must honor cache headers.
|
||||
/// Policy: min 7-day cache, must honor cache headers.
|
||||
/// Concurrency managed by flutter_map's NetworkTileProvider.
|
||||
/// https://operations.osmfoundation.org/policies/tiles/
|
||||
const ServicePolicy.osmTileServer()
|
||||
: maxConcurrentRequests = 0, // managed by flutter_map
|
||||
minRequestInterval = null,
|
||||
allowsOfflineDownload = false,
|
||||
allowsOfflineDownload = true,
|
||||
requiresClientCaching = true,
|
||||
minCacheTtl = const Duration(days: 7),
|
||||
attributionUrl = 'https://www.openstreetmap.org/copyright';
|
||||
|
||||
@@ -267,42 +267,6 @@ class _DownloadAreaDialogState extends State<DownloadAreaDialog> {
|
||||
final selectedProvider = appState.selectedTileProvider;
|
||||
final selectedTileType = appState.selectedTileType;
|
||||
|
||||
// Check if the tile provider allows offline downloads
|
||||
if (selectedTileType != null && !selectedTileType.allowsOfflineDownload) {
|
||||
if (!context.mounted) return;
|
||||
// Capture navigator before popping, since context is
|
||||
// deactivated after Navigator.pop.
|
||||
final navigator = Navigator.of(context);
|
||||
navigator.pop();
|
||||
showDialog(
|
||||
context: navigator.context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Row(
|
||||
children: [
|
||||
const Icon(Icons.block, color: Colors.orange),
|
||||
const SizedBox(width: 10),
|
||||
Text(locService.t('download.title')),
|
||||
],
|
||||
),
|
||||
content: Text(
|
||||
locService.t(
|
||||
'download.offlineNotPermitted',
|
||||
params: [
|
||||
selectedProvider?.name ?? locService.t('download.currentTileProvider'),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(locService.t('actions.ok')),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Guard: provider and tile type must be non-null for a
|
||||
// useful offline area (fetchLocalTile requires exact match).
|
||||
if (selectedProvider == null || selectedTileType == null) {
|
||||
|
||||
@@ -96,11 +96,11 @@ void main() {
|
||||
});
|
||||
|
||||
group('resolve', () {
|
||||
test('OSM tile server policy disallows offline download', () {
|
||||
test('OSM tile server policy allows offline download', () {
|
||||
final policy = ServicePolicyResolver.resolve(
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
);
|
||||
expect(policy.allowsOfflineDownload, false);
|
||||
expect(policy.allowsOfflineDownload, true);
|
||||
});
|
||||
|
||||
test('OSM tile server policy requires 7-day min cache TTL', () {
|
||||
@@ -175,7 +175,7 @@ void main() {
|
||||
final policy = ServicePolicyResolver.resolve(
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
);
|
||||
expect(policy.allowsOfflineDownload, false);
|
||||
expect(policy.allowsOfflineDownload, true);
|
||||
});
|
||||
|
||||
test('handles {quadkey} template variable', () {
|
||||
@@ -381,7 +381,7 @@ void main() {
|
||||
group('ServicePolicy', () {
|
||||
test('osmTileServer policy has correct values', () {
|
||||
const policy = ServicePolicy.osmTileServer();
|
||||
expect(policy.allowsOfflineDownload, false);
|
||||
expect(policy.allowsOfflineDownload, true);
|
||||
expect(policy.minCacheTtl, const Duration(days: 7));
|
||||
expect(policy.requiresClientCaching, true);
|
||||
expect(policy.attributionUrl, 'https://www.openstreetmap.org/copyright');
|
||||
|
||||
Reference in New Issue
Block a user