mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-21 07:41:58 +00:00
Merge pull request #664 from NBA2K1/main
Improve Kitsu login dialog with autofill, input validation
This commit is contained in:
commit
9ac0f191d7
1 changed files with 139 additions and 110 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:isar_community/isar.dart';
|
||||
|
|
@ -81,9 +82,7 @@ class TrackScreen extends ConsumerWidget {
|
|||
entries: entries!,
|
||||
),
|
||||
TrackListile(
|
||||
onTap: () async {
|
||||
_showDialogLogin(context, ref);
|
||||
},
|
||||
onTap: () => _showDialogLogin(context, ref),
|
||||
id: TrackerProviders.kitsu.syncId,
|
||||
entries: entries,
|
||||
),
|
||||
|
|
@ -166,19 +165,54 @@ class TrackScreen extends ConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
void _showDialogLogin(BuildContext context, WidgetRef ref) {
|
||||
Future<void> _showDialogLogin(BuildContext context, WidgetRef ref) async {
|
||||
final passwordController = TextEditingController();
|
||||
final emailController = TextEditingController();
|
||||
String email = "";
|
||||
String password = "";
|
||||
final emailFocusNode = FocusNode();
|
||||
final passwordFocusNode = FocusNode();
|
||||
bool canLogin = false;
|
||||
String errorMessage = "";
|
||||
bool isLoading = false;
|
||||
bool obscureText = true;
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
showDialog(
|
||||
void updateCanLogin() {
|
||||
canLogin =
|
||||
emailController.text.trim().isNotEmpty &&
|
||||
passwordController.text.isNotEmpty;
|
||||
}
|
||||
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) => StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
void doLogin() async {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
errorMessage = "";
|
||||
});
|
||||
final email = emailController.text.trim();
|
||||
final password = passwordController.text;
|
||||
final res = await ref
|
||||
.read(
|
||||
kitsuProvider(
|
||||
syncId: TrackerProviders.kitsu.syncId,
|
||||
widgetRef: ref,
|
||||
).notifier,
|
||||
)
|
||||
.login(email, password);
|
||||
if (!res.$1) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
errorMessage = res.$2;
|
||||
});
|
||||
} else {
|
||||
TextInput.finishAutofillContext();
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
l10n.login_into("Kitsu"),
|
||||
|
|
@ -187,120 +221,115 @@ void _showDialogLogin(BuildContext context, WidgetRef ref) {
|
|||
content: SizedBox(
|
||||
height: 300,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextFormField(
|
||||
controller: emailController,
|
||||
autofocus: true,
|
||||
onChanged: (value) => setState(() {
|
||||
email = value;
|
||||
}),
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.email_adress,
|
||||
filled: false,
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(width: 0.4),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
borderSide: const BorderSide(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextFormField(
|
||||
controller: passwordController,
|
||||
obscureText: obscureText,
|
||||
onChanged: (value) => setState(() {
|
||||
password = value;
|
||||
}),
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.password,
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () => setState(() {
|
||||
obscureText = !obscureText;
|
||||
}),
|
||||
icon: Icon(
|
||||
obscureText
|
||||
? Icons.visibility_outlined
|
||||
: Icons.visibility_off_outlined,
|
||||
child: AutofillGroup(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextFormField(
|
||||
controller: emailController,
|
||||
focusNode: emailFocusNode,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
textInputAction: TextInputAction.next,
|
||||
autofillHints: const [
|
||||
AutofillHints.email,
|
||||
AutofillHints.username,
|
||||
],
|
||||
autofocus: true,
|
||||
onChanged: (_) => setState(updateCanLogin),
|
||||
onFieldSubmitted: (_) => passwordFocusNode.requestFocus(),
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.email_adress,
|
||||
filled: false,
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(width: 0.4),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
borderSide: const BorderSide(),
|
||||
),
|
||||
),
|
||||
filled: false,
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(width: 0.4),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
borderSide: const BorderSide(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextFormField(
|
||||
controller: passwordController,
|
||||
focusNode: passwordFocusNode,
|
||||
obscureText: obscureText,
|
||||
onChanged: (_) => setState(updateCanLogin),
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
textInputAction: TextInputAction.done,
|
||||
onFieldSubmitted: (_) {
|
||||
if (canLogin && !isLoading) doLogin();
|
||||
},
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.password,
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () => setState(() {
|
||||
obscureText = !obscureText;
|
||||
}),
|
||||
icon: Icon(
|
||||
obscureText
|
||||
? Icons.visibility_outlined
|
||||
: Icons.visibility_off_outlined,
|
||||
),
|
||||
),
|
||||
filled: false,
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(width: 0.4),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: const BorderSide(),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
borderSide: const BorderSide(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(errorMessage, style: const TextStyle(color: Colors.red)),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: SizedBox(
|
||||
width: context.width(1),
|
||||
height: 50,
|
||||
child: ElevatedButton(
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () async {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
final res = await ref
|
||||
.read(
|
||||
kitsuProvider(
|
||||
syncId: TrackerProviders.kitsu.syncId,
|
||||
widgetRef: ref,
|
||||
).notifier,
|
||||
)
|
||||
.login(email, password);
|
||||
if (!res.$1) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
errorMessage = res.$2;
|
||||
});
|
||||
} else {
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: isLoading
|
||||
? const CircularProgressIndicator()
|
||||
: Text(l10n.login),
|
||||
const SizedBox(height: 10),
|
||||
Text(errorMessage, style: const TextStyle(color: Colors.red)),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: SizedBox(
|
||||
width: context.width(1),
|
||||
height: 50,
|
||||
child: ElevatedButton(
|
||||
onPressed: (!canLogin || isLoading) ? null : doLogin,
|
||||
child: isLoading
|
||||
? const CircularProgressIndicator()
|
||||
: Text(l10n.login),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
emailController.dispose();
|
||||
passwordController.dispose();
|
||||
emailFocusNode.dispose();
|
||||
passwordFocusNode.dispose();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue