✨ Create account field validation
This commit is contained in:
parent
add904cc41
commit
45f61533ee
@ -84,8 +84,12 @@
|
||||
"fieldEmail": "Email address",
|
||||
"fieldPassword": "Password",
|
||||
"fieldDescription": "Description",
|
||||
"fieldUsernameAlphanumOnly": "Username can only contain alphanumeric characters.",
|
||||
"fieldUsernameLengthLimit": "Username must be between {} and {} characters.",
|
||||
"fieldUsernameCannotEditHint": "Username cannot be edited after created",
|
||||
"fieldUsernameLookupHint": "You can use username, phone number or email to login",
|
||||
"fieldNicknameLengthLimit": "Nickname must be between {} and {} characters.",
|
||||
"fieldEmailAddressMustBeValid": "Email address must be an email address.",
|
||||
"fieldFirstName": "First name",
|
||||
"fieldLastName": "Last name",
|
||||
"fieldBirthday": "Birthday",
|
||||
@ -408,5 +412,6 @@
|
||||
"accountDeletionSubmitted": "Account deletion request has been sent, you can check your inbox and follow the instructions in the email to complete the deletion operation.",
|
||||
"channelNewChannel": "New Channel",
|
||||
"channelNewDirectMessage": "New Direct Message",
|
||||
"channelDirectMessageDescription": "Direct Message with {}"
|
||||
"channelDirectMessageDescription": "Direct Message with {}",
|
||||
"fieldCannotBeEmpty": "This field cannot be empty."
|
||||
}
|
||||
|
@ -69,8 +69,12 @@
|
||||
"fieldNickname": "显示名",
|
||||
"fieldEmail": "电子邮箱地址",
|
||||
"fieldPassword": "密码",
|
||||
"fieldUsernameAlphanumOnly": "用户名只能包含英文大小写字母和数字。",
|
||||
"fieldUsernameLengthLimit": "用户名必须在 {} 和 {} 之间。",
|
||||
"fieldUsernameCannotEditHint": "用户名在创建后无法修改",
|
||||
"fieldUsernameLookupHint": "支持用户名、电话号码或邮箱地址",
|
||||
"fieldNicknameLengthLimit": "昵称必须在 {} 和 {} 之间。",
|
||||
"fieldEmailAddressMustBeValid": "电子邮箱地址必须是一个电子邮箱地址。",
|
||||
"fieldFirstName": "名",
|
||||
"fieldLastName": "姓",
|
||||
"fieldBirthday": "生日",
|
||||
@ -408,5 +412,6 @@
|
||||
"accountDeletionSubmitted": "帐户删除申请已发出,你可以检查你的收件箱并根据邮件内的指示完成删除操作。",
|
||||
"channelNewChannel": "新建频道",
|
||||
"channelNewDirectMessage": "发起私信",
|
||||
"channelDirectMessageDescription": "与 {} 的私聊"
|
||||
"channelDirectMessageDescription": "与 {} 的私聊",
|
||||
"fieldCannotBeEmpty": "此字段不能为空。"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:email_validator/email_validator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
@ -16,20 +17,21 @@ class RegisterScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RegisterScreenState extends State<RegisterScreen> {
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
|
||||
final _emailController = TextEditingController();
|
||||
final _usernameController = TextEditingController();
|
||||
final _nicknameController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
|
||||
void _performAction(BuildContext context) async {
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
|
||||
final email = _emailController.value.text;
|
||||
final username = _usernameController.value.text;
|
||||
final nickname = _nicknameController.value.text;
|
||||
final password = _passwordController.value.text;
|
||||
if (email.isEmpty ||
|
||||
username.isEmpty ||
|
||||
nickname.isEmpty ||
|
||||
password.isEmpty) {
|
||||
if (email.isEmpty || username.isEmpty || nickname.isEmpty || password.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -42,8 +44,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
||||
'password': password,
|
||||
});
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
if (!context.mounted) return;
|
||||
GoRouter.of(context).replaceNamed("authLogin");
|
||||
} catch (err) {
|
||||
context.showErrorDialog(err);
|
||||
@ -75,67 +76,96 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
).tr().padding(left: 4, bottom: 16),
|
||||
Column(
|
||||
children: [
|
||||
TextField(
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: _usernameController,
|
||||
autofillHints: const [AutofillHints.username],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldUsername'.tr(),
|
||||
Form(
|
||||
key: _formKey,
|
||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
validator: (value) {
|
||||
if (value == null || value.length < 4 || value.length > 32) {
|
||||
return 'fieldUsernameLengthLimit'.tr(args: [4.toString(), 32.toString()]);
|
||||
}
|
||||
if (!RegExp(r'^[a-zA-Z0-9_]+$').hasMatch(value)) {
|
||||
return 'fieldUsernameAlphanumOnly'.tr();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: _usernameController,
|
||||
autofillHints: const [AutofillHints.username],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldUsername'.tr(),
|
||||
),
|
||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
const Gap(12),
|
||||
TextField(
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: _nicknameController,
|
||||
autofillHints: const [AutofillHints.nickname],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldNickname'.tr(),
|
||||
const Gap(12),
|
||||
TextFormField(
|
||||
validator: (value) {
|
||||
if (value == null || value.length < 4 || value.length > 32) {
|
||||
return 'fieldNicknameLengthLimit'.tr(args: [4.toString(), 32.toString()]);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: _nicknameController,
|
||||
autofillHints: const [AutofillHints.nickname],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldNickname'.tr(),
|
||||
),
|
||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
const Gap(12),
|
||||
TextField(
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: _emailController,
|
||||
autofillHints: const [AutofillHints.email],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldEmail'.tr(),
|
||||
const Gap(12),
|
||||
TextFormField(
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'fieldCannotBeEmpty'.tr();
|
||||
}
|
||||
if (!EmailValidator.validate(value)) {
|
||||
return 'fieldEmailAddressMustBeValid'.tr();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
controller: _emailController,
|
||||
autofillHints: const [AutofillHints.email],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldEmail'.tr(),
|
||||
),
|
||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
const Gap(12),
|
||||
TextField(
|
||||
obscureText: true,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
controller: _passwordController,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldPassword'.tr(),
|
||||
const Gap(12),
|
||||
TextFormField(
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'fieldCannotBeEmpty'.tr();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
obscureText: true,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
controller: _passwordController,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const UnderlineInputBorder(),
|
||||
labelText: 'fieldPassword'.tr(),
|
||||
),
|
||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
onSubmitted: (_) => _performAction(context),
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 7),
|
||||
],
|
||||
).padding(horizontal: 7),
|
||||
),
|
||||
const Gap(16),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
|
@ -23,6 +23,7 @@ import pasteboard
|
||||
import path_provider_foundation
|
||||
import screen_brightness_macos
|
||||
import sentry_flutter
|
||||
import share_plus
|
||||
import shared_preferences_foundation
|
||||
import sqflite_darwin
|
||||
import url_launcher_macos
|
||||
@ -47,6 +48,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
|
||||
SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
|
24
pubspec.lock
24
pubspec.lock
@ -454,6 +454,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.2"
|
||||
email_validator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: email_validator
|
||||
sha256: b19aa5d92fdd76fbc65112060c94d45ba855105a28bb6e462de7ff03b12fa1fb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1538,6 +1546,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.10.1"
|
||||
share_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: share_plus
|
||||
sha256: "9c9bafd4060728d7cdb2464c341743adbd79d327cb067ec7afb64583540b47c8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.1.2"
|
||||
share_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus_platform_interface
|
||||
sha256: c57c0bbfec7142e3a0f55633be504b796af72e60e3c791b44d5a017b985f7a48
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -96,6 +96,8 @@ dependencies:
|
||||
sliver_tools: ^0.2.12
|
||||
bitsdojo_window: ^0.1.6
|
||||
gal: ^2.3.0
|
||||
share_plus: ^10.1.2
|
||||
email_validator: ^3.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <screen_brightness_windows/screen_brightness_windows_plugin.h>
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
@ -51,6 +52,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("ScreenBrightnessWindowsPlugin"));
|
||||
SentryFlutterPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SentryFlutterPlugin"));
|
||||
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
permission_handler_windows
|
||||
screen_brightness_windows
|
||||
sentry_flutter
|
||||
share_plus
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user