diff --git a/lib/screens/device_config_screen.dart b/lib/screens/device_config_screen.dart index d13cbca..c2b2a1e 100644 --- a/lib/screens/device_config_screen.dart +++ b/lib/screens/device_config_screen.dart @@ -342,6 +342,21 @@ class _DeviceConfigScreenState extends State { }); } + void _syncRadioPresetSelection() { + final freqResult = ValidationService().parseFrequency(_freqController.text); + final matchedPreset = freqResult.isSuccess + ? _matchRadioPreset( + frequencyKhz: (freqResult.value! * 1000).round(), + bandwidth: _bandwidthToValue(_selectedBandwidth), + spreadingFactor: _selectedSpreadingFactor, + codingRate: _selectedCodingRate, + ) + : null; + + _selectedRadioPreset = matchedPreset; + _showCustomRadioSettings = matchedPreset == null; + } + void _markPublicInfoDirty() { if (_publicInfoSaved || _publicInfoError != null) { setState(() { @@ -902,6 +917,7 @@ class _DeviceConfigScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ DropdownButtonFormField<_RadioPreset?>( + key: ValueKey(_selectedRadioPreset?.id ?? 'custom'), initialValue: _selectedRadioPreset, decoration: InputDecoration( labelText: 'Radio preset', @@ -993,16 +1009,13 @@ class _DeviceConfigScreenState extends State { decimal: true, ), onChanged: (_) { - if (_selectedRadioPreset != null) { - setState(() { - _selectedRadioPreset = null; - }); - } + setState(_syncRadioPresetSelection); _markRadioSettingsDirty(); }, ), const SizedBox(height: 16), DropdownButtonFormField( + key: ValueKey('bandwidth-$_selectedBandwidth'), initialValue: _selectedBandwidth, decoration: InputDecoration( labelText: AppLocalizations.of( @@ -1024,7 +1037,7 @@ class _DeviceConfigScreenState extends State { if (newValue != null) { setState(() { _selectedBandwidth = newValue; - _selectedRadioPreset = null; + _syncRadioPresetSelection(); }); _markRadioSettingsDirty(); } @@ -1032,6 +1045,9 @@ class _DeviceConfigScreenState extends State { ), const SizedBox(height: 16), DropdownButtonFormField( + key: ValueKey( + 'spreading-factor-$_selectedSpreadingFactor', + ), initialValue: _selectedSpreadingFactor, decoration: InputDecoration( labelText: AppLocalizations.of( @@ -1055,7 +1071,7 @@ class _DeviceConfigScreenState extends State { if (newValue != null) { setState(() { _selectedSpreadingFactor = newValue; - _selectedRadioPreset = null; + _syncRadioPresetSelection(); }); _markRadioSettingsDirty(); } @@ -1063,6 +1079,7 @@ class _DeviceConfigScreenState extends State { ), const SizedBox(height: 16), DropdownButtonFormField( + key: ValueKey('coding-rate-$_selectedCodingRate'), initialValue: _selectedCodingRate, decoration: InputDecoration( labelText: AppLocalizations.of( @@ -1086,7 +1103,7 @@ class _DeviceConfigScreenState extends State { if (newValue != null) { setState(() { _selectedCodingRate = newValue; - _selectedRadioPreset = null; + _syncRadioPresetSelection(); }); _markRadioSettingsDirty(); } diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index cb46ebd..e284091 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -1260,156 +1260,6 @@ class _SettingsScreenState extends State { ), ), ]), - _buildSettingsCard([ - ListTile( - leading: const Icon(Icons.layers_outlined), - title: const Text('Rendering'), - subtitle: const Text( - 'Control map drawings and overlay layers used by the renderer', - ), - ), - Consumer( - builder: (context, drawingProvider, child) => SwitchListTile( - secondary: const Icon(Icons.draw_outlined), - title: Text(AppLocalizations.of(context)!.showReceivedDrawings), - subtitle: const Text( - 'Render drawings received from other devices on the map', - ), - value: drawingProvider.showReceivedDrawings, - onChanged: (value) async { - await drawingProvider.toggleReceivedDrawings(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.grid_on, color: Colors.blue), - title: Text(AppLocalizations.of(context)!.cadastralParcels), - subtitle: const Text('WMS overlay'), - value: mapProvider.showCadastralOverlay, - onChanged: (value) async { - await mapProvider.toggleCadastralOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.route, color: Colors.green), - title: Text(AppLocalizations.of(context)!.forestRoads), - subtitle: const Text('WMS overlay'), - value: mapProvider.showForestRoadsOverlay, - onChanged: (value) async { - await mapProvider.toggleForestRoadsOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.hiking, color: Colors.brown), - title: Text(AppLocalizations.of(context)!.hikingTrails), - subtitle: const Text('WMS overlay'), - value: mapProvider.showHikingTrailsOverlay, - onChanged: (value) async { - await mapProvider.toggleHikingTrailsOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.alt_route, color: Colors.grey), - title: Text(AppLocalizations.of(context)!.mainRoads), - subtitle: const Text('WMS overlay'), - value: mapProvider.showMainRoadsOverlay, - onChanged: (value) async { - await mapProvider.toggleMainRoadsOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.numbers, color: Colors.purple), - title: Text(AppLocalizations.of(context)!.houseNumbers), - subtitle: const Text('WMS overlay'), - value: mapProvider.showHouseNumbersOverlay, - onChanged: (value) async { - await mapProvider.toggleHouseNumbersOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon( - Icons.warning_amber, - color: Colors.orange, - ), - title: Text(AppLocalizations.of(context)!.fireHazardZones), - subtitle: const Text('WMS overlay'), - value: mapProvider.showFireHazardZonesOverlay, - onChanged: (value) async { - await mapProvider.toggleFireHazardZonesOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon( - Icons.local_fire_department, - color: Colors.red, - ), - title: Text(AppLocalizations.of(context)!.historicalFires), - subtitle: const Text('WMS overlay'), - value: mapProvider.showHistoricalFiresOverlay, - onChanged: (value) async { - await mapProvider.toggleHistoricalFiresOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.forest, color: Colors.teal), - title: Text(AppLocalizations.of(context)!.firebreaks), - subtitle: const Text('WMS overlay'), - value: mapProvider.showFirebreaksOverlay, - onChanged: (value) async { - await mapProvider.toggleFirebreaksOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.warning, color: Colors.deepOrange), - title: Text(AppLocalizations.of(context)!.krasFireZones), - subtitle: const Text('WMS overlay'), - value: mapProvider.showKrasFireZonesOverlay, - onChanged: (value) async { - await mapProvider.toggleKrasFireZonesOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.place, color: Colors.indigo), - title: Text(AppLocalizations.of(context)!.placeNames), - subtitle: const Text('WMS overlay'), - value: mapProvider.showPlaceNamesOverlay, - onChanged: (value) async { - await mapProvider.togglePlaceNamesOverlay(); - }, - ), - ), - Consumer( - builder: (context, mapProvider, child) => SwitchListTile( - secondary: const Icon(Icons.border_outer, color: Colors.cyan), - title: Text(AppLocalizations.of(context)!.municipalityBorders), - subtitle: const Text('WMS overlay'), - value: mapProvider.showMunicipalityBordersOverlay, - onChanged: (value) async { - await mapProvider.toggleMunicipalityBordersOverlay(); - }, - ), - ), - ]), - _buildSectionHeader('Voice'), Consumer2( builder: (context, appProvider, connectionProvider, child) =>