TF-2271 Implement dns lookup to get jmap url

Signed-off-by: dab246 <tdvu@linagora.com>
(cherry picked from commit 7b0c0015a15a243b6b4aef3d78e7653d556ad109)
This commit is contained in:
dab246
2023-11-10 17:06:50 +07:00
committed by Dat Vu
parent c0bef69435
commit 9b661b0688
33 changed files with 773 additions and 483 deletions
@@ -0,0 +1,57 @@
import 'package:core/presentation/views/text/type_ahead_form_field_builder.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:tmail_ui_user/features/base/widget/recent_item_tile_widget.dart';
import 'package:tmail_ui_user/features/login/domain/model/recent_login_username.dart';
import 'package:tmail_ui_user/features/login/presentation/widgets/login_input_decoration_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class DNSLookupInputForm extends StatelessWidget {
final TextEditingController textEditingController;
final ValueChanged<String> onTextChange;
final ValueChanged<String> onTextSubmitted;
final SuggestionsCallback<RecentLoginUsername> suggestionsCallback;
final SuggestionSelectionCallback<RecentLoginUsername> onSuggestionSelected;
const DNSLookupInputForm({
super.key,
required this.textEditingController,
required this.onTextChange,
required this.onTextSubmitted,
required this.suggestionsCallback,
required this.onSuggestionSelected
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.only(bottom: 16, start: 24, end: 24),
child: TypeAheadFormFieldBuilder<RecentLoginUsername>(
controller: textEditingController,
onTextChange: onTextChange,
onTextSubmitted: onTextSubmitted,
textInputAction: TextInputAction.next,
autocorrect: false,
autofillHints: const [AutofillHints.email],
keyboardType: TextInputType.emailAddress,
decoration: (LoginInputDecorationBuilder()
..setLabelText(AppLocalizations.of(context).email)
..setHintText(AppLocalizations.of(context).email)
).build(),
debounceDuration: const Duration(milliseconds: 300),
suggestionsCallback: suggestionsCallback,
itemBuilder: (_, loginUsername) => RecentItemTileWidget(loginUsername),
onSuggestionSelected: onSuggestionSelected,
suggestionsBoxDecoration: const SuggestionsBoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(14))
),
noItemsFoundBuilder: (context) => const SizedBox(),
hideOnEmpty: true,
hideOnError: true,
hideOnLoading: true,
),
);
}
}
@@ -0,0 +1,30 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class HorizontalProgressLoadingButton extends StatelessWidget {
const HorizontalProgressLoadingButton({super.key});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsetsDirectional.only(bottom: 16, start: 24, end: 24),
width: context.width,
height: 48,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.primaryColor,
disabledBackgroundColor: AppColor.primaryColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
)
),
onPressed: null,
child: const LinearProgressIndicator(
color: Colors.white,
backgroundColor: AppColor.primaryColor
)
)
);
}
}
@@ -0,0 +1,30 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
class LoginBackButton extends StatelessWidget {
final _imagePath = Get.find<ImagePaths>();
final VoidCallback onBackAction;
LoginBackButton({super.key, required this.onBackAction});
@override
Widget build(BuildContext context) {
return PositionedDirectional(
start: 12,
top: 12,
child: IconButton(
onPressed: onBackAction,
icon: SvgPicture.asset(
_imagePath.icBack,
alignment: Alignment.center,
colorFilter: AppColor.primaryColor.asFilter()
)
),
);
}
}
@@ -0,0 +1,83 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/login/domain/state/dns_lookup_to_get_jmap_url_state.dart';
import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration_state.dart';
import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/utils/message_toast_utils.dart';
class LoginMessageWidget extends StatelessWidget {
static const double _loginTextFieldWidthSmallScreen = 280.0;
static const double _loginTextFieldWidthLargeScreen = 320.0;
final LoginFormType formType;
final Either<Failure, Success> viewState;
const LoginMessageWidget({
super.key,
required this.formType,
required this.viewState
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.only(
top: 11,
bottom: 36,
start: 58,
end: 58
),
child: SizedBox(
width: context.width < ResponsiveUtils.minTabletWidth
? _loginTextFieldWidthSmallScreen
: _loginTextFieldWidthLargeScreen,
child: Text(
viewState.fold(
(failure) {
if (failure is GetOIDCConfigurationFailure) {
return AppLocalizations.of(context).canNotVerifySSOConfiguration;
} else if (failure is DNSLookupToGetJmapUrlFailure) {
return AppLocalizations.of(context).dnsLookupLoginMessage;
} else if (failure is FeatureFailure) {
final errorMessage = MessageToastUtils.getMessageByException(context, failure.exception);
return errorMessage ?? AppLocalizations.of(context).unknownError;
} else {
return AppLocalizations.of(context).unknownError;
}
},
(success) {
if (formType == LoginFormType.credentialForm) {
return AppLocalizations.of(context).loginInputCredentialMessage;
} else if (formType == LoginFormType.dnsLookupForm) {
return AppLocalizations.of(context).dnsLookupLoginMessage;
} else if (formType == LoginFormType.passwordForm) {
return AppLocalizations.of(context).enterYourPasswordToSignIn;
} else if (formType == LoginFormType.baseUrlForm) {
return AppLocalizations.of(context).loginInputUrlMessage;
} else {
return '';
}
}
),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400,
color: viewState.fold(
(failure) => AppColor.textFieldErrorBorderColor,
(success) => AppColor.colorNameEmail
)
),
)
)
);
}
}
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/features/login/presentation/widgets/login_text_input_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class PasswordInputForm extends StatelessWidget {
final TextEditingController textEditingController;
final FocusNode focusNode;
final ValueChanged<String> onTextChange;
final ValueChanged<String> onTextSubmitted;
const PasswordInputForm({
super.key,
required this.textEditingController,
required this.focusNode,
required this.onTextChange,
required this.onTextSubmitted
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.only(bottom: 16, start: 24, end: 24),
child: LoginTextInputBuilder(
controller: textEditingController,
autofillHints: const [AutofillHints.password],
textInputAction: TextInputAction.done,
hintText: AppLocalizations.of(context).password,
focusNode: focusNode,
onTextChange: onTextChange,
onSubmitted: onTextSubmitted,
),
);
}
}