mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-05-20 15:34:47 +02:00
Move settings around part 3
This commit is contained in:
+1
-1
@@ -39,7 +39,7 @@ const String kClientName = 'DeFlock';
|
||||
const String kClientVersion = '0.9.13';
|
||||
|
||||
// Development/testing features - set to false for production builds
|
||||
const bool kEnableDevelopmentModes = true; // Set to false to hide sandbox/simulate modes and force production mode
|
||||
const bool kEnableDevelopmentModes = false; // Set to false to hide sandbox/simulate modes and force production mode
|
||||
|
||||
// Marker/node interaction
|
||||
const int kCameraMinZoomLevel = 10; // Minimum zoom to show nodes (Overpass)
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
"operatorProfileDeleted": "Operator profile deleted"
|
||||
},
|
||||
"offlineAreas": {
|
||||
"title": "Offline Areas",
|
||||
"noAreasTitle": "No offline areas",
|
||||
"noAreasSubtitle": "Download a map area for offline use.",
|
||||
"provider": "Provider",
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
"operatorProfileDeleted": "Perfil de operador eliminado"
|
||||
},
|
||||
"offlineAreas": {
|
||||
"title": "Áreas Sin Conexión",
|
||||
"noAreasTitle": "Sin áreas sin conexión",
|
||||
"noAreasSubtitle": "Descarga un área del mapa para uso sin conexión.",
|
||||
"provider": "Proveedor",
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
"operatorProfileDeleted": "Profil d'opérateur supprimé"
|
||||
},
|
||||
"offlineAreas": {
|
||||
"title": "Zones Hors Ligne",
|
||||
"noAreasTitle": "Aucune zone hors ligne",
|
||||
"noAreasSubtitle": "Téléchargez une zone de carte pour utilisation hors ligne.",
|
||||
"provider": "Fournisseur",
|
||||
|
||||
@@ -39,13 +39,17 @@ class _MaxNodesSectionState extends State<MaxNodesSection> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
locService.t('settings.maxNodes'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.filter_alt),
|
||||
title: Text(locService.t('settings.maxNodes')),
|
||||
title: Text(locService.t('settings.maxNodesSubtitle')),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(locService.t('settings.maxNodesSubtitle')),
|
||||
if (showWarning)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
|
||||
@@ -65,16 +65,22 @@ class _OfflineAreasSectionState extends State<OfflineAreasSection> {
|
||||
final locService = LocalizationService.instance;
|
||||
final areas = service.offlineAreas;
|
||||
|
||||
if (areas.isEmpty) {
|
||||
return ListTile(
|
||||
leading: const Icon(Icons.download_for_offline),
|
||||
title: Text(locService.t('offlineAreas.noAreasTitle')),
|
||||
subtitle: Text(locService.t('offlineAreas.noAreasSubtitle')),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: areas.map((area) {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
locService.t('offlineAreas.title'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (areas.isEmpty)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.download_for_offline),
|
||||
title: Text(locService.t('offlineAreas.noAreasTitle')),
|
||||
subtitle: Text(locService.t('offlineAreas.noAreasSubtitle')),
|
||||
)
|
||||
else
|
||||
...areas.map((area) {
|
||||
String diskStr = area.sizeBytes > 0
|
||||
? area.sizeBytes > 1024 * 1024
|
||||
? "${(area.sizeBytes / (1024 * 1024)).toStringAsFixed(2)} ${locService.t('offlineAreas.megabytes')}"
|
||||
@@ -202,7 +208,8 @@ class _OfflineAreasSectionState extends State<OfflineAreasSection> {
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,14 +61,23 @@ class OfflineModeSection extends StatelessWidget {
|
||||
final locService = LocalizationService.instance;
|
||||
final appState = context.watch<AppState>();
|
||||
|
||||
return ListTile(
|
||||
leading: const Icon(Icons.wifi_off),
|
||||
title: Text(locService.t('settings.offlineMode')),
|
||||
subtitle: Text(locService.t('settings.offlineModeSubtitle')),
|
||||
trailing: Switch(
|
||||
value: appState.offlineMode,
|
||||
onChanged: (value) => _handleOfflineModeChange(context, appState, value),
|
||||
),
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
locService.t('settings.offlineMode'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.wifi_off),
|
||||
title: Text(locService.t('settings.offlineModeSubtitle')),
|
||||
trailing: Switch(
|
||||
value: appState.offlineMode,
|
||||
onChanged: (value) => _handleOfflineModeChange(context, appState, value),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -95,9 +95,8 @@ class _ProximityAlertsSectionState extends State<ProximityAlertsSection> {
|
||||
|
||||
// Enable/disable toggle
|
||||
SwitchListTile(
|
||||
title: const Text('Enable proximity alerts'),
|
||||
title: const Text('Get notified when approaching surveillance devices'),
|
||||
subtitle: Text(
|
||||
'Get notified when approaching surveillance devices\n'
|
||||
'Uses extra battery for continuous location monitoring\n'
|
||||
'${_notificationsEnabled ? "✓ Notifications enabled" : "⚠ Notifications disabled"}',
|
||||
style: const TextStyle(fontSize: 12),
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../app_state.dart';
|
||||
import '../models/tile_provider.dart';
|
||||
import '../services/localization_service.dart';
|
||||
import 'tile_provider_editor_screen.dart';
|
||||
|
||||
class TileProviderManagementScreen extends StatelessWidget {
|
||||
const TileProviderManagementScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: LocalizationService.instance,
|
||||
builder: (context, child) {
|
||||
final locService = LocalizationService.instance;
|
||||
final appState = context.watch<AppState>();
|
||||
final providers = appState.tileProviders;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(locService.t('tileProviders.title')),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.add),
|
||||
onPressed: () => _addProvider(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: providers.isEmpty
|
||||
? Center(
|
||||
child: Text(locService.t('tileProviders.noProvidersConfigured')),
|
||||
)
|
||||
: ListView.builder(
|
||||
itemCount: providers.length,
|
||||
itemBuilder: (context, index) {
|
||||
final provider = providers[index];
|
||||
final isSelected = appState.selectedTileProvider?.id == provider.id;
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
provider.name,
|
||||
style: TextStyle(
|
||||
fontWeight: isSelected ? FontWeight.bold : null,
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(locService.t('tileProviders.tileTypesCount', params: [provider.tileTypes.length.toString()])),
|
||||
if (provider.apiKey?.isNotEmpty == true)
|
||||
Text(
|
||||
locService.t('tileProviders.apiKeyConfigured'),
|
||||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
if (!provider.isUsable)
|
||||
Text(
|
||||
locService.t('tileProviders.needsApiKey'),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: isSelected
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.surfaceVariant,
|
||||
child: Icon(
|
||||
Icons.map,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.onPrimary
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
trailing: providers.length > 1
|
||||
? PopupMenuButton<String>(
|
||||
onSelected: (action) {
|
||||
switch (action) {
|
||||
case 'edit':
|
||||
_editProvider(context, provider);
|
||||
break;
|
||||
case 'delete':
|
||||
_deleteProvider(context, provider);
|
||||
break;
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'edit',
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.edit),
|
||||
const SizedBox(width: 8),
|
||||
Text(locService.t('actions.edit')),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.delete),
|
||||
const SizedBox(width: 8),
|
||||
Text(locService.t('tileProviders.deleteProvider')),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: const Icon(Icons.lock, size: 16), // Can't delete last provider
|
||||
onTap: () => _editProvider(context, provider),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _addProvider(BuildContext context) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TileProviderEditorScreen(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _editProvider(BuildContext context, TileProvider provider) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TileProviderEditorScreen(provider: provider),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _deleteProvider(BuildContext context, TileProvider provider) {
|
||||
final locService = LocalizationService.instance;
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(locService.t('tileProviders.deleteProvider')),
|
||||
content: Text(locService.t('tileProviders.deleteProviderConfirm', params: [provider.name])),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(locService.t('actions.cancel')),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.read<AppState>().deleteTileProvider(provider.id);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(locService.t('tileProviders.deleteProvider')),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user