fix: extract manual entry dialog into StatefulWidget
Fixes TextEditingController used after being disposed the controller was being manually disposed while the dialog's TextField still held a reference during the pop animation. Now the dialog is its own StatefulWidget so dispose() is called automatically by the framework at the right time.
This commit is contained in:
parent
024c05734b
commit
7635b0d85b
1 changed files with 51 additions and 30 deletions
|
|
@ -212,42 +212,63 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
|
||||
/// Fallback: let the user type the HW ID manually.
|
||||
Future<void> _showManualEntry(BuildContext context) async {
|
||||
final controller = TextEditingController();
|
||||
|
||||
final result = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
builder: (_) => const _ManualEntryDialog(),
|
||||
);
|
||||
|
||||
if (result != null && context.mounted) {
|
||||
Navigator.of(context).pop(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Manual Entry Dialog ───────────────────────────────────────────────
|
||||
class _ManualEntryDialog extends StatefulWidget {
|
||||
const _ManualEntryDialog();
|
||||
|
||||
@override
|
||||
State<_ManualEntryDialog> createState() => _ManualEntryDialogState();
|
||||
}
|
||||
|
||||
class _ManualEntryDialogState extends State<_ManualEntryDialog> {
|
||||
final _controller = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _submit() {
|
||||
final value = _controller.text.trim().toUpperCase();
|
||||
if (value.isNotEmpty) Navigator.of(context).pop(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Enter HW ID'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
controller: _controller,
|
||||
autofocus: true,
|
||||
textCapitalization: TextCapitalization.characters,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'e.g. JKF21',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onSubmitted: (_) => _submit(),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
final value = controller.text.trim().toUpperCase();
|
||||
if (value.isNotEmpty) Navigator.of(ctx).pop(value);
|
||||
},
|
||||
onPressed: _submit,
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (result != null && context.mounted) {
|
||||
controller.dispose();
|
||||
Navigator.of(context).pop(result);
|
||||
} else {
|
||||
controller.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue