From 47c8becbb5420b321a2771e7d3b452e1609947e3 Mon Sep 17 00:00:00 2001 From: katendejericho <106674175+katendejericho5@users.noreply.github.com> Date: Thu, 9 May 2024 10:56:23 +0300 Subject: [PATCH 1/2] initial --- .../email_verification_screen.dart | 88 +---- .../email_link/confirm_account_details.dart | 311 ----------------- .../screens/email_link/email_link_page.dart | 185 ---------- .../email_link/email_link_widgets.dart | 330 ------------------ .../email_link/link_verification_screen.dart | 313 ----------------- mobile/lib/screens/home_page.dart | 20 +- .../screens/profile/profile_edit_page.dart | 73 +--- mobile/lib/screens/profile/profile_view.dart | 22 +- .../lib/screens/profile/profile_widgets.dart | 280 ++------------- 9 files changed, 49 insertions(+), 1573 deletions(-) delete mode 100644 mobile/lib/screens/email_link/confirm_account_details.dart delete mode 100644 mobile/lib/screens/email_link/email_link_page.dart delete mode 100644 mobile/lib/screens/email_link/email_link_widgets.dart delete mode 100644 mobile/lib/screens/email_link/link_verification_screen.dart diff --git a/mobile/lib/screens/email_authentication/email_verification_screen.dart b/mobile/lib/screens/email_authentication/email_verification_screen.dart index 87e0335eaa..0dc2c66b15 100644 --- a/mobile/lib/screens/email_authentication/email_verification_screen.dart +++ b/mobile/lib/screens/email_authentication/email_verification_screen.dart @@ -1,5 +1,3 @@ -// ignore_for_file: use_build_context_synchronously - import 'package:app/blocs/blocs.dart'; import 'package:app/models/enum_constants.dart'; import 'package:app/screens/email_authentication/email_auth_widgets.dart'; @@ -8,7 +6,6 @@ import 'package:app/themes/theme.dart'; import 'package:app/utils/utils.dart'; import 'package:app/widgets/widgets.dart'; import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -211,39 +208,6 @@ class _EmailAuthVerificationWidgetState ); } - Future linkAccounts() async { - final emailAuthModel = - context.read().state.emailAuthModel; - - final emailCredential = EmailAuthProvider.credentialWithLink( - emailLink: emailAuthModel.signInLink, - email: emailAuthModel.emailAddress, - ); - - final user = FirebaseAuth.instance.currentUser; - - try { - if (user != null) { - await user.linkWithCredential(emailCredential); - context.read().add( - const SetEmailVerificationStatus( - AuthenticationStatus.success, - ), - ); - await AirqoApiClient().syncPlatformAccount(); - } - } catch (error) { - context.read().add( - const SetEmailVerificationStatus( - AuthenticationStatus.error, - ), - ); - if (kDebugMode) { - print('Error linking accounts: $error'); - } - } - } - Future _authenticate() async { loadingScreen(context); @@ -255,36 +219,27 @@ class _EmailAuthVerificationWidgetState ); try { - final currentUser = FirebaseAuth.instance.currentUser; - if (currentUser != null) { - - Navigator.pop(context); - - await _linkAccountWithEmailCredential(currentUser, emailCredential); - - await AirqoApiClient().syncPlatformAccount(); - } else { - final bool authenticationSuccessful = - await CustomAuth.firebaseSignIn(emailCredential); - if (!mounted) return; - - if (!authenticationSuccessful) { - Navigator.pop(context); - await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext _) { - return const AuthFailureDialog(); - }, - ); - return; - } + final bool authenticationSuccessful = + await CustomAuth.firebaseSignIn(emailCredential); + if (!mounted) return; - context.read().add( - const SetEmailVerificationStatus(AuthenticationStatus.success)); + Navigator.pop(context); - Navigator.pop(context); + if (authenticationSuccessful) { + context + .read() + .add(const SetEmailVerificationStatus( + AuthenticationStatus.success, + )); await AppService.postSignInActions(context); + } else { + await showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext _) { + return const AuthFailureDialog(); + }, + ); } } catch (exception, stackTrace) { Navigator.pop(context); @@ -299,11 +254,6 @@ class _EmailAuthVerificationWidgetState } } - Future _linkAccountWithEmailCredential( - User currentUser, AuthCredential emailCredential) async { - await currentUser.linkWithCredential(emailCredential); - } - Future onWillPop() { final now = DateTime.now(); @@ -323,4 +273,4 @@ class _EmailAuthVerificationWidgetState return Future.value(false); } -} +} \ No newline at end of file diff --git a/mobile/lib/screens/email_link/confirm_account_details.dart b/mobile/lib/screens/email_link/confirm_account_details.dart deleted file mode 100644 index 55d91d978c..0000000000 --- a/mobile/lib/screens/email_link/confirm_account_details.dart +++ /dev/null @@ -1,311 +0,0 @@ -import 'dart:async'; - -import 'package:app/blocs/blocs.dart'; -import 'package:app/models/models.dart'; -import 'package:app/screens/email_link/email_link_widgets.dart'; -import 'package:app/screens/home_page.dart'; -import 'package:app/screens/offline_banner.dart'; -import 'package:app/services/rest_api.dart'; -import 'package:app/themes/theme.dart'; -import 'package:app/utils/utils.dart'; -import 'package:app/widgets/widgets.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import '../on_boarding/on_boarding_widgets.dart'; -import '../email_authentication/email_verification_screen.dart'; - -class _EmailVerifyWidget extends StatefulWidget { - const _EmailVerifyWidget({ - super.key, - required this.authProcedure, - }); - - final AuthProcedure authProcedure; - - @override - _EmailAuthWidgetState createState() => _EmailAuthWidgetState(); -} - -class _EmailAuthWidgetState extends State { - DateTime? _exitTime; - bool _keyboardVisible = false; - final _formKey = GlobalKey(); - String emailAddress = ""; - final AirqoApiClient apiClient = AirqoApiClient(); - - @override - void initState() { - super.initState(); - context.read().add(InitializeEmailAuth( - authProcedure: widget.authProcedure, - )); - } - - @override - void dispose() { - _formKey.currentState?.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - _keyboardVisible = MediaQuery.of(context).viewInsets.bottom != 0; - - return OfflineBanner( - child: Scaffold( - appBar: const OnBoardingTopBar(backgroundColor: Colors.white), - body: PopScope( - onPopInvoked: ((didPop) { - if (didPop) { - onWillPop(); - } - }), - child: AppSafeArea( - backgroundColor: Colors.white, - horizontalPadding: 24, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const EmailLinkTitle(), - const EmailLinkSubTitle(), - const SizedBox(height: 32), - Form( - key: _formKey, - child: SizedBox( - height: 48, - child: BlocBuilder( - buildWhen: (previous, current) { - return previous.status != current.status; - }, - builder: (context, state) { - return TextFormField( - validator: (value) { - if (value == null || !value.isValidEmail()) { - return AppLocalizations.of(context)! - .pleaseEnterAValidEmail; - } - - return null; - }, - onChanged: (value) { - setState(() => emailAddress = value); - }, - onSaved: (value) { - setState(() => emailAddress = value!); - }, - style: inputTextStyle(state.status), - enableSuggestions: true, - cursorWidth: 1, - autofocus: false, - enabled: state.status != AuthenticationStatus.success, - keyboardType: TextInputType.emailAddress, - decoration: inputDecoration( - state.status, - hintText: 'me@company.com', - suffixIconCallback: () { - _formKey.currentState?.reset(); - FocusScope.of(context).requestFocus(FocusNode()); - }, - ), - ); - }, - ), - ), - ), - const EmailLinkErrorMessage(), - const Spacer(), - NextButton( - buttonColor: emailAddress.isValidEmail() - ? CustomColors.appColorBlue - : CustomColors.appColorDisabled, - callBack: () async { - FocusScope.of(context).requestFocus(FocusNode()); - - switch (context.read().state.status) { - case AuthenticationStatus.initial: - case AuthenticationStatus.error: - FormState? formState = _formKey.currentState; - if (formState == null) { - return; - } - - if (formState.validate()) { - formState.save(); - await _sendAuthCode(); - } - break; - case AuthenticationStatus.success: - await verifyEmailAuthCode(context); - break; - } - }, - ), - const SizedBox( - height: 16, - ), - Visibility( - visible: !_keyboardVisible, - child: const SkipLinkButtons(), - ), - ], - ), - ), - ), - ), - ); - } - - Future _sendAuthCode() async { - context.read().add(const SetEmailAuthStatus( - AuthenticationStatus.initial, - )); - - final hasConnection = await hasNetworkConnection(); - - if (!mounted) { - return; - } - - if (!hasConnection) { - context.read().add(SetEmailAuthStatus( - AuthenticationStatus.error, - errorMessage: - AppLocalizations.of(context)!.checkYourInternetConnection, - )); - - return; - } - - final confirmation = await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return AuthMethodDialog( - credentials: emailAddress, - authMethod: AuthMethod.email, - ); - }, - ); - - if (confirmation == null || - confirmation == ConfirmationAction.cancel || - !mounted) { - return; - } - - loadingScreen(context); - - final bool? exists = await apiClient.checkIfUserExists( - emailAddress: emailAddress, - ); - - if (!mounted) { - return; - } - - if (exists == null) { - Navigator.pop(context); - await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext _) { - return const LinkFailureDialog(); - }, - ); - - return; - } - - AuthProcedure authProcedure = - context.read().state.authProcedure; - if (!exists && authProcedure == AuthProcedure.login) { - Navigator.pop(context); - context.read().add(SetEmailAuthStatus( - AuthenticationStatus.error, - errorMessage: - AppLocalizations.of(context)!.emailNotFoundDidYouSignUp, - )); - - return; - } - - if (exists && authProcedure == AuthProcedure.signup) { - Navigator.pop(context); - context.read().add(SetEmailAuthStatus( - AuthenticationStatus.error, - errorMessage: - AppLocalizations.of(context)!.emailAlreadyRegisteredPleaseLogIn, - )); - - return; - } - - EmailAuthModel? emailAuthModel = - await apiClient.sendEmailVerificationCode(emailAddress); - - if (!mounted) { - return; - } - Navigator.pop(context); - - if (emailAuthModel == null) { - await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext _) { - return const LinkFailureDialog(); - }, - ); - - return; - } - - context - .read() - .add(const SetEmailAuthStatus(AuthenticationStatus.success)); - context.read().add(InitializeEmailVerification( - emailAuthModel: emailAuthModel, - authProcedure: context.read().state.authProcedure, - )); - } - - Future onWillPop() { - final now = DateTime.now(); - - if (_exitTime == null || - now.difference(_exitTime!) > const Duration(seconds: 2)) { - _exitTime = now; - - showSnackBar( - context, - AppLocalizations.of(context)!.tapAgainToCancel, - ); - - return Future.value(false); - } - - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) { - return const HomePage(); - }), - (r) => false, - ); - - return Future.value(false); - } -} - -class EmailLinkScreen extends _EmailVerifyWidget { - const EmailLinkScreen({super.key}) - : super(authProcedure: AuthProcedure.signup); - - @override - EmailLinkScreenWidgetState createState() => EmailLinkScreenWidgetState(); -} - -class EmailLinkScreenWidgetState - extends _EmailAuthWidgetState {} diff --git a/mobile/lib/screens/email_link/email_link_page.dart b/mobile/lib/screens/email_link/email_link_page.dart deleted file mode 100644 index de1d961f69..0000000000 --- a/mobile/lib/screens/email_link/email_link_page.dart +++ /dev/null @@ -1,185 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:app/screens/email_link/confirm_account_details.dart'; -import 'package:app/screens/email_link/email_link_widgets.dart'; -import 'package:app/screens/quiz/quiz_view.dart'; -import 'package:app/themes/colors.dart'; -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:app/themes/theme.dart'; -import 'package:url_launcher/url_launcher.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -Future bottomSheetEmailLink(BuildContext context) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - bool shouldShowBottomSheet = true; - int remindMeLaterTimestamp = prefs.getInt('remindMeLaterTimestamp') ?? 0; - - if (remindMeLaterTimestamp > 3) { - DateTime lastRemindTimestamp = - DateTime.fromMillisecondsSinceEpoch(remindMeLaterTimestamp); - DateTime now = DateTime.now(); - if (now.difference(lastRemindTimestamp).inDays <= 1) { - shouldShowBottomSheet = false; - } - } - if (shouldShowBottomSheet) { - return showModalBottomSheet( - isScrollControlled: true, - enableDrag: false, - elevation: 1, - transitionAnimationController: bottomSheetTransition(context), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - ), - ), - isDismissible: false, - context: context, - builder: (context) { - return SizedBox( - height: MediaQuery.of(context).size.height * 0.9, - child: AnimatedPadding( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - padding: const EdgeInsets.fromLTRB(0, 2, 0, 10), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 3), - SizedBox( - height: 215, - width: 373, - child: AnimatedPadding( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - padding: const EdgeInsets.fromLTRB(4, 4, 4, 10), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: Image.asset( - 'assets/images/email_link.png', - fit: BoxFit.cover, - height: double.infinity, - width: double.infinity, - alignment: Alignment.center, - ), - ), - ), - ), - const SizedBox(height: 10), - AnimatedPadding( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - padding: const EdgeInsets.fromLTRB(30, 0, 30, 20), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - width: 295.53, - height: 67, - child: AutoSizeText( - AppLocalizations.of(context)! - .weAreShufflingThingsAroundForYou, - textAlign: TextAlign.center, - style: TextStyle( - color: CustomColors.quizColorBlack, - fontWeight: FontWeight.w700, - fontSize: 19.58, - ), - ), - ), - const SizedBox(height: 10), - SizedBox( - width: 271, - height: 67, - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - children: [ - TextSpan( - text: AppLocalizations.of(context)! - .youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe, - style: const TextStyle( - color: Color(0xFF485972), - fontSize: 13.24, - fontWeight: FontWeight.w400, - ), - ), - TextSpan( - text: "AirQo analytics", - style: TextStyle( - color: CustomColors.appColorBlue, - fontSize: 13.24, - fontWeight: FontWeight.w400, - decoration: TextDecoration.underline, - ), - recognizer: TapGestureRecognizer() - ..onTap = () async { - Uri url = - Uri.parse('https://platform.airqo.net'); - if (await canLaunchUrl(url)) { - await launchUrl( - url, - mode: LaunchMode.inAppBrowserView, - ); - } else { - throw 'Could not launch $url'; - } - }, - ), - TextSpan( - text: AppLocalizations.of(context)! - .withOneAccount, - style: const TextStyle( - color: Color(0xFF485972), - fontSize: 13.24, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), - ), - const SizedBox(height: 20), - InkWell( - onTap: () async { - Navigator.push(context, MaterialPageRoute( - builder: (context) { - return const EmailLinkScreen(); - }, - )); - }, - child: EmailLinkActionButton( - text: AppLocalizations.of(context)!.addMyEmail, - ), - ), - const SizedBox(height: 10), - InkWell( - onTap: () async { - Navigator.pop(context, false); - prefs.setInt( - 'remindMeLaterTimestamp', - DateTime.now().millisecondsSinceEpoch, - ); - }, - child: EmailLinkSkipButton( - text: AppLocalizations.of(context)!.remindMeLater, - ), - ), - ], - ), - ), - ], - ), - ), - ); - }, - ); - } -} diff --git a/mobile/lib/screens/email_link/email_link_widgets.dart b/mobile/lib/screens/email_link/email_link_widgets.dart deleted file mode 100644 index 2b9b6f0ba0..0000000000 --- a/mobile/lib/screens/email_link/email_link_widgets.dart +++ /dev/null @@ -1,330 +0,0 @@ -import 'package:app/blocs/email_auth/email_auth_bloc.dart'; -import 'package:app/models/enum_constants.dart'; -import 'package:app/screens/home_page.dart'; -import 'package:app/themes/app_theme.dart'; -import 'package:app/themes/colors.dart'; -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class EmailLinkActionButton extends StatelessWidget { - const EmailLinkActionButton({ - super.key, - required this.text, - }); - final String text; - - @override - Widget build(BuildContext context) { - return Container( - height: 39.94, - width: 159.66, - padding: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - color: CustomColors.appColorBlue, - borderRadius: const BorderRadius.all( - Radius.circular(8.0), - ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - text, - style: const TextStyle( - color: Colors.white, - fontSize: 14, - letterSpacing: 16 * -0.022, - ), - ), - const SizedBox( - width: 6, - ), - ], - ), - ); - } -} - -class EmailLinkSkipButton extends StatelessWidget { - const EmailLinkSkipButton({ - super.key, - required this.text, - }); - final String text; - - @override - Widget build(BuildContext context) { - return IntrinsicWidth( - child: Container( - height: 39.94, - padding: const EdgeInsets.symmetric(horizontal: 8), - decoration: const BoxDecoration( - color: Color.fromARGB(0, 0, 0, 0), - borderRadius: BorderRadius.all( - Radius.circular(8.0), - ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - text, - style: const TextStyle( - color: Color.fromARGB(197, 0, 0, 0), - fontSize: 14, - letterSpacing: 16 * -0.022, - ), - ), - const SizedBox( - width: 6, - ), - ], - ), - ), - ); - } -} - -class EmailLinkErrorMessage extends StatelessWidget { - const EmailLinkErrorMessage({super.key}); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state.errorMessage.isEmpty) { - return const SizedBox.shrink(); - } - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 16), - child: SizedBox( - child: Row( - children: [ - SvgPicture.asset( - 'assets/icon/error_info_icon.svg', - ), - const SizedBox( - width: 5, - ), - Expanded( - child: AutoSizeText( - AppLocalizations.of(context)!.yourEmailIsAlreadyRegistered, - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - color: CustomColors.appColorInvalid, - fontSize: 14, - ), - ), - ), - ], - ), - ), - ); - }, - ); - } -} - -class EmailLinkTitle extends StatelessWidget { - const EmailLinkTitle({super.key}); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - String message; - switch (state.status) { - case AuthenticationStatus.initial: - message = AppLocalizations.of(context)!.addYourEmail; - break; - case AuthenticationStatus.error: - message = - AppLocalizations.of(context)!.oopsSomethingsWrongWithYourEmail; - break; - case AuthenticationStatus.success: - message = AppLocalizations.of(context)!.success; - break; - } - - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16, top: 10), - child: AutoSizeText( - message, - textAlign: TextAlign.center, - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: CustomTextStyle.headline7(context), - ), - ); - }, - ); - } -} - -class SkipLinkButtons extends StatelessWidget { - const SkipLinkButtons({super.key}); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state.status == AuthenticationStatus.success || - context.read().state.authProcedure != - AuthProcedure.signup) { - return const SizedBox.shrink(); - } - - return Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Column( - children: [ - const SizedBox(height: 8), - GestureDetector( - onTap: () async { - SharedPreferences prefs = - await SharedPreferences.getInstance(); - prefs.setInt( - 'remindMeLaterTimestamp', - DateTime.now().millisecondsSinceEpoch, - ); - Navigator.pop(context); - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) { - return const HomePage(); - }), - (r) => true, - ); - }, - child: Text( - AppLocalizations.of(context)!.skip, - style: const TextStyle( - color: Colors.blue, // Customize the color as needed - ), - ), - ), - ], - ), - ); - }, - ); - } -} - -class EmailLinkSubTitle extends StatelessWidget { - const EmailLinkSubTitle({super.key}); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - String message; - switch (state.status) { - case AuthenticationStatus.error: - return const SizedBox.shrink(); - case AuthenticationStatus.initial: - message = - AppLocalizations.of(context)!.wellSendYouAVerificationCode; - - break; - case AuthenticationStatus.success: - message = "Your Email has been added"; - break; - } - - return Padding( - padding: const EdgeInsets.only(left: 16, right: 16, top: 8), - child: AutoSizeText( - message, - textAlign: TextAlign.center, - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: CustomColors.appColorBlack.withOpacity(0.6), - ), - ), - ); - }, - ); - } -} - -class LinkAuthButtons extends StatelessWidget { - const LinkAuthButtons({super.key}); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state.status == AuthenticationStatus.success) { - return const SizedBox.shrink(); - } - - return Padding( - padding: const EdgeInsets.only(bottom: 12), - child: context.read().state.authProcedure == - AuthProcedure.signup - ? Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - EmailLinkActionButton( - text: AppLocalizations.of(context)!.add, - ), - const SizedBox( - width: 12, - ), - EmailLinkSkipButton( - text: AppLocalizations.of(context)!.skip, - ), - ], - ) - : const SizedBox.shrink(), - ); - }, - ); - } -} - -class LinkFailureDialog extends StatelessWidget { - const LinkFailureDialog({super.key}); - - @override - Widget build(BuildContext context) { - return CupertinoAlertDialog( - title: Text( - AppLocalizations.of(context)!.oopsSomethingWentWrongPleaseTryAgainLater, - textAlign: TextAlign.center, - style: CustomTextStyle.headline8(context), - ), - actions: [ - CupertinoDialogAction( - onPressed: () async { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const HomePage(), - ), - ); - }, - isDefaultAction: true, - isDestructiveAction: false, - child: Text( - AppLocalizations.of(context)!.tryAgainLater, - style: CustomTextStyle.button2(context) - ?.copyWith(color: CustomColors.appColorBlue), - ), - ), - ], - ); - } -} diff --git a/mobile/lib/screens/email_link/link_verification_screen.dart b/mobile/lib/screens/email_link/link_verification_screen.dart deleted file mode 100644 index a33e514964..0000000000 --- a/mobile/lib/screens/email_link/link_verification_screen.dart +++ /dev/null @@ -1,313 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:app/blocs/blocs.dart'; -import 'package:app/models/enum_constants.dart'; -import 'package:app/screens/dashboard/dashboard_view.dart'; -import 'package:app/screens/email_authentication/email_auth_widgets.dart'; -import 'package:app/services/services.dart'; -import 'package:app/themes/theme.dart'; -import 'package:app/utils/utils.dart'; -import 'package:app/widgets/widgets.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import '../../widgets/auth_widgets.dart'; -import '../on_boarding/on_boarding_widgets.dart'; - -Future verifyLinkAuthCode(BuildContext context) async { - await Navigator.of(context).push( - PageRouteBuilder( - pageBuilder: (context, animation, secondaryAnimation) => - const _EmailAuthVerificationWidget(), - transitionsBuilder: (context, animation, secondaryAnimation, child) { - const begin = Offset(0.0, 1.0); - const end = Offset.zero; - const curve = Curves.ease; - - var tween = Tween( - begin: begin, - end: end, - ).chain(CurveTween(curve: curve)); - - return SlideTransition( - position: animation.drive(tween), - child: child, - ); - }, - ), - ); -} - -class _EmailAuthVerificationWidget extends StatefulWidget { - const _EmailAuthVerificationWidget(); - - @override - State<_EmailAuthVerificationWidget> createState() => - _EmailAuthVerificationWidgetState(); -} - -class _EmailAuthVerificationWidgetState - extends State<_EmailAuthVerificationWidget> { - DateTime? _exitTime; - final _formKey = GlobalKey(); - String _inputCode = ''; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: const OnBoardingTopBar(backgroundColor: Colors.white), - body: PopScope( - onPopInvoked: ((didPop) { - if (didPop) { - onWillPop(); - } - }), - child: AppSafeArea( - horizontalPadding: 24, - backgroundColor: Colors.white, - child: BlocBuilder( - builder: (context, state) { - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const EmailVerificationTitle(), - const EmailVerificationSubTitle(), - const SizedBox( - height: 20, - ), - Form( - key: _formKey, - child: SizedBox( - height: 64, - child: AnimatedPadding( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - padding: const EdgeInsets.symmetric(horizontal: 36), - child: TextFormField( - validator: (value) { - String? error; - if (value == null) { - error = AppLocalizations.of(context)! - .pleaseEnterTheCode; - } - - if (value != null && value.length < 6) { - error = AppLocalizations.of(context)! - .pleaseEnterAllTheDigits; - } - - if (value != - state.emailAuthModel.token.toString()) { - error = AppLocalizations.of(context)! - .pleaseEnterAllTheDigits; - } - - if (error != null) { - context - .read() - .add(const SetEmailVerificationStatus( - AuthenticationStatus.error, - )); - } - - return error; - }, - onChanged: (value) { - setState(() => _inputCode = value); - }, - showCursor: state.codeCountDown <= 0 && - state.status != AuthenticationStatus.success, - enabled: state.codeCountDown <= 0 && - state.status != AuthenticationStatus.success, - textAlign: TextAlign.center, - maxLength: 6, - cursorWidth: 1, - keyboardType: TextInputType.number, - style: inputTextStyle( - state.status, - optField: true, - ), - decoration: optInputDecoration( - state.status, - codeSent: state.codeCountDown <= 0, - ), - ), - ), - ), - ), - const EmailVerificationCodeCountDown(), - Visibility( - visible: state.status != AuthenticationStatus.success, - child: const AuthOrSeparator(), - ), - Visibility( - visible: state.status != AuthenticationStatus.success, - child: const ChangeAuthCredentials(AuthMethod.email), - ), - const Spacer(), - Visibility( - visible: state.status == AuthenticationStatus.success, - child: const AuthSuccessWidget(), - ), - const Spacer(), - NextButton( - buttonColor: _inputCode.length >= 6 - ? CustomColors.appColorBlue - : CustomColors.appColorDisabled, - callBack: () async { - switch (state.status) { - case AuthenticationStatus.success: - break; - case AuthenticationStatus.error: - case AuthenticationStatus.initial: - if (_inputCode.length < 6) { - return; - } - FormState? formState = _formKey.currentState; - if (formState == null) { - return; - } - if (formState.validate()) { - await _authenticate(); - } - return; - } - - if (!mounted) return; - - if (state.authProcedure == AuthProcedure.login) { - await Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) { - return const DashboardView(); - }), - (r) => false, - ); - } else { - await Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) { - return const DashboardView(); - }), - (r) => false, - ); - } - }, - ), - const SizedBox( - height: 12, - ), - ], - ); - }, - ), - ), - ), - ); - } - - Future linkAccounts() async { - final emailAuthModel = - context.read().state.emailAuthModel; - - final emailCredential = EmailAuthProvider.credentialWithLink( - emailLink: emailAuthModel.signInLink, - email: emailAuthModel.emailAddress, - ); - - final user = CustomAuth.getUser(); - - try { - if (user != null) { - await user.linkWithCredential(emailCredential); - context.read().add( - const SetEmailVerificationStatus( - AuthenticationStatus.success, - ), - ); - await AirqoApiClient().syncPlatformAccount(); - } - } catch (error) { - context.read().add( - const SetEmailVerificationStatus( - AuthenticationStatus.error, - ), - ); - if (kDebugMode) { - print('Error linking accounts: $error'); - } - } - } - - Future _authenticate() async { - loadingScreen(context); - - final emailAuthModel = - context.read().state.emailAuthModel; - final emailCredential = EmailAuthProvider.credentialWithLink( - emailLink: emailAuthModel.signInLink, - email: emailAuthModel.emailAddress, - ); - - try { - final currentUser = CustomAuth.getUser(); - if (currentUser != null) { - await currentUser.linkWithCredential(emailCredential); - } else { - final bool authenticationSuccessful = - await CustomAuth.firebaseSignIn(emailCredential); - if (!mounted) return; - - if (!authenticationSuccessful) { - await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext _) { - return const AuthFailureDialog(); - }, - ); - } - } - - context - .read() - .add(const SetEmailVerificationStatus( - AuthenticationStatus.success, - )); - } catch (exception, stackTrace) { - Navigator.pop(context); - await showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext _) { - return const AuthFailureDialog(); - }, - ); - await logException(exception, stackTrace); - } - } - - Future onWillPop() { - final now = DateTime.now(); - - if (_exitTime == null || - now.difference(_exitTime!) > const Duration(seconds: 2)) { - _exitTime = now; - - showSnackBar( - context, - AppLocalizations.of(context)!.tapAgainToCancel, - ); - - return Future.value(false); - } - - Navigator.pop(context, false); - - return Future.value(false); - } -} diff --git a/mobile/lib/screens/home_page.dart b/mobile/lib/screens/home_page.dart index 8d19ef881f..5f90115921 100644 --- a/mobile/lib/screens/home_page.dart +++ b/mobile/lib/screens/home_page.dart @@ -4,7 +4,6 @@ import 'package:animations/animations.dart'; import 'package:app/blocs/blocs.dart'; import 'package:app/constants/config.dart'; import 'package:app/models/models.dart'; -import 'package:app/screens/email_link/email_link_page.dart'; import 'package:app/screens/profile/profile_view.dart'; import 'package:app/screens/settings/update_screen.dart'; import 'package:app/services/services.dart'; @@ -17,6 +16,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:showcaseview/showcaseview.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -25,7 +25,6 @@ import 'for_you_page.dart'; import 'map/map_view.dart'; import 'offline_banner.dart'; - class HomePage extends StatefulWidget { const HomePage({super.key}); @@ -242,23 +241,6 @@ class _HomePageState extends State { }); } }); - WidgetsBinding.instance.addPostFrameCallback((_) async { - final user = CustomAuth.getUser(); - if ((user != null && user.phoneNumber != null)) { - if (user.email != null) { - return; - } else if (user.isAnonymous) { - return; - } - if (mounted) { - await bottomSheetEmailLink(context); - } - } - }); - } - - Future showEmailLinkBottomSheet(BuildContext context) async { - await bottomSheetEmailLink(context); } Future _initializeDynamicLinks() async { diff --git a/mobile/lib/screens/profile/profile_edit_page.dart b/mobile/lib/screens/profile/profile_edit_page.dart index 34a9daee98..ad4b702753 100644 --- a/mobile/lib/screens/profile/profile_edit_page.dart +++ b/mobile/lib/screens/profile/profile_edit_page.dart @@ -1,6 +1,5 @@ import 'package:app/blocs/blocs.dart'; import 'package:app/models/models.dart'; -import 'package:app/screens/email_link/confirm_account_details.dart'; import 'package:app/themes/theme.dart'; import 'package:app/widgets/widgets.dart'; import 'package:flutter/material.dart'; @@ -22,9 +21,6 @@ class ProfileEditPage extends StatelessWidget { horizontalPadding: 16, child: BlocBuilder( builder: (context, profile) { - bool isAccountLinked = profile.phoneNumber.isNotEmpty && - profile.emailAddress.isNotEmpty; - return ListView( physics: const BouncingScrollPhysics(), children: [ @@ -36,71 +32,14 @@ class ProfileEditPage extends StatelessWidget { height: 40, ), Visibility( - visible: true, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 16), - EditCredentialsField( - profile: profile, - authMethod: AuthMethod.phone, - ), - const SizedBox(height: 16), - Visibility( - visible: !isAccountLinked, - child: GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const EmailLinkScreen(), - ), - ); - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Email Address', - style: TextStyle( - fontSize: 12, - color: CustomColors.inactiveColor, - ), - ), - const SizedBox(height: 4), - TextFormField( - initialValue: '', - onTap: () { - FocusScope.of(context).unfocus(); - }, - decoration: InputDecoration( - filled: true, - fillColor: Colors.white, - hintText:AppLocalizations.of(context)!.enterYourEmailAddress, - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - enabledBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: Colors.transparent, - width: 1.0), - borderRadius: BorderRadius.circular(8.0), - ), - ), - ), - ], - ), - ), - ), - const SizedBox(height: 16), - ], + visible: profile.phoneNumber.isNotEmpty, + child: EditCredentialsField( + profile: profile, + authMethod: AuthMethod.phone, ), ), Visibility( - visible: isAccountLinked, + visible: profile.emailAddress.isNotEmpty, child: EditCredentialsField( profile: profile, authMethod: AuthMethod.email, @@ -154,4 +93,4 @@ class ProfileEditPage extends StatelessWidget { ), ); } -} +} \ No newline at end of file diff --git a/mobile/lib/screens/profile/profile_view.dart b/mobile/lib/screens/profile/profile_view.dart index f53f486367..ba3a0f73e9 100644 --- a/mobile/lib/screens/profile/profile_view.dart +++ b/mobile/lib/screens/profile/profile_view.dart @@ -1,6 +1,5 @@ import 'package:app/blocs/blocs.dart'; import 'package:app/models/models.dart'; -import 'package:app/services/firebase_service.dart'; import 'package:app/themes/theme.dart'; import 'package:app/widgets/widgets.dart'; import 'package:flutter/material.dart'; @@ -15,16 +14,6 @@ class ProfileView extends StatelessWidget { @override Widget build(BuildContext context) { - final user = CustomAuth.getUser(); - bool showLinkAccountReminder = false; - - if (user != null && user.phoneNumber != null) { - if (user.email != null) { - } else if (user.isAnonymous) { - } else { - showLinkAccountReminder = true; - } - } return BlocBuilder( builder: (context, profile) { if (profile.isAnonymous) { @@ -35,14 +24,9 @@ class ProfileView extends StatelessWidget { appBar: ProfileViewAppBar(profile), body: AppSafeArea( horizontalPadding: 16, - child: ListView( + child: Column( children: [ const SizedBox(height: 10), - Visibility( - visible: showLinkAccountReminder, - child: const LinkAccountReminder(), - ), - const SizedBox(height: 6), ProfileSection(profile), const SizedBox(height: 16), CardSection( @@ -53,7 +37,7 @@ class ProfileView extends StatelessWidget { isBottomItem: true, isTopItem: true, ), - const SizedBox(height: 10), + const Spacer(), const SignOutButton(), const SizedBox(height: 10), ], @@ -63,4 +47,4 @@ class ProfileView extends StatelessWidget { }, ); } -} +} \ No newline at end of file diff --git a/mobile/lib/screens/profile/profile_widgets.dart b/mobile/lib/screens/profile/profile_widgets.dart index 147b251c93..56f893439a 100644 --- a/mobile/lib/screens/profile/profile_widgets.dart +++ b/mobile/lib/screens/profile/profile_widgets.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:app/blocs/blocs.dart'; import 'package:app/constants/constants.dart'; import 'package:app/models/models.dart'; -import 'package:app/screens/email_link/confirm_account_details.dart'; import 'package:app/screens/notification/notification_page.dart'; import 'package:app/services/services.dart'; import 'package:app/themes/theme.dart'; @@ -11,15 +10,12 @@ import 'package:app/utils/utils.dart'; import 'package:app/widgets/widgets.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:cached_network_image/cached_network_image.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_svg/svg.dart'; import 'package:image_picker/image_picker.dart'; -import 'package:url_launcher/url_launcher.dart'; import '../favourite_places/favourite_places_page.dart'; import '../feedback/feedback_page.dart'; @@ -102,61 +98,6 @@ class _SignOutButtonState extends State { } } -class GuestFeedbackButton extends StatelessWidget { - const GuestFeedbackButton({super.key}); - - @override - Widget build(BuildContext context) { - return OutlinedButton( - onPressed: () async { - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) { - return const FeedbackPage(); - }, - ), - ); - }, - style: OutlinedButton.styleFrom( - elevation: 0, - side: const BorderSide( - color: Colors.transparent, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(8), - ), - ), - backgroundColor: Colors.white, - foregroundColor: CustomColors.appColorBlue, - padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), - ), - child: ListTile( - leading: Container( - height: 40, - width: 40, - decoration: BoxDecoration( - color: CustomColors.appColorBlue.withOpacity(0.15), - shape: BoxShape.circle, - ), - child: Center( - child: Icon( - Icons.chat, - color: CustomColors.appColorBlue, - ), - ), - ), - title: AutoSizeText( - AppLocalizations.of(context)!.sendFeedback, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodyLarge, - ), - ), - ); - } -} - class SignUpSection extends StatelessWidget { const SignUpSection({super.key}); @@ -173,11 +114,9 @@ class SignUpSection extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox( - height: 15, + height: 48, ), - AnimatedPadding( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, + Padding( padding: const EdgeInsets.symmetric(horizontal: 25.0), child: AutoSizeText( AppLocalizations.of(context)!.personaliseYourExperience, @@ -191,9 +130,7 @@ class SignUpSection extends StatelessWidget { const SizedBox( height: 8, ), - AnimatedPadding( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, + Padding( padding: const EdgeInsets.symmetric(horizontal: 55.0), child: AutoSizeText( AppLocalizations.of(context)! @@ -209,14 +146,12 @@ class SignUpSection extends StatelessWidget { const SizedBox( height: 4, ), - AnimatedPadding( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - padding: const EdgeInsets.symmetric(horizontal: 32), - child: const SignUpButton(), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 32), + child: SignUpButton(), ), const SizedBox( - height: 30, + height: 40, ), ], ), @@ -861,7 +796,7 @@ class EditProfileAppBar extends StatelessWidget implements PreferredSizeWidget { ? Colors.transparent : CustomColors.appColorBlue, ), - child: AutoSizeText( + child: Text( AppLocalizations.of(context)!.save, textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleSmall?.copyWith( @@ -883,31 +818,14 @@ class EditProfileAppBar extends StatelessWidget implements PreferredSizeWidget { Size get preferredSize => const Size.fromHeight(60); } -class EditCredentialsField extends StatefulWidget { +class EditCredentialsField extends StatelessWidget { const EditCredentialsField({ super.key, required this.authMethod, required this.profile, - this.isSaveClicked = false, }); - final AuthMethod authMethod; final Profile profile; - final bool isSaveClicked; - - @override - EditCredentialsFieldState createState() => EditCredentialsFieldState(); -} - -class EditCredentialsFieldState extends State { - late bool isReadOnly; - - @override - void initState() { - super.initState(); - // Set the initial readOnly status based on whether the email is present - isReadOnly = widget.profile.emailAddress.isNotEmpty; - } @override Widget build(BuildContext context) { @@ -916,7 +834,7 @@ class EditCredentialsFieldState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.authMethod == AuthMethod.email + authMethod == AuthMethod.email ? AppLocalizations.of(context)!.email : AppLocalizations.of(context)!.phoneNumber, style: TextStyle( @@ -928,44 +846,16 @@ class EditCredentialsFieldState extends State { height: 4, ), TextFormField( - initialValue: widget.authMethod == AuthMethod.email - ? widget.profile.emailAddress - : widget.profile.phoneNumber, + initialValue: authMethod == AuthMethod.email + ? profile.emailAddress + : profile.phoneNumber, enableSuggestions: false, - readOnly: widget.isSaveClicked || isReadOnly, + readOnly: true, style: TextStyle(color: CustomColors.inactiveColor), - onChanged: (value) { - if (widget.authMethod == AuthMethod.email && - !widget.isSaveClicked) { - context.read().add( - UpdateProfile( - widget.profile.copyWith(emailAddress: value), - ), - ); - } - }, - onTap: () { - // Allow editing when the user taps the field - if (!widget.isSaveClicked) { - setState(() { - isReadOnly = false; - }); - } - }, decoration: InputDecoration( filled: true, fillColor: Colors.white, hintText: '-', - suffixIcon: isReadOnly - ? null - : Container( - padding: const EdgeInsets.all(10), - height: 20, - width: 20, - child: SvgPicture.asset( - 'assets/icon/profile_edit.svg', - ), - ), focusedBorder: OutlineInputBorder( borderSide: const BorderSide(color: Colors.transparent, width: 1.0), @@ -1044,7 +934,7 @@ class GuestProfileView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox( - height: 15, + height: 20, ), const Row( children: [ @@ -1068,148 +958,18 @@ class GuestProfileView extends StatelessWidget { horizontalPadding: 16.0, child: Column( children: [ - SignUpSection(), SizedBox( - height: 8, + height: 24, ), - SettingsButton(), + SignUpSection(), SizedBox( - height: 8, + height: 16, ), - GuestFeedbackButton(), + SettingsButton(), Spacer(), ], ), ), ); } -} - -class LinkAccountReminder extends StatelessWidget { - const LinkAccountReminder({super.key}); - - @override - Widget build(BuildContext context) { - return Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - color: const Color.fromARGB(255, 184, 217, 255), - elevation: 1, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: SizedBox( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - AppLocalizations.of(context)!.accessDeeperAirQualityInsights, - style: const TextStyle( - color: Color.fromARGB(197, 0, 0, 0), - fontSize: 18, - fontWeight: FontWeight.w600, - ), - ), - const SizedBox(height: 4), - RichText( - textAlign: TextAlign.start, - text: TextSpan( - children: [ - TextSpan( - text: AppLocalizations.of(context)! - .addYourEmailToYourProfileToEnableYouToAccessThe, - style: const TextStyle( - color: Color(0xFF485972), - fontSize: 13.24, - fontWeight: FontWeight.w400, - ), - ), - TextSpan( - text: "AirQo analytics ", - style: TextStyle( - color: CustomColors.appColorBlue, - fontSize: 13.24, - fontWeight: FontWeight.w400, - decoration: TextDecoration.underline, - ), - recognizer: TapGestureRecognizer() - ..onTap = () async { - Uri url = Uri.parse('https://platform.airqo.net'); - if (await canLaunchUrl(url)) { - await launchUrl( - url, - mode: LaunchMode.inAppBrowserView, - ); - } else { - throw 'Could not launch $url'; - } - }, - ), - TextSpan( - text: AppLocalizations.of(context)! - .usingYourAirQoMobileAppAccount, - style: const TextStyle( - color: Color(0xFF485972), - fontSize: 13.24, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), - const SizedBox(height: 8), - MaterialButton( - height: 40, - color: CustomColors.appBodyColor, - onPressed: () async { - Navigator.push(context, MaterialPageRoute( - builder: (context) { - return const EmailLinkScreen(); - }, - )); - }, - padding: const EdgeInsets.only(top: 8, bottom: 8), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - child: Row( - children: [ - Padding( - padding: const EdgeInsets.only(left: 16, right: 10), - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.535, - child: AutoSizeText( - overflow: TextOverflow.ellipsis, - AppLocalizations.of(context)!.addMyEmailToMyProfile, - style: TextStyle( - color: CustomColors.appColorBlue, - fontSize: 14, - fontWeight: FontWeight.w400, - )), - ), - ), - const SizedBox(width: 10), - Container( - height: 35, - width: 35, - decoration: const BoxDecoration( - color: Color.fromARGB(255, 184, 217, 255), - shape: BoxShape.circle, - ), - child: Icon( - Icons.arrow_forward_ios_rounded, - size: 18, - color: CustomColors.appColorBlue, - ), - ), - ], - ), - ), - ], - ), - ), - ), - ); - } -} +} \ No newline at end of file From 2371947830e713d84ca39023d36fbba97ddd53b0 Mon Sep 17 00:00:00 2001 From: katendejericho <106674175+katendejericho5@users.noreply.github.com> Date: Thu, 9 May 2024 14:12:24 +0300 Subject: [PATCH 2/2] remove unsued imports --- mobile/lib/screens/home_page.dart | 64 +++++++++++++++++-------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/mobile/lib/screens/home_page.dart b/mobile/lib/screens/home_page.dart index 5f90115921..c035328605 100644 --- a/mobile/lib/screens/home_page.dart +++ b/mobile/lib/screens/home_page.dart @@ -16,7 +16,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:showcaseview/showcaseview.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -25,6 +24,7 @@ import 'for_you_page.dart'; import 'map/map_view.dart'; import 'offline_banner.dart'; + class HomePage extends StatefulWidget { const HomePage({super.key}); @@ -222,25 +222,31 @@ class _HomePageState extends State { ); await _initializeDynamicLinks(); await SharedPreferencesHelper.updateOnBoardingPage(OnBoardingPage.home); - WidgetsBinding.instance.addPostFrameCallback((_) async { - if (context.read().state.checkForUpdates) { - final PackageInfo packageInfo = await PackageInfo.fromPlatform(); + WidgetsBinding.instance.addPostFrameCallback( + (_) async { + if (context.read().state.checkForUpdates) { + final PackageInfo packageInfo = await PackageInfo.fromPlatform(); - await AirqoApiClient() - .getAppVersion( - currentVersion: packageInfo.version, - bundleId: Platform.isIOS ? packageInfo.packageName : null, - packageName: Platform.isAndroid ? packageInfo.packageName : null, - ) - .then((version) async { - if (version != null && mounted && !version.isUpdated) { - await canLaunchUrl(version.url).then((bool result) async { - await openUpdateScreen(context, version); - }); - } - }); - } - }); + await AirqoApiClient() + .getAppVersion( + currentVersion: packageInfo.version, + bundleId: Platform.isIOS ? packageInfo.packageName : null, + packageName: Platform.isAndroid ? packageInfo.packageName : null, + ) + .then( + (version) async { + if (version != null && mounted && !version.isUpdated) { + await canLaunchUrl(version.url).then( + (bool result) async { + await openUpdateScreen(context, version); + }, + ); + } + }, + ); + } + }, + ); } Future _initializeDynamicLinks() async { @@ -319,14 +325,16 @@ class _HomePageState extends State { } void _startShowcase() { - WidgetsBinding.instance.addPostFrameCallback((_) { - ShowCaseWidget.of(_showcaseContext).startShowCase( - [ - _homeShowcaseKey, - _mapShowcaseKey, - _profileShowcaseKey, - ], - ); - }); + WidgetsBinding.instance.addPostFrameCallback( + (_) { + ShowCaseWidget.of(_showcaseContext).startShowCase( + [ + _homeShowcaseKey, + _mapShowcaseKey, + _profileShowcaseKey, + ], + ); + }, + ); } }