102 lines
2.3 KiB
Dart
102 lines
2.3 KiB
Dart
/// Name prompt that owns its text controller for the dialog lifetime.
|
|
library;
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
Future<String?> showNameDialog(
|
|
BuildContext context, {
|
|
required String title,
|
|
String? initial,
|
|
String label = 'Name',
|
|
String confirmLabel = 'Save',
|
|
}) {
|
|
return showDialog<String>(
|
|
context: context,
|
|
builder: (context) => _NameDialog(
|
|
title: title,
|
|
initial: initial ?? '',
|
|
label: label,
|
|
confirmLabel: confirmLabel,
|
|
),
|
|
);
|
|
}
|
|
|
|
class _NameDialog extends StatefulWidget {
|
|
const _NameDialog({
|
|
required this.title,
|
|
required this.initial,
|
|
required this.label,
|
|
required this.confirmLabel,
|
|
});
|
|
|
|
final String title;
|
|
final String initial;
|
|
final String label;
|
|
final String confirmLabel;
|
|
|
|
@override
|
|
State<_NameDialog> createState() => _NameDialogState();
|
|
}
|
|
|
|
class _NameDialogState extends State<_NameDialog> {
|
|
late final TextEditingController _controller;
|
|
String? _error;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = TextEditingController(text: widget.initial);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _save() {
|
|
final name = _controller.text.trim();
|
|
if (name.isEmpty) {
|
|
setState(() => _error = 'Enter a name.');
|
|
return;
|
|
}
|
|
Navigator.of(context).pop(name);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AlertDialog(
|
|
title: Text(widget.title),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
TextField(
|
|
controller: _controller,
|
|
autofocus: true,
|
|
textCapitalization: TextCapitalization.sentences,
|
|
decoration: InputDecoration(labelText: widget.label),
|
|
onSubmitted: (_) => _save(),
|
|
),
|
|
if (_error != null) ...[
|
|
const SizedBox(height: 8),
|
|
Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
_error!,
|
|
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
child: const Text('Cancel'),
|
|
),
|
|
TextButton(onPressed: _save, child: Text(widget.confirmLabel)),
|
|
],
|
|
);
|
|
}
|
|
}
|