TF-518 Handle missing field in login form
This commit is contained in:
committed by
Dat H. Pham
parent
3fc2ae4776
commit
15cc421525
@@ -55,6 +55,6 @@ class ResponsiveUtils {
|
|||||||
double getWidthLoginButton() => _loginButtonWidth;
|
double getWidthLoginButton() => _loginButtonWidth;
|
||||||
|
|
||||||
bool isHeightShortest(BuildContext context) {
|
bool isHeightShortest(BuildContext context) {
|
||||||
return MediaQuery.of(context).size.shortestSide < 600;
|
return MediaQuery.of(context).size.shortestSide < heightShortest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,6 @@ import 'package:core/presentation/views/text/text_field_builder.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/state/authentication_user_state.dart';
|
|
||||||
import 'package:tmail_ui_user/features/login/presentation/login_controller.dart';
|
import 'package:tmail_ui_user/features/login/presentation/login_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart';
|
import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart';
|
||||||
import 'package:tmail_ui_user/features/login/presentation/state/login_state.dart';
|
import 'package:tmail_ui_user/features/login/presentation/state/login_state.dart';
|
||||||
@@ -29,9 +28,17 @@ abstract class BaseLoginView extends GetWidget<LoginController> {
|
|||||||
child: CenterTextBuilder()
|
child: CenterTextBuilder()
|
||||||
.key(const Key('login_message'))
|
.key(const Key('login_message'))
|
||||||
.text(loginState.viewState.fold(
|
.text(loginState.viewState.fold(
|
||||||
(failure) => failure is AuthenticationUserFailure
|
(failure) {
|
||||||
? AppLocalizations.of(context).unknown_error_login_message
|
if (failure is LoginMissUrlAction) {
|
||||||
: AppLocalizations.of(context).loginInputUrlMessage,
|
return AppLocalizations.of(context).requiredUrl;
|
||||||
|
} else if (failure is LoginMissUsernameAction) {
|
||||||
|
return AppLocalizations.of(context).requiredEmail;
|
||||||
|
} else if (failure is LoginMissPasswordAction) {
|
||||||
|
return AppLocalizations.of(context).requiredPassword;
|
||||||
|
} else {
|
||||||
|
return AppLocalizations.of(context).unknown_error_login_message;
|
||||||
|
}
|
||||||
|
},
|
||||||
(success) {
|
(success) {
|
||||||
if (loginController.loginFormType.value == LoginFormType.credentialForm || kIsWeb) {
|
if (loginController.loginFormType.value == LoginFormType.credentialForm || kIsWeb) {
|
||||||
return AppLocalizations.of(context).loginInputCredentialMessage;
|
return AppLocalizations.of(context).loginInputCredentialMessage;
|
||||||
@@ -42,9 +49,7 @@ abstract class BaseLoginView extends GetWidget<LoginController> {
|
|||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: loginState.viewState.fold(
|
color: loginState.viewState.fold(
|
||||||
(failure) => failure is AuthenticationUserFailure
|
(failure) => AppColor.textFieldErrorBorderColor,
|
||||||
? AppColor.textFieldErrorBorderColor
|
|
||||||
: AppColor.colorNameEmail,
|
|
||||||
(success) => AppColor.colorNameEmail)))
|
(success) => AppColor.colorNameEmail)))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -65,8 +65,12 @@ class LoginController extends GetxController {
|
|||||||
final password = _parsePassword(_passwordText);
|
final password = _parsePassword(_passwordText);
|
||||||
if (baseUri != null && userName != null && password != null) {
|
if (baseUri != null && userName != null && password != null) {
|
||||||
_loginAction(baseUri, userName, password);
|
_loginAction(baseUri, userName, password);
|
||||||
} else {
|
} else if (baseUri == null) {
|
||||||
loginState.value = LoginState(Left(LoginMissPropertiesAction()));
|
loginState.value = LoginState(Left(LoginMissUrlAction()));
|
||||||
|
} else if (userName == null) {
|
||||||
|
loginState.value = LoginState(Left(LoginMissUsernameAction()));
|
||||||
|
} else if (password == null) {
|
||||||
|
loginState.value = LoginState(Left(LoginMissPasswordAction()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ class LoginView extends BaseLoginView {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: true,
|
|
||||||
backgroundColor: AppColor.primaryLightColor,
|
backgroundColor: AppColor.primaryLightColor,
|
||||||
body: GestureDetector(
|
body: GestureDetector(
|
||||||
onTap: () => FocusScope.of(context).unfocus(),
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
|
|||||||
@@ -100,32 +100,32 @@ class LoginView extends BaseLoginView {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 16),
|
padding: const EdgeInsets.only(top: 16),
|
||||||
child: (SloganBuilder(arrangedByHorizontal: true, )
|
child: (SloganBuilder(arrangedByHorizontal: true, )
|
||||||
..setLogoSVG(imagePaths.icEncrypted)
|
..setLogoSVG(imagePaths.icEncrypted)
|
||||||
..setSizeLogo(48.0)
|
..setSizeLogo(48.0)
|
||||||
..setPadding(const EdgeInsets.only(left: 12))
|
..setPadding(const EdgeInsets.only(left: 12))
|
||||||
..setSloganText(AppLocalizations.of(context).encryptedMailbox)
|
..setSloganText(AppLocalizations.of(context).encryptedMailbox)
|
||||||
..setSloganTextStyle(const TextStyle(fontSize: 24, fontWeight: FontWeight.w400, color: AppColor.colorNameEmail)))
|
..setSloganTextStyle(const TextStyle(fontSize: 24, fontWeight: FontWeight.w400, color: AppColor.colorNameEmail)))
|
||||||
.build()
|
.build()
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 16),
|
padding: const EdgeInsets.only(top: 16),
|
||||||
child: (SloganBuilder(arrangedByHorizontal: true, )
|
child: (SloganBuilder(arrangedByHorizontal: true, )
|
||||||
..setLogoSVG(imagePaths.icTeam)
|
..setLogoSVG(imagePaths.icTeam)
|
||||||
..setSizeLogo(48.0)
|
..setSizeLogo(48.0)
|
||||||
..setPadding(const EdgeInsets.only(left: 12))
|
..setPadding(const EdgeInsets.only(left: 12))
|
||||||
..setSloganText(AppLocalizations.of(context).manageEmailAsATeam)
|
..setSloganText(AppLocalizations.of(context).manageEmailAsATeam)
|
||||||
..setSloganTextStyle(const TextStyle(fontSize: 24, fontWeight: FontWeight.w400, color: AppColor.colorNameEmail)))
|
..setSloganTextStyle(const TextStyle(fontSize: 24, fontWeight: FontWeight.w400, color: AppColor.colorNameEmail)))
|
||||||
.build()
|
.build()
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 16),
|
padding: const EdgeInsets.only(top: 16),
|
||||||
child: (SloganBuilder(arrangedByHorizontal: true, )
|
child: (SloganBuilder(arrangedByHorizontal: true, )
|
||||||
..setLogoSVG(imagePaths.icIntegration)
|
..setLogoSVG(imagePaths.icIntegration)
|
||||||
..setSizeLogo(48.0)
|
..setSizeLogo(48.0)
|
||||||
..setPadding(const EdgeInsets.only(left: 12))
|
..setPadding(const EdgeInsets.only(left: 12))
|
||||||
..setSloganText(AppLocalizations.of(context).multipleIntegrations)
|
..setSloganText(AppLocalizations.of(context).multipleIntegrations)
|
||||||
..setSloganTextStyle(const TextStyle(fontSize: 24, fontWeight: FontWeight.w400, color: AppColor.colorNameEmail)))
|
..setSloganTextStyle(const TextStyle(fontSize: 24, fontWeight: FontWeight.w400, color: AppColor.colorNameEmail)))
|
||||||
.build()
|
.build()
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 44),
|
padding: const EdgeInsets.only(top: 44),
|
||||||
|
|||||||
@@ -26,7 +26,19 @@ class LoginInitAction extends ViewState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class LoginMissPropertiesAction extends Failure {
|
class LoginMissUrlAction extends Failure {
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class LoginMissUsernameAction extends Failure {
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class LoginMissPasswordAction extends Failure {
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [];
|
List<Object?> get props => [];
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,3 @@
|
|||||||
// LinShare is an open source filesharing software, part of the LinPKI software
|
|
||||||
// suite, developed by Linagora.
|
|
||||||
//
|
|
||||||
// Copyright (C) 2020 LINAGORA
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
// terms of the GNU Affero General Public License as published by the Free Software
|
|
||||||
// Foundation, either version 3 of the License, or (at your option) any later version,
|
|
||||||
// provided you comply with the Additional Terms applicable for LinShare software by
|
|
||||||
// Linagora pursuant to Section 7 of the GNU Affero General Public License,
|
|
||||||
// subsections (b), (c), and (e), pursuant to which you must notably (i) retain the
|
|
||||||
// display in the interface of the “LinShare™” trademark/logo, the "Libre & Free" mention,
|
|
||||||
// the words “You are using the Free and Open Source version of LinShare™, powered by
|
|
||||||
// Linagora © 2009–2020. Contribute to Linshare R&D by subscribing to an Enterprise
|
|
||||||
// offer!”. You must also retain the latter notice in all asynchronous messages such as
|
|
||||||
// e-mails sent with the Program, (ii) retain all hypertext links between LinShare and
|
|
||||||
// http://www.linshare.org, between linagora.com and Linagora, and (iii) refrain from
|
|
||||||
// infringing Linagora intellectual property rights over its trademarks and commercial
|
|
||||||
// brands. Other Additional Terms apply, see
|
|
||||||
// <http://www.linshare.org/licenses/LinShare-License_AfferoGPL-v3.pdf
|
|
||||||
//
|
|
||||||
// for more details.
|
|
||||||
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
|
||||||
// more details.
|
|
||||||
// You should have received a copy of the GNU Affero General Public License and its
|
|
||||||
// applicable Additional Terms for LinShare along with this program. If not, see
|
|
||||||
// <http://www.gnu.org/licenses
|
|
||||||
// for the GNU Affero General Public License version
|
|
||||||
//
|
|
||||||
// 3 and <http://www.linshare.org/licenses/LinShare-License_AfferoGPL-v3.pdf
|
|
||||||
// for
|
|
||||||
//
|
|
||||||
// the Additional Terms applicable to LinShare software.
|
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
|
|||||||
@@ -66,6 +66,21 @@ class AppLocalizations {
|
|||||||
name: 'signIn');
|
name: 'signIn');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get requiredEmail {
|
||||||
|
return Intl.message('Email is required',
|
||||||
|
name: 'requiredEmail');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get requiredPassword {
|
||||||
|
return Intl.message('Password is required',
|
||||||
|
name: 'requiredPassword');
|
||||||
|
}
|
||||||
|
|
||||||
|
String get requiredUrl {
|
||||||
|
return Intl.message('Server address is required',
|
||||||
|
name: 'requiredUrl');
|
||||||
|
}
|
||||||
|
|
||||||
String get jmapBasedMailSolution {
|
String get jmapBasedMailSolution {
|
||||||
return Intl.message('JMAP-based\ncollaborative team mail solution',
|
return Intl.message('JMAP-based\ncollaborative team mail solution',
|
||||||
name: 'jmapBasedMailSolution');
|
name: 'jmapBasedMailSolution');
|
||||||
|
|||||||
Reference in New Issue
Block a user