pass suggestions

This commit is contained in:
davmar
2026-09-17 15:45:11 +02:00
parent bd3bc5357e
commit 22a535a6fd
2 changed files with 83 additions and 59 deletions
+71 -59
View File
@@ -2,6 +2,7 @@
library;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:provider/provider.dart';
@@ -46,6 +47,8 @@ class _LoginScreenState extends State<LoginScreen> {
email: _emailController.text,
password: _passwordController.text,
);
// Lets iOS/Android password managers offer to save / confirm the login.
TextInput.finishAutofillContext();
if (!mounted) return;
if (!widget.asRoot) {
Navigator.of(context).pop(true);
@@ -96,68 +99,77 @@ class _LoginScreenState extends State<LoginScreen> {
),
),
const SizedBox(height: 24),
Form(
key: _formKey,
child: Column(
children: [
AppTextField(
controller: _emailController,
label: 'Email',
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
autofocus: true,
validator: (value) {
final text = value?.trim() ?? '';
if (text.isEmpty) return 'Enter your email';
if (!text.contains('@')) return 'Enter a valid email';
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordController,
obscureText: _obscurePassword,
textInputAction: TextInputAction.done,
onFieldSubmitted: (_) => _submit(),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Enter your password';
}
return null;
},
decoration: InputDecoration(
labelText: 'Password',
suffixIcon: IconButton(
tooltip: _obscurePassword
? 'Show password'
: 'Hide password',
onPressed: () => setState(
() => _obscurePassword = !_obscurePassword,
),
icon: Icon(
_obscurePassword
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
AutofillGroup(
child: Form(
key: _formKey,
child: Column(
children: [
AppTextField(
controller: _emailController,
label: 'Email',
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
autofocus: true,
autofillHints: const [
AutofillHints.email,
AutofillHints.username,
],
validator: (value) {
final text = value?.trim() ?? '';
if (text.isEmpty) return 'Enter your email';
if (!text.contains('@')) return 'Enter a valid email';
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordController,
obscureText: _obscurePassword,
textInputAction: TextInputAction.done,
autofillHints: const [AutofillHints.password],
enableSuggestions: false,
autocorrect: false,
onFieldSubmitted: (_) => _submit(),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Enter your password';
}
return null;
},
decoration: InputDecoration(
labelText: 'Password',
suffixIcon: IconButton(
tooltip: _obscurePassword
? 'Show password'
: 'Hide password',
onPressed: () => setState(
() => _obscurePassword = !_obscurePassword,
),
icon: Icon(
_obscurePassword
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
),
),
),
),
),
const SizedBox(height: 24),
FilledButton.icon(
onPressed: _busy ? null : _submit,
icon: _busy
? SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(
strokeWidth: 2,
color: theme.colorScheme.onPrimary,
),
)
: const Icon(Icons.login),
label: Text(_busy ? 'Signing in…' : 'Sign in'),
),
],
const SizedBox(height: 24),
FilledButton.icon(
onPressed: _busy ? null : _submit,
icon: _busy
? SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(
strokeWidth: 2,
color: theme.colorScheme.onPrimary,
),
)
: const Icon(Icons.login),
label: Text(_busy ? 'Signing in…' : 'Sign in'),
),
],
),
),
),
],
+12
View File
@@ -14,6 +14,10 @@ class AppTextField extends StatelessWidget {
this.keyboardType,
this.validator,
this.autofocus = false,
this.autofillHints,
this.obscureText = false,
this.enableSuggestions,
this.autocorrect,
});
final TextEditingController controller;
@@ -24,6 +28,10 @@ class AppTextField extends StatelessWidget {
final TextInputType? keyboardType;
final String? Function(String?)? validator;
final bool autofocus;
final Iterable<String>? autofillHints;
final bool obscureText;
final bool? enableSuggestions;
final bool? autocorrect;
@override
Widget build(BuildContext context) {
@@ -31,8 +39,12 @@ class AppTextField extends StatelessWidget {
controller: controller,
maxLines: maxLines,
autofocus: autofocus,
obscureText: obscureText,
textInputAction: textInputAction,
keyboardType: keyboardType,
autofillHints: autofillHints,
enableSuggestions: enableSuggestions ?? !obscureText,
autocorrect: autocorrect ?? !obscureText,
validator: validator,
decoration: InputDecoration(
labelText: label,