From cb2d222288e6e9b6dec9554202a11913f04c5aa1 Mon Sep 17 00:00:00 2001 From: katendejericho <106674175+katendejericho5@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:35:37 +0300 Subject: [PATCH] Initial --- mobile/lib/l10n/app_en.arb | 9 +- mobile/lib/l10n/app_fr.arb | 6 +- mobile/lib/l10n/app_lg.arb | 7 +- mobile/lib/l10n/app_pt.arb | 6 +- mobile/lib/l10n/app_sw.arb | 6 +- .../screens/email_link/email_link_page.dart | 19 +-- .../email_link/email_link_widgets.dart | 21 ++- mobile/lib/screens/home_page.dart | 1 - mobile/lib/screens/profile/profile_view.dart | 21 ++- .../lib/screens/profile/profile_widgets.dart | 129 ++++++++++++++++++ mobile/pubspec.lock | 56 +++++--- 11 files changed, 236 insertions(+), 45 deletions(-) diff --git a/mobile/lib/l10n/app_en.arb b/mobile/lib/l10n/app_en.arb index 54f09111d5..3e9ba432f3 100644 --- a/mobile/lib/l10n/app_en.arb +++ b/mobile/lib/l10n/app_en.arb @@ -363,6 +363,9 @@ "youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe" :" You would be required to add your email to your profile on the mobile app to enable you access the ", "withOneAccount":" with one account.", "addMyEmail":"Add my email", - "remindMeLater":"Remind me later" - -} \ No newline at end of file + "remindMeLater":"Remind me later", + "addMyEmailToMyProfile":"Add my email to my profile", + "addYourEmailToYourProfileToEnableYouToAccessThe" : "Add your email to your profile to enable you to access the ", + "accessDeeperAirQualityInsights":"Access deeper Air Quality insights", + "usingYourAirQoMobileAppAccount":"using your AirQo mobile app account" + } \ No newline at end of file diff --git a/mobile/lib/l10n/app_fr.arb b/mobile/lib/l10n/app_fr.arb index 8dee6fe7cb..3ceb1f2232 100644 --- a/mobile/lib/l10n/app_fr.arb +++ b/mobile/lib/l10n/app_fr.arb @@ -353,5 +353,9 @@ "youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe" : " Vous devrez ajouter votre e-mail à votre profil sur l'application mobile pour vous permettre d'accéder au ", "withOneAccount":" avec un compte.", "addMyEmail":"ajouter mon e-mail", - "remindMeLater":"Rappelez-moi plus tard" + "remindMeLater":"Rappelez-moi plus tard", + "addMyEmailToMyProfile":"Ajoutez mon e-mail à mon profil", + "addYourEmailToYourProfileToEnableYouToAccessThe" : "Ajoutez votre e-mail à votre profil pour vous permettre d'accéder au ", + "accessDeeperAirQualityInsights":"Accéder à des informations plus approfondies sur la qualité de l'air", + "usingYourAirQoMobileAppAccount":"En utilisant votre compte AirQo Mobile App" } diff --git a/mobile/lib/l10n/app_lg.arb b/mobile/lib/l10n/app_lg.arb index 855a709e43..9b4cc49c71 100644 --- a/mobile/lib/l10n/app_lg.arb +++ b/mobile/lib/l10n/app_lg.arb @@ -355,6 +355,9 @@ "youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe":" Wandibadde weetaaga okwongera email yo ku profile yo ku app y'essimu okukusobozesa okuyingira mu ", "withOneAccount":" nga erina akawunti emu.", "addMyEmail":"Yongerako email yange", - "remindMeLater":"Nzijukiza oluvannyuma" - + "remindMeLater":"Nzijukiza oluvannyuma", + "addMyEmailToMyProfile":"Yongerako email yange ku profile yange", + "addYourEmailToYourProfileToEnableYouToAccessThe" : "Yongerako email yo ku profile yo okukusobozesa okuyingira mu ", + "accessDeeperAirQualityInsights":"okwekenenya okw'omutindo gw'empewo", + "usingYourAirQoMobileAppAccount":"okuva ku akawunti yo ku app ya AirQo" } diff --git a/mobile/lib/l10n/app_pt.arb b/mobile/lib/l10n/app_pt.arb index b4888bd304..43883c4fa3 100644 --- a/mobile/lib/l10n/app_pt.arb +++ b/mobile/lib/l10n/app_pt.arb @@ -353,5 +353,9 @@ "youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe":" Você deverá adicionar seu e-mail ao seu perfil no aplicativo móvel para permitir o acesso ao ", "withOneAccount":" com uma conta.", "addMyEmail":"Adicionar meu e-mail", - "remindMeLater":"Lembre-me mais tarde" + "remindMeLater":"Lembre-me mais tarde", + "addMyEmailToMyProfile":"Adicionar meu e-mail ao meu perfil", + "addYourEmailToYourProfileToEnableYouToAccessThe" : "Adicione seu e-mail ao seu perfil para permitir o acesso ao ", + "accessDeeperAirQualityInsights":"acesso a insights mais profundos sobre a qualidade do ar", + "usingYourAirQoMobileAppAccount":"Usando sua conta do aplicativo móvel AirQo" } \ No newline at end of file diff --git a/mobile/lib/l10n/app_sw.arb b/mobile/lib/l10n/app_sw.arb index 7e35bf05f2..8762c4187c 100644 --- a/mobile/lib/l10n/app_sw.arb +++ b/mobile/lib/l10n/app_sw.arb @@ -354,5 +354,9 @@ "youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe":" Utahitajika kuongeza barua pepe yako kwenye wasifu wako kwenye programu ya simu ili kukuwezesha kufikia ", "withOneAccount":" na akaunti moja.", "addMyEmail":"Ongeza barua pepe yangu", - "remindMeLater":"Nikumbushe baadaye" + "remindMeLater":"Nikumbushe baadaye", + "addMyEmailToMyProfile":"Ongeza barua pepe yangu kwenye wasifu wangu", + "addYourEmailToYourProfileToEnableYouToAccessThe" : "Ongeza barua pepe yako kwenye wasifu wako ili uweze kufikia ", + "accessDeeperAirQualityInsights":"fikia maelezo zaidi ya ubora wa hewa", + "usingYourAirQoMobileAppAccount":"Kwa kutumia akaunti yako ya programu ya simu ya AirQo" } \ No newline at end of file diff --git a/mobile/lib/screens/email_link/email_link_page.dart b/mobile/lib/screens/email_link/email_link_page.dart index ee5878027e..de1d961f69 100644 --- a/mobile/lib/screens/email_link/email_link_page.dart +++ b/mobile/lib/screens/email_link/email_link_page.dart @@ -17,7 +17,7 @@ Future bottomSheetEmailLink(BuildContext context) async { bool shouldShowBottomSheet = true; int remindMeLaterTimestamp = prefs.getInt('remindMeLaterTimestamp') ?? 0; - if (remindMeLaterTimestamp > 0) { + if (remindMeLaterTimestamp > 3) { DateTime lastRemindTimestamp = DateTime.fromMillisecondsSinceEpoch(remindMeLaterTimestamp); DateTime now = DateTime.now(); @@ -84,7 +84,8 @@ Future bottomSheetEmailLink(BuildContext context) async { width: 295.53, height: 67, child: AutoSizeText( - AppLocalizations.of(context)!.weAreShufflingThingsAroundForYou, + AppLocalizations.of(context)! + .weAreShufflingThingsAroundForYou, textAlign: TextAlign.center, style: TextStyle( color: CustomColors.quizColorBlack, @@ -101,8 +102,9 @@ Future bottomSheetEmailLink(BuildContext context) async { textAlign: TextAlign.center, text: TextSpan( children: [ - TextSpan( - text:AppLocalizations.of(context)!.youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe, + TextSpan( + text: AppLocalizations.of(context)! + .youWouldBeRequiredToAddYourEmailToYourProfileOnTheMobileAppToEnableYouAccessThe, style: const TextStyle( color: Color(0xFF485972), fontSize: 13.24, @@ -131,8 +133,9 @@ Future bottomSheetEmailLink(BuildContext context) async { } }, ), - TextSpan( - text: AppLocalizations.of(context)!.withOneAccount, + TextSpan( + text: AppLocalizations.of(context)! + .withOneAccount, style: const TextStyle( color: Color(0xFF485972), fontSize: 13.24, @@ -152,7 +155,7 @@ Future bottomSheetEmailLink(BuildContext context) async { }, )); }, - child: EmailLinkActionButton( + child: EmailLinkActionButton( text: AppLocalizations.of(context)!.addMyEmail, ), ), @@ -165,7 +168,7 @@ Future bottomSheetEmailLink(BuildContext context) async { DateTime.now().millisecondsSinceEpoch, ); }, - child: EmailLinkSkipButton( + 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 index afba462c60..2b9b6f0ba0 100644 --- a/mobile/lib/screens/email_link/email_link_widgets.dart +++ b/mobile/lib/screens/email_link/email_link_widgets.dart @@ -9,6 +9,7 @@ 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({ @@ -115,7 +116,7 @@ class EmailLinkErrorMessage extends StatelessWidget { ), Expanded( child: AutoSizeText( - 'Your Email is already registered ', + AppLocalizations.of(context)!.yourEmailIsAlreadyRegistered, maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, @@ -189,12 +190,20 @@ class SkipLinkButtons extends StatelessWidget { children: [ const SizedBox(height: 8), GestureDetector( - onTap: () { - Navigator.push( + onTap: () async { + SharedPreferences prefs = + await SharedPreferences.getInstance(); + prefs.setInt( + 'remindMeLaterTimestamp', + DateTime.now().millisecondsSinceEpoch, + ); + Navigator.pop(context); + Navigator.pushAndRemoveUntil( context, - MaterialPageRoute( - builder: (context) => const HomePage(), - ), + MaterialPageRoute(builder: (context) { + return const HomePage(); + }), + (r) => true, ); }, child: Text( diff --git a/mobile/lib/screens/home_page.dart b/mobile/lib/screens/home_page.dart index 890a81d0e1..8d19ef881f 100644 --- a/mobile/lib/screens/home_page.dart +++ b/mobile/lib/screens/home_page.dart @@ -250,7 +250,6 @@ class _HomePageState extends State { } else if (user.isAnonymous) { return; } - await Future.delayed(const Duration(seconds: 2)); if (mounted) { await bottomSheetEmailLink(context); } diff --git a/mobile/lib/screens/profile/profile_view.dart b/mobile/lib/screens/profile/profile_view.dart index 290b8d59ea..c334e3d782 100644 --- a/mobile/lib/screens/profile/profile_view.dart +++ b/mobile/lib/screens/profile/profile_view.dart @@ -1,5 +1,6 @@ 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'; @@ -14,6 +15,16 @@ 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) { @@ -24,9 +35,15 @@ class ProfileView extends StatelessWidget { appBar: ProfileViewAppBar(profile), body: AppSafeArea( horizontalPadding: 16, - child: Column( + child: ListView( children: [ const SizedBox(height: 10), + //TODO new feature loading + Visibility( + visible: showLinkAccountReminder, + child: const LinkAccountReminder(), + ), + const SizedBox(height: 6), ProfileSection(profile), const SizedBox(height: 16), CardSection( @@ -37,7 +54,7 @@ class ProfileView extends StatelessWidget { isBottomItem: true, isTopItem: true, ), - const Spacer(), + const SizedBox(height: 10), const SignOutButton(), const SizedBox(height: 10), ], diff --git a/mobile/lib/screens/profile/profile_widgets.dart b/mobile/lib/screens/profile/profile_widgets.dart index 0e3f08ed11..82b26e0cb7 100644 --- a/mobile/lib/screens/profile/profile_widgets.dart +++ b/mobile/lib/screens/profile/profile_widgets.dart @@ -3,6 +3,7 @@ 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'; @@ -10,12 +11,15 @@ 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'; @@ -1080,3 +1084,128 @@ class GuestProfileView extends StatelessWidget { ); } } + +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: Text( + 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, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index f118f116a8..4a8cae025c 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -317,10 +317,10 @@ packages: dependency: transitive description: name: coverage - sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" + sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" url: "https://pub.dev" source: hosted - version: "1.6.4" + version: "1.7.2" cross_file: dependency: transitive description: @@ -1133,6 +1133,30 @@ packages: url: "https://pub.dev" source: hosted version: "6.7.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -1161,26 +1185,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mime: dependency: transitive description: @@ -1265,10 +1289,10 @@ packages: dependency: "direct main" description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_parsing: dependency: transitive description: @@ -1878,10 +1902,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "11.10.0" + version: "13.0.0" watcher: dependency: transitive description: @@ -1890,14 +1914,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 - url: "https://pub.dev" - source: hosted - version: "0.3.0" web_socket_channel: dependency: transitive description: