diff --git a/lib/dev_config.dart b/lib/dev_config.dart index e597807..70d53b1 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -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) diff --git a/lib/localizations/en.json b/lib/localizations/en.json index 67d7aec..0e10f82 100644 --- a/lib/localizations/en.json +++ b/lib/localizations/en.json @@ -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", diff --git a/lib/localizations/es.json b/lib/localizations/es.json index 016ecd7..f123e32 100644 --- a/lib/localizations/es.json +++ b/lib/localizations/es.json @@ -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", diff --git a/lib/localizations/fr.json b/lib/localizations/fr.json index 46017e3..4deda22 100644 --- a/lib/localizations/fr.json +++ b/lib/localizations/fr.json @@ -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", diff --git a/lib/screens/settings_screen_sections/max_nodes_section.dart b/lib/screens/settings_screen_sections/max_nodes_section.dart index 54351e5..f7130d8 100644 --- a/lib/screens/settings_screen_sections/max_nodes_section.dart +++ b/lib/screens/settings_screen_sections/max_nodes_section.dart @@ -39,13 +39,17 @@ class _MaxNodesSectionState extends State { 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), diff --git a/lib/screens/settings_screen_sections/offline_areas_section.dart b/lib/screens/settings_screen_sections/offline_areas_section.dart index 2b70593..6144598 100644 --- a/lib/screens/settings_screen_sections/offline_areas_section.dart +++ b/lib/screens/settings_screen_sections/offline_areas_section.dart @@ -65,16 +65,22 @@ class _OfflineAreasSectionState extends State { 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 { ), ); }).toList(), - ); + ], + ); }, ); } diff --git a/lib/screens/settings_screen_sections/offline_mode_section.dart b/lib/screens/settings_screen_sections/offline_mode_section.dart index 250e531..eddfb0d 100644 --- a/lib/screens/settings_screen_sections/offline_mode_section.dart +++ b/lib/screens/settings_screen_sections/offline_mode_section.dart @@ -61,14 +61,23 @@ class OfflineModeSection extends StatelessWidget { final locService = LocalizationService.instance; final appState = context.watch(); - 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), + ), + ), + ], ); }, ); diff --git a/lib/screens/settings_screen_sections/proximity_alerts_section.dart b/lib/screens/settings_screen_sections/proximity_alerts_section.dart index 0f7919c..2bb1ed8 100644 --- a/lib/screens/settings_screen_sections/proximity_alerts_section.dart +++ b/lib/screens/settings_screen_sections/proximity_alerts_section.dart @@ -95,9 +95,8 @@ class _ProximityAlertsSectionState extends State { // 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), diff --git a/lib/screens/tile_provider_management_screen.dart b/lib/screens/tile_provider_management_screen.dart deleted file mode 100644 index 8629f22..0000000 --- a/lib/screens/tile_provider_management_screen.dart +++ /dev/null @@ -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(); - 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( - 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().deleteTileProvider(provider.id); - Navigator.of(context).pop(); - }, - child: Text(locService.t('tileProviders.deleteProvider')), - ), - ], - ), - ); - } -} \ No newline at end of file