feat: Refactor code structure and optimize performance across multiple modules
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:app_links/app_links.dart';
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
|
||||
import 'package:krow/core/presentation/styles/theme.dart';
|
||||
import 'package:krow/core/presentation/widgets/scroll_layout_helper.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_app_bar.dart';
|
||||
import 'package:krow/features/profile/email_verification/domain/bloc/email_verification_bloc.dart';
|
||||
import 'package:krow/features/profile/email_verification/presentation/widgets/bottom_control_button.dart';
|
||||
import 'package:krow/features/profile/email_verification/presentation/widgets/verification_actions_widget.dart';
|
||||
|
||||
@RoutePage()
|
||||
class EmailVerificationScreen extends StatefulWidget
|
||||
implements AutoRouteWrapper {
|
||||
const EmailVerificationScreen({
|
||||
super.key,
|
||||
required this.verifiedEmail,
|
||||
required this.userPhone,
|
||||
});
|
||||
|
||||
final String verifiedEmail;
|
||||
final String userPhone;
|
||||
|
||||
@override
|
||||
State<EmailVerificationScreen> createState() =>
|
||||
_EmailVerificationScreenState();
|
||||
|
||||
@override
|
||||
Widget wrappedRoute(BuildContext context) {
|
||||
return BlocProvider<EmailVerificationBloc>(
|
||||
create: (context) => EmailVerificationBloc()
|
||||
..add(SetVerifiedData(
|
||||
verifiedEmail: verifiedEmail,
|
||||
userPhone: userPhone,
|
||||
)),
|
||||
child: this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _EmailVerificationScreenState extends State<EmailVerificationScreen> {
|
||||
StreamSubscription<Uri>? _appLinkSubscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final context = this.context;
|
||||
_appLinkSubscription = AppLinks().uriLinkStream.listen(
|
||||
(link) {
|
||||
if (!context.mounted) return;
|
||||
|
||||
context
|
||||
.read<EmailVerificationBloc>()
|
||||
.add(IncomingVerificationLink(verificationLink: link));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: KwAppBar(
|
||||
titleText: 'email_verification'.tr(),
|
||||
),
|
||||
body: ScrollLayoutHelper(
|
||||
padding: const EdgeInsets.all(16),
|
||||
upperWidget: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Gap(4),
|
||||
Text(
|
||||
'check_your_email'.tr(),
|
||||
style: AppTextStyles.headingH1,
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
const Gap(8),
|
||||
Text(
|
||||
'verification_link_sent'
|
||||
.tr(args: [widget.verifiedEmail]),
|
||||
style: AppTextStyles.bodyMediumReg.copyWith(
|
||||
color: AppColors.blackGray,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
const Gap(24),
|
||||
const VerificationActionsWidget(),
|
||||
],
|
||||
),
|
||||
lowerWidget: const BottomControlButton(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_appLinkSubscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow/core/application/routing/routes.gr.dart';
|
||||
import 'package:krow/core/data/enums/state_status.dart';
|
||||
import 'package:krow/core/presentation/gen/assets.gen.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/dialogs/kw_dialog.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_button.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_loading_overlay.dart';
|
||||
import 'package:krow/features/profile/email_verification/domain/bloc/email_verification_bloc.dart';
|
||||
|
||||
class BottomControlButton extends StatelessWidget {
|
||||
const BottomControlButton({super.key});
|
||||
|
||||
void _listenHandler(BuildContext context, EmailVerificationState state) {
|
||||
if (state.reAuthRequirement == ReAuthRequirement.none) return;
|
||||
|
||||
KwDialog.show(
|
||||
context: context,
|
||||
icon: Assets.images.icons.alertTriangle,
|
||||
state: KwDialogState.negative,
|
||||
barrierDismissible: false,
|
||||
title: 'additional_action_needed'.tr(),
|
||||
message: state.reAuthRequirement == ReAuthRequirement.recent
|
||||
? 'email_verification_security_sensitive'.tr(args: [state.userPhone])
|
||||
: 'unable_to_validate_email_status'.tr(),
|
||||
primaryButtonLabel: 'Continue'.tr(),
|
||||
onPrimaryButtonPressed: (dialogContext) async {
|
||||
final isReAuthenticated = await dialogContext.pushRoute<bool>(
|
||||
PhoneReLoginFlowRoute(userPhone: state.userPhone),
|
||||
);
|
||||
|
||||
if (dialogContext.mounted) Navigator.maybePop(dialogContext);
|
||||
|
||||
if (isReAuthenticated == true &&
|
||||
context.mounted &&
|
||||
state.reAuthRequirement == ReAuthRequirement.recent) {
|
||||
context
|
||||
.read<EmailVerificationBloc>()
|
||||
.add(const ResendVerificationEmail());
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocConsumer<EmailVerificationBloc, EmailVerificationState>(
|
||||
buildWhen: (previous, current) => previous.status != current.status,
|
||||
listenWhen: (previous, current) =>
|
||||
previous.reAuthRequirement != current.reAuthRequirement,
|
||||
listener: _listenHandler,
|
||||
builder: (context, state) {
|
||||
return KwLoadingOverlay(
|
||||
shouldShowLoading: state.status == StateStatus.loading,
|
||||
child: KwButton.primary(
|
||||
label: 'Continue'.tr(),
|
||||
disabled: state.status != StateStatus.success,
|
||||
onPressed: () {
|
||||
context.maybePop(true);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
|
||||
import 'package:krow/core/presentation/styles/theme.dart';
|
||||
import 'package:krow/features/profile/email_verification/domain/bloc/email_verification_bloc.dart';
|
||||
|
||||
class VerificationActionsWidget extends StatefulWidget {
|
||||
const VerificationActionsWidget({super.key});
|
||||
|
||||
@override
|
||||
State<VerificationActionsWidget> createState() =>
|
||||
_VerificationActionsWidgetState();
|
||||
}
|
||||
|
||||
//TODO: Finish this widget incorporating increasing timer on each code resend.
|
||||
class _VerificationActionsWidgetState extends State<VerificationActionsWidget> {
|
||||
double secondsToHold = 1;
|
||||
bool onHold = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenHeight = MediaQuery.sizeOf(context).height;
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: screenHeight / 4.6),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
text: 'didnt_receive'.tr(),
|
||||
style: AppTextStyles.bodyMediumReg
|
||||
.copyWith(color: AppColors.blackGray),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'resend'.tr(),
|
||||
style: AppTextStyles.bodyMediumSmb,
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
context
|
||||
.read<EmailVerificationBloc>()
|
||||
.add(const ResendVerificationEmail());
|
||||
},
|
||||
),
|
||||
TextSpan(
|
||||
text: ' ${'or'.tr()} ',
|
||||
style: AppTextStyles.bodyMediumReg
|
||||
.copyWith(color: AppColors.blackGray),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'contact_support_1'.tr(),
|
||||
style: AppTextStyles.bodyMediumSmb,
|
||||
recognizer: TapGestureRecognizer()..onTap = () {
|
||||
//TODO: Add Contact support action.
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user