From c2df7f251261d3d445a0287ecdc60bf7d22feae0 Mon Sep 17 00:00:00 2001 From: Lucas Delanier Date: Mon, 14 Aug 2023 23:12:44 +0200 Subject: [PATCH] change password --- .../justMUSIC/assets/images/password_icon.png | Bin 0 -> 3503 bytes Sources/justMUSIC/lib/config/routes.dart | 19 ++ .../lib/screens/change_password_screen.dart | 307 ++++++++++++++++++ .../justMUSIC/lib/screens/profile_screen.dart | 9 + .../justMUSIC/lib/screens/user_screen.dart | 6 +- Sources/justMUSIC/lib/values/icons.dart | 6 +- 6 files changed, 343 insertions(+), 4 deletions(-) create mode 100644 Sources/justMUSIC/assets/images/password_icon.png create mode 100644 Sources/justMUSIC/lib/screens/change_password_screen.dart diff --git a/Sources/justMUSIC/assets/images/password_icon.png b/Sources/justMUSIC/assets/images/password_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..769b019646f9789fd315055040f5e07ad43514ec GIT binary patch literal 3503 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 Xx(8s2$F}G971J#<8`EZE_muwyUHQbb literal 0 HcmV?d00001 diff --git a/Sources/justMUSIC/lib/config/routes.dart b/Sources/justMUSIC/lib/config/routes.dart index 1c4ed4b..a9f0df0 100644 --- a/Sources/justMUSIC/lib/config/routes.dart +++ b/Sources/justMUSIC/lib/config/routes.dart @@ -1,5 +1,6 @@ import 'package:flutter/Material.dart'; import 'package:justmusic/screens/add_friend_screen.dart'; +import 'package:justmusic/screens/change_password_screen.dart'; import 'package:justmusic/screens/feed_screen.dart'; import 'package:justmusic/screens/profile_screen.dart'; import 'package:justmusic/screens/user_screen.dart'; @@ -71,3 +72,21 @@ Route routeUser(User user) { }, ); } + +Route routePassword() { + return PageRouteBuilder( + pageBuilder: (context, animation, secondaryAnimation) => const ChangePasswordScreen(), + transitionsBuilder: (context, animation, secondaryAnimation, child) { + const begin = Offset(1.0, 0.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, + ); + }, + ); +} diff --git a/Sources/justMUSIC/lib/screens/change_password_screen.dart b/Sources/justMUSIC/lib/screens/change_password_screen.dart new file mode 100644 index 0000000..0965a74 --- /dev/null +++ b/Sources/justMUSIC/lib/screens/change_password_screen.dart @@ -0,0 +1,307 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +import 'package:flutter/Material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/main.dart'; + +import '../values/constants.dart'; + +class ChangePasswordScreen extends StatefulWidget { + const ChangePasswordScreen({super.key}); + + @override + State createState() => _ChangePasswordScreenState(); +} + +class _ChangePasswordScreenState extends State { + final _currentPasswordTextField = TextEditingController(); + final _newPasswordTextField = TextEditingController(); + final _confirmPasswordTextField = TextEditingController(); + final _formKey = GlobalKey(); + Future resetFullScreen() async { + await SystemChannels.platform.invokeMethod( + 'SystemChrome.restoreSystemUIOverlays', + ); + } + + handleChange() async { + print("test"); + if (_formKey.currentState!.validate()) { + var error; + try { + await FirebaseAuth.instance.signInWithEmailAndPassword( + email: MyApp.userViewModel.userCurrent.mail, + password: _currentPasswordTextField.text, + ); + if (_newPasswordTextField.text == _confirmPasswordTextField.text) { + await FirebaseAuth.instance.currentUser?.updatePassword(_confirmPasswordTextField.text); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + "Mot de passe mis à jour", + style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w400, fontSize: 15.h), + ), + backgroundColor: primaryColor, + closeIconColor: Colors.white, + ), + ); + } else { + throw FirebaseAuthException(code: "not-same", message: "Les mots de passe ne correspondent pas"); + } + } on FirebaseAuthException catch (e) { + if (e.code == "wrong-password") { + error = "Mot de passe incorrect"; + } else if (e.code == "too-many-requests") { + error = "Trop de tentatives infructueuses. Veuillez réessayer plus tard"; + } else if (e.code == "channel-error") { + error = "Impossible de vérifier le mot de passe"; + } else if (e.code == "weak-password") { + error = "Le mot de passe doit contenir 6 caractères minimum"; + } + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + error ?? e.message, + style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w400, fontSize: 15.h), + ), + backgroundColor: Colors.red, + closeIconColor: Colors.white, + ), + ); + } + setState(() { + _currentPasswordTextField.clear(); + _newPasswordTextField.clear(); + _confirmPasswordTextField.clear(); + }); + } + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + resetFullScreen(); + } + }, + child: Scaffold( + appBar: PreferredSize( + preferredSize: Size(double.infinity, 58), + child: Container( + height: double.infinity, + color: bgAppBar, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: defaultPadding), + child: Stack( + alignment: Alignment.centerLeft, + children: [ + GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + Navigator.pop(context, true); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + height: 30, + width: 30, + child: Image( + image: AssetImage("assets/images/return_icon.png"), + height: 8, + ), + )), + Align( + child: Text( + "Mettre le mot de passe à jour", + style: + GoogleFonts.plusJakartaSans(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold), + ), + ) + ], + ), + ), + ), + ), + body: Container( + width: double.infinity, + height: double.infinity, + color: bgColor, + child: SingleChildScrollView( + physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: settingPadding), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 30, bottom: 40), + child: SizedBox( + width: double.infinity, + child: Form( + key: _formKey, + child: Stack( + alignment: Alignment.center, + children: [ + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Padding( + padding: const EdgeInsets.only(right: 10), + child: Text( + "Mot de passe actuel", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontWeight: FontWeight.w800, fontSize: 16), + ), + )), + Expanded( + child: TextFormField( + controller: _currentPasswordTextField, + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + // Hides the border when you click the TextField + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + // Hides the border when the TextField is disabled + disabledBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + filled: true, + hintText: '6 caractères minimum', + hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)), + maxLines: 1, + obscureText: true, + cursorColor: primaryColor, + style: GoogleFonts.plusJakartaSans( + color: grayText, fontWeight: FontWeight.w400, fontSize: 16), + ), + ), + ], + ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Padding( + padding: const EdgeInsets.only(right: 10), + child: Text( + "Nouveau mot de passe", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontWeight: FontWeight.w800, fontSize: 16), + ), + )), + Expanded( + child: TextField( + controller: _newPasswordTextField, + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + // Hides the border when you click the TextField + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + // Hides the border when the TextField is disabled + disabledBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + filled: true, + hintText: '6 caractères minimum', + hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)), + maxLines: 1, + obscureText: true, + cursorColor: primaryColor, + style: GoogleFonts.plusJakartaSans( + color: grayText, fontWeight: FontWeight.w400, fontSize: 16), + ), + ), + ], + ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Padding( + padding: const EdgeInsets.only(right: 10), + child: Text( + "Confirmer", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontWeight: FontWeight.w800, fontSize: 16), + ), + )), + Expanded( + child: TextField( + obscureText: true, + controller: _confirmPasswordTextField, + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + // Hides the border when you click the TextField + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + // Hides the border when the TextField is disabled + disabledBorder: OutlineInputBorder( + borderSide: const BorderSide(color: Colors.transparent), + ), + filled: true, + hintText: '6 caractères minimum', + hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)), + maxLines: 1, + cursorColor: primaryColor, + style: GoogleFonts.plusJakartaSans( + color: grayText, fontWeight: FontWeight.w400, fontSize: 16), + ), + ), + ], + ), + ], + ) + ], + ), + ), + ), + ), + GestureDetector( + onTap: handleChange, + child: Align( + child: Container( + height: 35, + width: 160, + decoration: + BoxDecoration(color: primaryColor, borderRadius: BorderRadius.all(Radius.circular(10))), + child: Center( + child: Text( + "Mettre à jour", + style: GoogleFonts.plusJakartaSans(color: Colors.white), + ), + ), + ), + ), + ) + ], + ), + ), + ), + ), + )); + } +} diff --git a/Sources/justMUSIC/lib/screens/profile_screen.dart b/Sources/justMUSIC/lib/screens/profile_screen.dart index 1a5fafe..ab9835d 100644 --- a/Sources/justMUSIC/lib/screens/profile_screen.dart +++ b/Sources/justMUSIC/lib/screens/profile_screen.dart @@ -30,6 +30,10 @@ class _ProfileScreenState extends State { Navigator.of(context).push(routeUser(MyApp.userViewModel.userCurrent)); } + void _openPassword() { + Navigator.of(context).push(routePassword()); + } + return Scaffold( appBar: PreferredSize( preferredSize: Size(double.infinity, 58), @@ -113,6 +117,11 @@ class _ProfileScreenState extends State { label: 'Lier un compte Spotify', action: null, ), + SettingPartComponent( + icon: JustMusicIcon.password, + label: 'Modifier mon mot de passe', + action: _openPassword, + ), const SettingPartComponent( icon: JustMusicIcon.trash, label: 'Supprimer mon compte', diff --git a/Sources/justMUSIC/lib/screens/user_screen.dart b/Sources/justMUSIC/lib/screens/user_screen.dart index 4ee6494..30eb974 100644 --- a/Sources/justMUSIC/lib/screens/user_screen.dart +++ b/Sources/justMUSIC/lib/screens/user_screen.dart @@ -1,5 +1,7 @@ import 'dart:io'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/Material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; @@ -10,11 +12,11 @@ import 'package:image_picker/image_picker.dart'; import '../components/profile_component.dart'; import '../components/recap_component.dart'; import '../main.dart'; -import '../model/User.dart'; +import '../model/User.dart' as UserJstMusic; import '../values/constants.dart'; class UserScreen extends StatefulWidget { - final User user; + final UserJstMusic.User user; const UserScreen({super.key, required this.user}); @override diff --git a/Sources/justMUSIC/lib/values/icons.dart b/Sources/justMUSIC/lib/values/icons.dart index 1cd01d1..f08140b 100644 --- a/Sources/justMUSIC/lib/values/icons.dart +++ b/Sources/justMUSIC/lib/values/icons.dart @@ -5,7 +5,8 @@ enum JustMusicIcon { cross, history, theme, - notification + notification, + password, } extension MyIconExtension on JustMusicIcon { @@ -25,7 +26,8 @@ extension MyIconExtension on JustMusicIcon { return 'assets/images/theme_icon.png'; case JustMusicIcon.notification: return 'assets/images/notification_icon.png'; - + case JustMusicIcon.password: + return 'assets/images/password_icon.png'; default: throw 'assets/images/unknown.png'; }