make login page use a Form

This commit is contained in:
Henry Hiles 2026-06-05 17:17:42 -04:00
commit a98afcff3d
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

View file

@ -17,11 +17,14 @@ class LoginPage extends HookConsumerWidget {
final password = useTextEditingController(); final password = useTextEditingController();
final inputError = useState<String?>(null); final inputError = useState<String?>(null);
final formKey = useRef(GlobalKey<FormState>());
Future<void> tryLogin() async { Future<void> tryLogin() async {
isLoading.value = true; isLoading.value = true;
try { try {
if (formKey.value.currentState?.validate() != true) return;
final error = await client.login( final error = await client.login(
.new( .new(
username: username.text, username: username.text,
@ -41,6 +44,9 @@ class LoginPage extends HookConsumerWidget {
} }
} }
String? requiredValidator(String? value) =>
value == null || value.isEmpty ? "This field is required" : null;
return Scaffold( return Scaffold(
appBar: Appbar( appBar: Appbar(
leading: IconButton( leading: IconButton(
@ -50,31 +56,36 @@ class LoginPage extends HookConsumerWidget {
), ),
body: AlertDialog( body: AlertDialog(
title: Text("Login to ${homeserver.host}"), title: Text("Login to ${homeserver.host}"),
content: Column( content: Form(
key: formKey.value,
child: Column(
mainAxisSize: .min, mainAxisSize: .min,
crossAxisAlignment: .start, crossAxisAlignment: .start,
children: [ children: [
TextField( TextFormField(
autofocus: true, autofocus: true,
textInputAction: .next, textInputAction: .next,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: requiredValidator,
decoration: .new(label: Text("Username")), decoration: .new(label: Text("Username")),
controller: username, controller: username,
), ),
SizedBox(height: 12), SizedBox(height: 12),
TextField( TextFormField(
textInputAction: .done, textInputAction: .done,
onSubmitted: (_) => tryLogin(),
selectAllOnFocus: true,
decoration: .new( decoration: .new(
label: Text("Password"), label: Text("Password"),
errorText: inputError.value, errorText: inputError.value,
errorMaxLines: 5, errorMaxLines: 5,
), ),
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: requiredValidator,
controller: password, controller: password,
obscureText: true, obscureText: true,
), ),
], ],
), ),
),
actions: [ actions: [
TextButton( TextButton(
onPressed: isLoading.value ? null : tryLogin, onPressed: isLoading.value ? null : tryLogin,