feat(#18): inline Radio Settings form into its pane

Bring radio config up a level: render the form directly in the Radio Settings pane with a full-width Save button, instead of a tile that opens a dialog. _RadioSettingsDialog -> _RadioSettingsForm; build returns an inline Column of the (verbatim) fields + Save; _saveSettings drops the Navigator.pop (no dialog), which also resolves the unguarded-pop-after-await finding. Removed _showRadioSettings. Field widgets, controllers, preset matching, and off-grid snapshot logic unchanged.

Key the form on the device's current radio values (freq/bw/sf/cr/txpower/clientRepeat) so a device-reported change re-seeds it -- the dialog got this for free by reopening; the persistent inline form needs the key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pull/36/head
Strycher 1 month ago
parent eb2888162e
commit 413e47563e

@ -138,21 +138,33 @@ class _SettingsScreenState extends State<SettingsScreen> {
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
children: [ children: [
Card( Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ListTile( Text(
leading: const Icon(Icons.radio), l10n.settings_radioSettings,
title: Text(l10n.settings_radioSettings), style: const TextStyle(
subtitle: Text(l10n.settings_radioSettingsSubtitle), fontSize: 18,
trailing: const Icon(Icons.chevron_right), fontWeight: FontWeight.bold,
onTap: () => _showRadioSettings(context, connector), ),
),
const SizedBox(height: 8),
_RadioSettingsForm(
key: ValueKey(
'${connector.currentFreqHz}-${connector.currentBwHz}-'
'${connector.currentSf}-${connector.currentCr}-'
'${connector.currentTxPower}-${connector.clientRepeat}',
),
connector: connector,
), ),
const Divider(height: 1),
_PathHashSizeTile(connector: connector),
], ],
), ),
), ),
),
const SizedBox(height: 16),
Card(child: _PathHashSizeTile(connector: connector)),
], ],
); );
} }
@ -663,13 +675,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
); );
} }
void _showRadioSettings(BuildContext context, MeshCoreConnector connector) {
showDialog(
context: context,
builder: (context) => _RadioSettingsDialog(connector: connector),
);
}
void _editLocation(BuildContext context, MeshCoreConnector connector) { void _editLocation(BuildContext context, MeshCoreConnector connector) {
final l10n = context.l10n; final l10n = context.l10n;
final latController = TextEditingController(); final latController = TextEditingController();
@ -1367,16 +1372,16 @@ class _AutoAddSectionState extends State<_AutoAddSection> {
} }
} }
class _RadioSettingsDialog extends StatefulWidget { class _RadioSettingsForm extends StatefulWidget {
final MeshCoreConnector connector; final MeshCoreConnector connector;
const _RadioSettingsDialog({required this.connector}); const _RadioSettingsForm({super.key, required this.connector});
@override @override
State<_RadioSettingsDialog> createState() => _RadioSettingsDialogState(); State<_RadioSettingsForm> createState() => _RadioSettingsFormState();
} }
class _RadioSettingsDialogState extends State<_RadioSettingsDialog> { class _RadioSettingsFormState extends State<_RadioSettingsForm> {
final _frequencyController = TextEditingController(); final _frequencyController = TextEditingController();
LoRaBandwidth _bandwidth = LoRaBandwidth.bw125; LoRaBandwidth _bandwidth = LoRaBandwidth.bw125;
LoRaSpreadingFactor _spreadingFactor = LoRaSpreadingFactor.sf7; LoRaSpreadingFactor _spreadingFactor = LoRaSpreadingFactor.sf7;
@ -1763,7 +1768,6 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
content: Text(l10n.settings_error(e.toString())), content: Text(l10n.settings_error(e.toString())),
); );
} }
Navigator.pop(context);
} }
String _presetLabel(int? index) { String _presetLabel(int? index) {
@ -1803,10 +1807,7 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final l10n = context.l10n; final l10n = context.l10n;
return AlertDialog( return Column(
title: Text(l10n.settings_radioSettings),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -1839,9 +1840,7 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
helperText: l10n.settings_frequencyHelper, helperText: l10n.settings_frequencyHelper,
), ),
keyboardType: const TextInputType.numberWithOptions( keyboardType: const TextInputType.numberWithOptions(decimal: true),
decimal: true,
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
DropdownButtonFormField<LoRaBandwidth>( DropdownButtonFormField<LoRaBandwidth>(
@ -1851,9 +1850,7 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
), ),
items: LoRaBandwidth.values items: LoRaBandwidth.values
.map( .map((bw) => DropdownMenuItem(value: bw, child: Text(bw.label)))
(bw) => DropdownMenuItem(value: bw, child: Text(bw.label)),
)
.toList(), .toList(),
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
@ -1873,9 +1870,7 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
), ),
items: LoRaSpreadingFactor.values items: LoRaSpreadingFactor.values
.map( .map((sf) => DropdownMenuItem(value: sf, child: Text(sf.label)))
(sf) => DropdownMenuItem(value: sf, child: Text(sf.label)),
)
.toList(), .toList(),
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
@ -1883,9 +1878,7 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
_spreadingFactor = value; _spreadingFactor = value;
_syncPresetSelection(); _syncPresetSelection();
}); });
_logRadioSettingsState( _logRadioSettingsState('Manual settings edit: spreading factor');
'Manual settings edit: spreading factor',
);
} }
}, },
), ),
@ -1897,9 +1890,7 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
), ),
items: LoRaCodingRate.values items: LoRaCodingRate.values
.map( .map((cr) => DropdownMenuItem(value: cr, child: Text(cr.label)))
(cr) => DropdownMenuItem(value: cr, child: Text(cr.label)),
)
.toList(), .toList(),
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
@ -1934,15 +1925,15 @@ class _RadioSettingsDialogState extends State<_RadioSettingsDialog> {
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
), ),
], ],
], const SizedBox(height: 16),
), SizedBox(
width: double.infinity,
child: FilledButton.icon(
onPressed: _saveSettings,
icon: const Icon(Icons.save_outlined),
label: Text(l10n.common_save),
), ),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(l10n.common_cancel),
), ),
FilledButton(onPressed: _saveSettings, child: Text(l10n.common_save)),
], ],
); );
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.