diff --git a/Sources/justMUSIC/assets/images/plane_icon.png b/Sources/justMUSIC/assets/images/plane_icon.png new file mode 100644 index 0000000..9283f00 Binary files /dev/null and b/Sources/justMUSIC/assets/images/plane_icon.png differ diff --git a/Sources/justMUSIC/lib/main.dart b/Sources/justMUSIC/lib/main.dart index bcba65c..45e9b19 100644 --- a/Sources/justMUSIC/lib/main.dart +++ b/Sources/justMUSIC/lib/main.dart @@ -16,6 +16,7 @@ import 'package:justmusic/screens/launching_rocker_screen.dart'; import 'package:justmusic/screens/post_screen.dart'; import 'package:justmusic/screens/profile_screen.dart'; import 'package:justmusic/screens/registration_screen.dart'; +import 'package:justmusic/screens/verify_email_screen.dart'; import 'package:justmusic/screens/welcome_screen.dart'; import 'package:justmusic/view_model/CommentViewModel.dart'; import 'package:justmusic/view_model/MusicViewModel.dart'; @@ -100,6 +101,7 @@ class _MyAppState extends State { '/explanation': (context) => const ExplanationsScreen(), '/addFriend': (context) => const AddFriendScreen(), '/launchingRocket': (context) => const LaunchingRocketScreen(), + '/verifyEmail': (context) => const VerifyEmailScreen(), }, debugShowCheckedModeBanner: false, theme: ThemeData( diff --git a/Sources/justMUSIC/lib/screens/registration_screen.dart b/Sources/justMUSIC/lib/screens/registration_screen.dart index f0ada00..9ff5692 100644 --- a/Sources/justMUSIC/lib/screens/registration_screen.dart +++ b/Sources/justMUSIC/lib/screens/registration_screen.dart @@ -31,7 +31,7 @@ class _RegistrationScreenState extends State { if (_formKey.currentState!.validate()) { try { await MyApp.userViewModel.register(_userPseudoTextField.text, _passwordTextField.text, _userMailTextField.text); - Navigator.pushNamed(context, '/explanation'); + Navigator.pushNamed(context, '/verifyEmail'); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -369,7 +369,7 @@ class _RegistrationScreenState extends State { borderRadius: BorderRadius.circular(10.0), child: LinearProgressIndicator( minHeight: 5, - value: 0.5, + value: 0.1, backgroundColor: grayColor, color: primaryColor, ), diff --git a/Sources/justMUSIC/lib/screens/verify_email_screen.dart b/Sources/justMUSIC/lib/screens/verify_email_screen.dart new file mode 100644 index 0000000..6d964e9 --- /dev/null +++ b/Sources/justMUSIC/lib/screens/verify_email_screen.dart @@ -0,0 +1,212 @@ +import 'dart:async'; + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/Material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/main.dart'; +import 'package:justmusic/values/constants.dart'; + +import '../components/login_button.dart'; + +class VerifyEmailScreen extends StatefulWidget { + const VerifyEmailScreen({Key? key}) : super(key: key); + + @override + State createState() => _VerifyEmailScreenState(); +} + +class _VerifyEmailScreenState extends State { + bool isEmailVerified = false; + bool canResendEmail = false; + Timer? timer; + + @override + void initState() { + super.initState(); + + isEmailVerified = FirebaseAuth.instance.currentUser!.emailVerified; + + if (!isEmailVerified) { + sendVerificationEmail(); + + timer = Timer.periodic( + Duration(seconds: 5), + (_) => checkEmailVerified(), + ); + } + } + + @override + void dispose() { + timer?.cancel(); + + super.dispose(); + } + + Future checkEmailVerified() async { + await FirebaseAuth.instance.currentUser!.reload(); + + setState(() { + isEmailVerified = FirebaseAuth.instance.currentUser!.emailVerified; + }); + + if (isEmailVerified) { + timer?.cancel(); + Navigator.pushNamed(context, '/explanation'); + } + } + + cancel() { + Navigator.pushNamed(context, '/register'); + MyApp.userViewModel.delete(); + } + + Future sendVerificationEmail() async { + try { + final user = FirebaseAuth.instance.currentUser!; + await user.sendEmailVerification(); + + setState(() => canResendEmail = false); + await Future.delayed(Duration(minutes: 1)); + setState(() => canResendEmail = true); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + e.toString() ?? "", + style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w400, fontSize: 20.h), + ), + backgroundColor: Colors.red, + ), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: bgColor, + body: Stack( + children: [ + SingleChildScrollView( + child: SizedBox( + width: double.infinity, + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 200.h), + child: Align( + child: SizedBox( + width: 56.h, + child: Image(image: AssetImage("assets/images/plane_icon.png")), + ), + )), + Padding( + padding: EdgeInsets.only(top: 43.h), + child: AutoSizeText( + "Verification de ton Email", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontWeight: FontWeight.w600, fontSize: 24.w), + maxLines: 1, + maxFontSize: 30, + overflow: TextOverflow.fade, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: defaultPadding), + child: Padding( + padding: EdgeInsets.only(bottom: 50.h), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + height: 15.h, + ), + SizedBox( + width: 346.h, + child: AutoSizeText( + "Nous vous avons envoyé un lien de confirmation a l'adresse ${MyApp.userViewModel.userCurrent.mail}.\nVeuillez verifier votre messagerie et cliquer sur le lien pour vérifier votre Email.", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontWeight: FontWeight.w100, fontSize: 16.w), + maxFontSize: 20, + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: defaultPadding), + child: SizedBox( + width: 600, + child: LoginButton( + callback: checkEmailVerified, + )), + ), + Align( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + canResendEmail ? sendVerificationEmail() : null; + }, + child: Padding( + padding: EdgeInsets.only(top: 55), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: 'Renvoyer l’Email de confirmation', + style: GoogleFonts.plusJakartaSans( + fontSize: 15, fontWeight: FontWeight.w400, color: primaryColor), + ), + ), + ), + ), + ), + Align( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + cancel(); + }, + child: Padding( + padding: EdgeInsets.only(top: 43), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: 'Revenir a l’étape précédente', + style: GoogleFonts.plusJakartaSans( + fontSize: 15, fontWeight: FontWeight.w400, color: primaryColor), + ), + ), + ), + ), + ), + ], + ), + ), + ), + Align( + alignment: Alignment.topCenter, + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 800), + child: Padding( + padding: EdgeInsets.only(top: 45.h, left: defaultPadding, right: defaultPadding), + child: ClipRRect( + borderRadius: BorderRadius.circular(10.0), + child: LinearProgressIndicator( + minHeight: 5, + value: 0.5, + backgroundColor: grayColor, + color: primaryColor, + ), + ), + ), + ), + ) + ], + )); + } +} diff --git a/Sources/justMUSIC/lib/services/AuthService.dart b/Sources/justMUSIC/lib/services/AuthService.dart index 79bb717..b668fba 100644 --- a/Sources/justMUSIC/lib/services/AuthService.dart +++ b/Sources/justMUSIC/lib/services/AuthService.dart @@ -103,7 +103,6 @@ class AuthService { await currentUser?.delete(); await FirebaseAuth.instance.signOut(); - } on FirebaseAuthException catch (e) { if (e.code == 'requires-recent-login') { throw ('Please log in again to delete your account'); diff --git a/Sources/justMUSIC/lib/view_model/UserViewModel.dart b/Sources/justMUSIC/lib/view_model/UserViewModel.dart index 34278f2..6bc8452 100644 --- a/Sources/justMUSIC/lib/view_model/UserViewModel.dart +++ b/Sources/justMUSIC/lib/view_model/UserViewModel.dart @@ -35,13 +35,17 @@ class UserViewModel { try { var token; await authService.login(pseudo, password); - await updateUserCurrent(); - if (!kIsWeb) { - token = await FirebaseMessaging.instance.getToken(); - if (_userCurrent.token != token) { - _userService.updateTokenNotify(_userCurrent.id, token); - _userCurrent.token = token; + if (firebase_auth.FirebaseAuth.instance.currentUser!.emailVerified) { + await updateUserCurrent(); + if (!kIsWeb) { + token = await FirebaseMessaging.instance.getToken(); + if (_userCurrent.token != token) { + _userService.updateTokenNotify(_userCurrent.id, token); + _userCurrent.token = token; + } } + } else { + throw ("Le mail n'a pas encore été vérifié"); } } catch (e) { rethrow;