make verify page use a form

This commit is contained in:
Henry Hiles 2026-06-05 17:23:09 -04:00
commit 91dde7b684
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
3 changed files with 40 additions and 52 deletions

View file

@ -0,0 +1,2 @@
String? requiredValidator(String? value) =>
value == null || value.isEmpty ? "This field is required" : null;

View file

@ -3,6 +3,7 @@ import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/client_controller.dart";
import "package:nexus/widgets/appbar.dart";
import "package:nexus/helpers/required_validator_helper.dart";
class LoginPage extends HookConsumerWidget {
final Uri homeserver;
@ -44,9 +45,6 @@ class LoginPage extends HookConsumerWidget {
}
}
String? requiredValidator(String? value) =>
value == null || value.isEmpty ? "This field is required" : null;
return Scaffold(
appBar: Appbar(
leading: IconButton(
@ -65,7 +63,7 @@ class LoginPage extends HookConsumerWidget {
TextFormField(
autofocus: true,
textInputAction: .next,
autovalidateMode: AutovalidateMode.onUserInteraction,
autovalidateMode: .onUserInteraction,
validator: requiredValidator,
decoration: .new(label: Text("Username")),
controller: username,
@ -78,7 +76,7 @@ class LoginPage extends HookConsumerWidget {
errorText: inputError.value,
errorMaxLines: 5,
),
autovalidateMode: AutovalidateMode.onUserInteraction,
autovalidateMode: .onUserInteraction,
validator: requiredValidator,
controller: password,
obscureText: true,

View file

@ -3,6 +3,7 @@ import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/client_controller.dart";
import "package:nexus/widgets/appbar.dart";
import "package:nexus/helpers/required_validator_helper.dart";
class VerifyPage extends HookConsumerWidget {
const VerifyPage({super.key});
@ -11,68 +12,55 @@ class VerifyPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final passphraseController = useTextEditingController();
final isLoading = useState(false);
final inputError = useState<String?>(null);
final formKey = useRef(GlobalKey<FormState>());
return Scaffold(
appBar: Appbar(),
body: AlertDialog(
title: Text("Verify"),
content: Column(
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
Text(
"Enter your recovery key or passphrase below to unlock encrypted events.\nYour passphrase is usually not the same as your password.",
),
SizedBox(height: 12),
TextField(
autofocus: true,
controller: passphraseController,
obscureText: true,
decoration: .new(label: Text("Recovery Key or Passphrase")),
),
],
content: Form(
key: formKey.value,
child: Column(
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
Text(
"Enter your recovery key or passphrase below to unlock encrypted events.\nYour passphrase is usually not the same as your password.",
),
SizedBox(height: 12),
TextFormField(
autofocus: true,
controller: passphraseController,
textInputAction: .done,
autovalidateMode: .onUserInteraction,
validator: requiredValidator,
obscureText: true,
decoration: .new(
label: Text("Recovery Key or Passphrase"),
errorText: inputError.value,
),
),
],
),
),
actions: [
TextButton(
onPressed: isLoading.value
? null
: () async {
final scaffoldMessenger = ScaffoldMessenger.of(context);
final snackbar = scaffoldMessenger.showSnackBar(
.new(
content: Text(
"Attempting to verify with recovery key...",
),
duration: .new(days: 999),
),
);
isLoading.value = true;
final error = await ref
.watch(ClientController.provider.notifier)
.verify(passphraseController.text);
snackbar.close();
if (error != null) {
isLoading.value = false;
if (context.mounted) {
scaffoldMessenger.showSnackBar(
.new(
backgroundColor: Theme.of(
context,
).colorScheme.errorContainer,
content: Text(
"Verification failed. Is your passphrase correct?\nError: $error",
style: .new(
color: Theme.of(
context,
).colorScheme.onErrorContainer,
),
),
),
);
try {
if (formKey.value.currentState?.validate() != true) {
return;
}
inputError.value = await ref
.watch(ClientController.provider.notifier)
.verify(passphraseController.text);
} finally {
isLoading.value = false;
}
},
child: Text("Verify"),