mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-02-13 09:12:56 +00:00
Move settings around part 2
This commit is contained in:
@@ -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 = false; // Set to false to hide sandbox/simulate modes and force production mode
|
||||
const bool kEnableDevelopmentModes = true; // 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)
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"offlineSettings": "Offline Settings",
|
||||
"offlineSettingsSubtitle": "Manage offline mode and downloaded areas",
|
||||
"advancedSettings": "Advanced Settings",
|
||||
"advancedSettingsSubtitle": "Performance and tile provider settings"
|
||||
"advancedSettingsSubtitle": "Performance, alerts, and tile provider settings",
|
||||
"proximityAlerts": "Proximity Alerts"
|
||||
},
|
||||
"node": {
|
||||
"title": "Node #{}",
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"offlineSettings": "Configuración Sin Conexión",
|
||||
"offlineSettingsSubtitle": "Gestionar modo sin conexión y áreas descargadas",
|
||||
"advancedSettings": "Configuración Avanzada",
|
||||
"advancedSettingsSubtitle": "Configuración de rendimiento y proveedores de teselas"
|
||||
"advancedSettingsSubtitle": "Configuración de rendimiento, alertas y proveedores de teselas",
|
||||
"proximityAlerts": "Alertas de Proximidad"
|
||||
},
|
||||
"node": {
|
||||
"title": "Nodo #{}",
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"offlineSettings": "Paramètres Hors Ligne",
|
||||
"offlineSettingsSubtitle": "Gérer le mode hors ligne et les zones téléchargées",
|
||||
"advancedSettings": "Paramètres Avancés",
|
||||
"advancedSettingsSubtitle": "Paramètres de performance et de fournisseurs de tuiles"
|
||||
"advancedSettingsSubtitle": "Paramètres de performance, alertes et fournisseurs de tuiles",
|
||||
"proximityAlerts": "Alertes de Proximité"
|
||||
},
|
||||
"node": {
|
||||
"title": "Nœud #{}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'settings_screen_sections/max_nodes_section.dart';
|
||||
import 'settings_screen_sections/proximity_alerts_section.dart';
|
||||
import 'settings_screen_sections/tile_provider_section.dart';
|
||||
import '../services/localization_service.dart';
|
||||
|
||||
@@ -21,6 +22,8 @@ class AdvancedSettingsScreen extends StatelessWidget {
|
||||
children: const [
|
||||
MaxNodesSection(),
|
||||
Divider(),
|
||||
ProximityAlertsSection(),
|
||||
Divider(),
|
||||
TileProviderSection(),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'settings_screen_sections/auth_section.dart';
|
||||
import 'settings_screen_sections/upload_mode_section.dart';
|
||||
import 'settings_screen_sections/queue_section.dart';
|
||||
import 'settings_screen_sections/about_section.dart';
|
||||
import 'settings_screen_sections/proximity_alerts_section.dart';
|
||||
import 'settings_screen_sections/language_section.dart';
|
||||
import '../services/localization_service.dart';
|
||||
import '../dev_config.dart';
|
||||
@@ -31,8 +30,6 @@ class SettingsScreen extends StatelessWidget {
|
||||
const Divider(),
|
||||
const QueueSection(),
|
||||
const Divider(),
|
||||
const ProximityAlertsSection(),
|
||||
const Divider(),
|
||||
|
||||
// Navigation to sub-pages
|
||||
_buildNavigationTile(
|
||||
|
||||
@@ -57,15 +57,11 @@ class _LanguageSectionState extends State<LanguageSection> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
|
||||
child: Text(
|
||||
locService.t('settings.language'),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
locService.t('settings.language'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// System Default option
|
||||
RadioListTile<String?>(
|
||||
title: Text(locService.t('settings.systemDefault')),
|
||||
|
||||
@@ -22,7 +22,10 @@ class OperatorProfileListSection extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(locService.t('operatorProfiles.title'), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
locService.t('operatorProfiles.title'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
|
||||
@@ -22,7 +22,10 @@ class ProfileListSection extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(locService.t('profiles.nodeProfiles'), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
locService.t('profiles.nodeProfiles'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
|
||||
@@ -82,14 +82,14 @@ class _ProximityAlertsSectionState extends State<ProximityAlertsSection> {
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<AppState>(
|
||||
builder: (context, appState, child) {
|
||||
final locService = LocalizationService.instance;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Proximity Alerts',
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
locService.t('settings.proximityAlerts'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
|
||||
import '../../app_state.dart';
|
||||
import '../../models/tile_provider.dart';
|
||||
import '../../services/localization_service.dart';
|
||||
import '../tile_provider_management_screen.dart';
|
||||
import '../tile_provider_editor_screen.dart';
|
||||
|
||||
class TileProviderSection extends StatelessWidget {
|
||||
const TileProviderSection({super.key});
|
||||
@@ -15,32 +15,166 @@ class TileProviderSection extends StatelessWidget {
|
||||
animation: LocalizationService.instance,
|
||||
builder: (context, child) {
|
||||
final locService = LocalizationService.instance;
|
||||
final appState = context.watch<AppState>();
|
||||
final providers = appState.tileProviders;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
locService.t('mapTiles.title'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
locService.t('mapTiles.title'),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () => _addProvider(context),
|
||||
icon: const Icon(Icons.add),
|
||||
label: Text(locService.t('tileProviders.addProvider')),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TileProviderManagementScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.settings),
|
||||
label: Text(locService.t('mapTiles.manageProviders')),
|
||||
),
|
||||
),
|
||||
if (providers.isEmpty)
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text(locService.t('tileProviders.noProvidersConfigured')),
|
||||
),
|
||||
)
|
||||
else
|
||||
...providers.map((provider) => _buildProviderTile(context, provider, appState)).toList(),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProviderTile(BuildContext context, TileProvider provider, AppState appState) {
|
||||
final locService = LocalizationService.instance;
|
||||
final isSelected = appState.selectedTileProvider?.id == provider.id;
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(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: appState.tileProviders.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