diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index 12381d1..5d474aa 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -1,540 +1,828 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sources/justMUSIC/.metadata b/Sources/justMUSIC/.metadata index e1179a6..771b2ad 100644 --- a/Sources/justMUSIC/.metadata +++ b/Sources/justMUSIC/.metadata @@ -1,45 +1,30 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled. - -version: - revision: 18a827f3933c19f51862dde3fa472197683249d6 - channel: stable - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 - - platform: android - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 - - platform: ios - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 - - platform: linux - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 - - platform: macos - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 - - platform: web - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 - - platform: windows - create_revision: 18a827f3933c19f51862dde3fa472197683249d6 - base_revision: 18a827f3933c19f51862dde3fa472197683249d6 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + - platform: android + create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/Sources/justMUSIC/android/app/build.gradle b/Sources/justMUSIC/android/app/build.gradle index 2c71df3..97e5ae2 100644 --- a/Sources/justMUSIC/android/app/build.gradle +++ b/Sources/justMUSIC/android/app/build.gradle @@ -1,71 +1,78 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion 33 - ndkVersion flutter.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.justmusic" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} +def localProperties = new Properties() + +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + namespace "com.example.justmusic" + compileSdkVersion 33 + ndkVersion flutter.ndkVersion + + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.justmusic" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion 19 + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation(platform("com.google.firebase:firebase-bom:32.2.0")) + implementation 'com.google.firebase:firebase-analytics-ktx' +} +apply plugin: 'com.google.gms.google-services' diff --git a/Sources/justMUSIC/android/app/google-services.json b/Sources/justMUSIC/android/app/google-services.json new file mode 100644 index 0000000..4764602 --- /dev/null +++ b/Sources/justMUSIC/android/app/google-services.json @@ -0,0 +1,46 @@ +{ + "project_info": { + "project_number": "994903990520", + "project_id": "justmusic-435d5", + "storage_bucket": "justmusic-435d5.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:994903990520:android:02a445b6561bf2820a9b0d", + "android_client_info": { + "package_name": "com.example.justmusic" + } + }, + "oauth_client": [ + { + "client_id": "994903990520-rdk6ldrmbi71ddqt84qfhtuficm7ngon.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCjkofl0nvfzQqRZPv_-H99WoyYa7O660g" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "994903990520-9jsnq9ipdn7smk7tlbdd20i7j6sl3jcd.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "994903990520-n6jd98ena56kb1tvtrd67tvb5et3nfbf.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.example.justmusic" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml b/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml index ea3a368..d63318f 100644 --- a/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml +++ b/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml @@ -1,34 +1,35 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/Sources/justMUSIC/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java b/Sources/justMUSIC/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java new file mode 100644 index 0000000..7ab3f6d --- /dev/null +++ b/Sources/justMUSIC/android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java @@ -0,0 +1,25 @@ +// Generated file. +// +// If you wish to remove Flutter's multidex support, delete this entire file. +// +// Modifications to this file should be done in a copy under a different name +// as this file may be regenerated. + +package io.flutter.app; + +import android.app.Application; +import android.content.Context; +import androidx.annotation.CallSuper; +import androidx.multidex.MultiDex; + +/** + * Extension of {@link android.app.Application}, adding multidex support. + */ +public class FlutterMultiDexApplication extends Application { + @Override + @CallSuper + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + MultiDex.install(this); + } +} diff --git a/Sources/justMUSIC/android/app/src/profile/AndroidManifest.xml b/Sources/justMUSIC/android/app/src/profile/AndroidManifest.xml index 44a649b..a5cc1f7 100644 --- a/Sources/justMUSIC/android/app/src/profile/AndroidManifest.xml +++ b/Sources/justMUSIC/android/app/src/profile/AndroidManifest.xml @@ -1,8 +1,9 @@ - - - - + + + + + \ No newline at end of file diff --git a/Sources/justMUSIC/android/build.gradle b/Sources/justMUSIC/android/build.gradle index 36cfe3f..c0f45cf 100644 --- a/Sources/justMUSIC/android/build.gradle +++ b/Sources/justMUSIC/android/build.gradle @@ -1,31 +1,32 @@ -buildscript { - ext.kotlin_version = '1.9.0' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} +buildscript { + ext.kotlin_version = '1.9.0' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.2' + classpath 'com.google.gms:google-services:4.3.15' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/Sources/justMUSIC/android/gradle/wrapper/gradle-wrapper.properties b/Sources/justMUSIC/android/gradle/wrapper/gradle-wrapper.properties index cb24abd..eabb85f 100644 --- a/Sources/justMUSIC/android/gradle/wrapper/gradle-wrapper.properties +++ b/Sources/justMUSIC/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/Sources/justMUSIC/ios/Runner/GoogleService-Info.plist b/Sources/justMUSIC/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..d67674a --- /dev/null +++ b/Sources/justMUSIC/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,34 @@ + + + + + CLIENT_ID + 994903990520-n6jd98ena56kb1tvtrd67tvb5et3nfbf.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.994903990520-n6jd98ena56kb1tvtrd67tvb5et3nfbf + API_KEY + AIzaSyBbYqsR6t7JTi8_XFNEHd43IRuKlYGeI3U + GCM_SENDER_ID + 994903990520 + PLIST_VERSION + 1 + BUNDLE_ID + com.example.justmusic + PROJECT_ID + justmusic-435d5 + STORAGE_BUCKET + justmusic-435d5.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:994903990520:ios:93188f32e320babe0a9b0d + + \ No newline at end of file diff --git a/Sources/justMUSIC/ios/firebase_app_id_file.json b/Sources/justMUSIC/ios/firebase_app_id_file.json new file mode 100644 index 0000000..dd5eb02 --- /dev/null +++ b/Sources/justMUSIC/ios/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:994903990520:ios:93188f32e320babe0a9b0d", + "FIREBASE_PROJECT_ID": "justmusic-435d5", + "GCM_SENDER_ID": "994903990520" +} \ No newline at end of file diff --git a/Sources/justMUSIC/lib/components/login_button.dart b/Sources/justMUSIC/lib/components/login_button.dart index 3e41e8e..6a41d9c 100644 --- a/Sources/justMUSIC/lib/components/login_button.dart +++ b/Sources/justMUSIC/lib/components/login_button.dart @@ -1,66 +1,68 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class LoginButton extends StatefulWidget { - const LoginButton({Key? key}) : super(key: key); - - @override - State createState() => _LoginButtonState(); -} - -class _LoginButtonState extends State { - @override - Widget build(BuildContext context) { - return ElevatedButton( - onPressed: () { - Navigator.pushNamed(context, '/explanation'); - }, - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(Color(0xFF1C1C1C)), - overlayColor: - MaterialStateProperty.all(Color(0xffD3C2FF).withOpacity(0.2)), - shape: MaterialStateProperty.all(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18), - )), - padding: MaterialStateProperty.all(EdgeInsets.all(0.0)), - ), - child: Ink( - decoration: BoxDecoration( - gradient: RadialGradient( - center: Alignment(0, 3), - focalRadius: 10, - radius: 2.5, - stops: [0.4, 1.0], - colors: [Color(0xff9E78FF), Color(0xff633AF4)], - ), - borderRadius: BorderRadius.circular(18.0), - border: Border.all( - color: Color(0xff1C1C1C), - width: 5, - ), - ), - child: Container( - padding: EdgeInsets.only(top: 20.h, bottom: 20.h), - constraints: BoxConstraints(maxWidth: 600, minHeight: 50), - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Color(0xff7E56F9).withOpacity(0.23), - spreadRadius: 4, - blurRadius: 40, - offset: Offset(0, 3), // changes position of shadow - ), - ], - ), - alignment: Alignment.center, - child: Text( - "Se connecter", - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white, fontSize: 18), - ), - ), - ), - ); - } -} +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LoginButton extends StatefulWidget { + final Function callback; + + const LoginButton({Key? key, required this.callback}) : super(key: key); + + @override + State createState() => _LoginButtonState(); +} + +class _LoginButtonState extends State { + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: () { + widget.callback(); + }, + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(Color(0xFF1C1C1C)), + overlayColor: + MaterialStateProperty.all(Color(0xffD3C2FF).withOpacity(0.2)), + shape: MaterialStateProperty.all(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + )), + padding: MaterialStateProperty.all(EdgeInsets.all(0.0)), + ), + child: Ink( + decoration: BoxDecoration( + gradient: RadialGradient( + center: Alignment(0, 3), + focalRadius: 10, + radius: 2.5, + stops: [0.4, 1.0], + colors: [Color(0xff9E78FF), Color(0xff633AF4)], + ), + borderRadius: BorderRadius.circular(18.0), + border: Border.all( + color: Color(0xff1C1C1C), + width: 5, + ), + ), + child: Container( + padding: EdgeInsets.only(top: 20.h, bottom: 20.h), + constraints: BoxConstraints(maxWidth: 600, minHeight: 50), + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Color(0xff7E56F9).withOpacity(0.23), + spreadRadius: 4, + blurRadius: 40, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + alignment: Alignment.center, + child: Text( + "Se connecter", + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white, fontSize: 18), + ), + ), + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/components/post_button_component.dart b/Sources/justMUSIC/lib/components/post_button_component.dart index 93f75d9..45b2c47 100644 --- a/Sources/justMUSIC/lib/components/post_button_component.dart +++ b/Sources/justMUSIC/lib/components/post_button_component.dart @@ -15,6 +15,12 @@ class _PostButtonComponentState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + @override void initState() { super.initState(); @@ -132,14 +138,11 @@ class _PostButtonComponentState extends State ), )), ClipOval( - child: Positioned( - left: -15, - child: Padding( - padding: const EdgeInsets.only(left: 5, top: 5), - child: Image( - image: AssetImage("assets/images/rocket_button.png"), - height: 65, - ), + child: Padding( + padding: const EdgeInsets.only(left: 5, top: 5), + child: Image( + image: AssetImage("assets/images/rocket_button.png"), + height: 65, ), ), ) diff --git a/Sources/justMUSIC/lib/firebase_options.dart b/Sources/justMUSIC/lib/firebase_options.dart new file mode 100644 index 0000000..7155c8e --- /dev/null +++ b/Sources/justMUSIC/lib/firebase_options.dart @@ -0,0 +1,76 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + return web; + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions web = FirebaseOptions( + apiKey: 'AIzaSyBv-Sba07nFFhctn6c3ARyvi9RfYwEKoNA', + appId: '1:994903990520:web:724c75003432ddbc0a9b0d', + messagingSenderId: '994903990520', + projectId: 'justmusic-435d5', + authDomain: 'justmusic-435d5.firebaseapp.com', + storageBucket: 'justmusic-435d5.appspot.com', + measurementId: 'G-D4YRLXK9TQ', + ); + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyCjkofl0nvfzQqRZPv_-H99WoyYa7O660g', + appId: '1:994903990520:android:02a445b6561bf2820a9b0d', + messagingSenderId: '994903990520', + projectId: 'justmusic-435d5', + storageBucket: 'justmusic-435d5.appspot.com', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyBbYqsR6t7JTi8_XFNEHd43IRuKlYGeI3U', + appId: '1:994903990520:ios:93188f32e320babe0a9b0d', + messagingSenderId: '994903990520', + projectId: 'justmusic-435d5', + storageBucket: 'justmusic-435d5.appspot.com', + iosClientId: '994903990520-n6jd98ena56kb1tvtrd67tvb5et3nfbf.apps.googleusercontent.com', + iosBundleId: 'com.example.justmusic', + ); +} diff --git a/Sources/justMUSIC/lib/main.dart b/Sources/justMUSIC/lib/main.dart index c0c9458..fd68156 100644 --- a/Sources/justMUSIC/lib/main.dart +++ b/Sources/justMUSIC/lib/main.dart @@ -1,62 +1,71 @@ -import 'package:audioplayers/audioplayers.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:justmusic/screens/explanations_screen.dart'; -import 'package:justmusic/screens/feed_screen.dart'; -import 'package:justmusic/screens/login_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/welcome_screen.dart'; -import 'package:justmusic/view_model/MusicViewModel.dart'; -import 'package:justmusic/view_model/UserViewModel.dart'; - -void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - static UserViewModel userViewModel = UserViewModel(); - static MusicViewModel musicViewModel = MusicViewModel(); - static AudioPlayer audioPlayer = AudioPlayer(); - - const MyApp({super.key}); - - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); - Paint.enableDithering = true; - return ScreenUtilInit( - useInheritedMediaQuery: true, - builder: (context, child) { - return MaterialApp( - routes: { - '/welcome': (context) => WellcomeScreen(), - '/feed': (context) => FeedScreen(), - '/login': (context) => LoginScreen(), - '/register': (context) => RegistrationScreen(), - '/post': (context) => PostScreen(), - '/profile': (context) => ProfileScreen(), - '/explanation': (context) => ExplanationsScreen(), - }, - debugShowCheckedModeBanner: false, - theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.blue, - ), - home: WellcomeScreen()); - }, - designSize: Size(390, 844), - ); - } -} +import 'package:audioplayers/audioplayers.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:justmusic/screens/explanations_screen.dart'; +import 'package:justmusic/screens/feed_screen.dart'; +import 'package:justmusic/screens/login_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/welcome_screen.dart'; +import 'package:justmusic/view_model/MusicViewModel.dart'; +import 'package:justmusic/view_model/UserViewModel.dart'; + +import 'firebase_options.dart'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + static FirebaseFirestore db = FirebaseFirestore.instance; + static UserViewModel userViewModel = UserViewModel(); + static MusicViewModel musicViewModel = MusicViewModel(); + static AudioPlayer audioPlayer = AudioPlayer(); + + const MyApp({super.key}); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); + Paint.enableDithering = true; + return ScreenUtilInit( + useInheritedMediaQuery: true, + builder: (context, child) { + return MaterialApp( + routes: { + '/welcome': (context) => WellcomeScreen(), + '/feed': (context) => FeedScreen(), + '/login': (context) => LoginScreen(), + '/register': (context) => RegistrationScreen(), + '/post': (context) => PostScreen(), + '/profile': (context) => ProfileScreen(), + '/explanation': (context) => ExplanationsScreen(), + }, + debugShowCheckedModeBanner: false, + theme: ThemeData( + // This is the theme of your application. + // + // Try running your application with "flutter run". You'll see the + // application has a blue toolbar. Then, without quitting the app, try + // changing the primarySwatch below to Colors.green and then invoke + // "hot reload" (press "r" in the console where you ran "flutter run", + // or simply save your changes to "hot reload" in a Flutter IDE). + // Notice that the counter didn't reset back to zero; the application + // is not restarted. + primarySwatch: Colors.blue, + ), + home: WellcomeScreen()); + }, + designSize: Size(390, 844), + ); + } +} diff --git a/Sources/justMUSIC/lib/model/User.dart b/Sources/justMUSIC/lib/model/User.dart index f601867..0f0bb79 100644 --- a/Sources/justMUSIC/lib/model/User.dart +++ b/Sources/justMUSIC/lib/model/User.dart @@ -1,60 +1,60 @@ -class User { - final int _id; - String _pseudo; - String _country; - String _mail; - String _pp; - int _followers; - int _capsules; - int _followed; - List friends = []; - - // Constructor - User(this._id, this._pseudo, this._country, this._mail, this._pp, - this._followers, this._capsules, this._followed, this.friends); - - //Getters and setters - int get id => _id; - - String get pseudo => _pseudo; - - set pseudo(String value) { - _pseudo = value; - } - - String get country => _country; - - set country(String value) { - _country = value; - } - - String get mail => _mail; - - set mail(String value) { - _mail = value; - } - - String get pp => _pp; - - set pp(String value) { - _pp = value; - } - - int get capsules => _capsules; - - set capsules(int value) { - _capsules = value; - } - - int get followed => _followed; - - set followed(int value) { - _followed = value; - } - - int get followers => _followers; - - set followers(int value) { - _followers = value; - } -} +class User { + final String _id; + String _pseudo; + String _country; + String _mail; + String _pp; + int _followers; + int _capsules; + int _followed; + List friends = []; + + // Constructor + User(this._id, this._pseudo, this._country, this._mail, this._pp, + this._followers, this._capsules, this._followed, this.friends); + + //Getters and setters + String get id => _id; + + String get pseudo => _pseudo; + + set pseudo(String value) { + _pseudo = value; + } + + String get country => _country; + + set country(String value) { + _country = value; + } + + String get mail => _mail; + + set mail(String value) { + _mail = value; + } + + String get pp => _pp; + + set pp(String value) { + _pp = value; + } + + int get capsules => _capsules; + + set capsules(int value) { + _capsules = value; + } + + int get followed => _followed; + + set followed(int value) { + _followed = value; + } + + int get followers => _followers; + + set followers(int value) { + _followers = value; + } +} diff --git a/Sources/justMUSIC/lib/model/mapper/UserMapper.dart b/Sources/justMUSIC/lib/model/mapper/UserMapper.dart new file mode 100644 index 0000000..8ef5bbc --- /dev/null +++ b/Sources/justMUSIC/lib/model/mapper/UserMapper.dart @@ -0,0 +1,31 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:justmusic/model/User.dart'; + +class UserMapper { + static User toModel(DocumentSnapshot> snapshot, + SnapshotOptions? options) { + final data = snapshot.data(); + return User( + data?["uid"] ?? "", + data?["unique_id"] ?? "", + data?["country"] ?? "", + data?["mail"] ?? "", + data?["profilePicture"] ?? "", + data?["followers"] ?? 0, + data?["nbCapsules"] ?? 0, + data?["followed"] ?? 0, + data?['friends'] is List ? List.from(data?['friends']) : []); + } +/* + static Map toFirebase(User user) { + return { + if (user.pseudo != null) "name": u, + if (user.country != null) "state": state, + if (user.mail != null) "country": country, + if (user.pp != null) "capital": capital, + if (user.followers != null) "population": population, + if (user.capsules != null) "regions": regions, + if () + }; + }*/ +} diff --git a/Sources/justMUSIC/lib/screens/login_screen.dart b/Sources/justMUSIC/lib/screens/login_screen.dart index 778d76d..2ca2f03 100644 --- a/Sources/justMUSIC/lib/screens/login_screen.dart +++ b/Sources/justMUSIC/lib/screens/login_screen.dart @@ -1,709 +1,373 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:flutter_signin_button/button_list.dart'; -import 'package:flutter_signin_button/button_view.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/values/constants.dart'; - -import '../components/login_button.dart'; - -class LoginScreen extends StatefulWidget { - const LoginScreen({Key? key}) : super(key: key); - - @override - State createState() => _LoginScreenState(); -} - -class _LoginScreenState extends State { - bool passenable = true; - final _formKey = GlobalKey(); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () => FocusManager.instance.primaryFocus?.unfocus(), - child: Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: bgColor, - body: LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxHeight >= 740) { - return Align( - child: SizedBox( - height: double.infinity, - width: 600, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Padding( - padding: - EdgeInsets.only(left: 40, right: 40), - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - Flexible( - flex: 5, - child: Padding( - padding: - EdgeInsets.only(bottom: 60), - child: Column( - mainAxisAlignment: - MainAxisAlignment.end, - children: [ - Text( - "Te revoilà!", - style: GoogleFonts - .plusJakartaSans( - color: - Colors.white, - fontWeight: - FontWeight - .w600, - fontSize: 38.h), - ), - SizedBox( - height: 10, - ), - SizedBox( - width: 230.w, - child: Text( - "Bon retour parmis nous tu nous as manqué!", - style: GoogleFonts - .plusJakartaSans( - color: Colors - .white, - fontWeight: - FontWeight - .w400, - fontSize: 20.h), - textAlign: - TextAlign.center, - ), - ), - ], - ), - ), - ), - Expanded( - flex: 4, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - TextFormField( - keyboardAppearance: - Brightness.dark, - validator: (value) { - if (value == null || - value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: - TextInputType - .emailAddress, - style: GoogleFonts - .plusJakartaSans( - color: - primaryColor), - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius.all( - Radius.circular( - 10))), - contentPadding: - EdgeInsets.only( - top: 0, - bottom: 0, - left: - defaultPadding), - fillColor: - bgTextField, - filled: true, - focusColor: Color.fromRGBO( - 255, 255, 255, 0.30), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius.all(Radius.circular(10))), - hintText: 'Email', - hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)), - ), - SizedBox( - height: 18, - ), - TextFormField( - keyboardAppearance: - Brightness.dark, - obscureText: passenable, - validator: (value) { - if (value == null || - value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: - TextInputType - .emailAddress, - style: GoogleFonts - .plusJakartaSans( - color: - primaryColor), - decoration: - InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius - .all(Radius - .circular( - 10))), - contentPadding: - EdgeInsets.only( - top: 0, - bottom: 0, - left: - defaultPadding), - fillColor: bgTextField, - filled: true, - focusColor: - Color.fromRGBO(255, - 255, 255, 0.30), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius - .all(Radius - .circular( - 10))), - hintText: - 'Mot de passe', - hintStyle: GoogleFonts - .plusJakartaSans( - color: - strokeTextField), - suffixIcon: Container( - padding: - EdgeInsets.only( - right: 10), - margin: - EdgeInsets.all( - 5), - height: 3, - child: InkWell( - onTap: () { - setState(() { - if (passenable) { - passenable = - false; - } else { - passenable = - true; - } - }); - }, // Image tapped - splashColor: Colors - .white10, // Splash color over image - child: Image( - image: passenable - ? AssetImage( - "assets/images/show_icon.png") - : AssetImage( - "assets/images/hide_icon.png"), - height: 2, - ), - )), - ), - ), - Padding( - padding: EdgeInsets.only( - top: 10), - child: Text( - "Mot de passe oublié?", - style: GoogleFonts - .plusJakartaSans( - color: Colors - .white), - ), - ), - SizedBox( - height: defaultPadding, - ), - SizedBox( - width: 600, - child: LoginButton()), - ], - )), - Expanded( - flex: 3, - child: Padding( - padding: - EdgeInsets.only(top: 20), - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment - .center, - children: [ - ConstrainedBox( - constraints: - BoxConstraints( - maxWidth: 600), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceEvenly, - children: [ - Expanded( - child: Container( - color: Color( - 0xFF3D3D3D), - height: 1, - ), - ), - Padding( - padding: const EdgeInsets - .only( - left: - defaultPadding, - right: - defaultPadding), - child: Text( - 'Ou', - style: GoogleFonts.plusJakartaSans( - color: Colors - .white, - fontWeight: - FontWeight - .bold), - ), - ), - Expanded( - child: - Container( - height: 1, - color: Color( - 0xFF3D3D3D), - )), - ], - ), - ), - SizedBox( - height: - defaultPadding), - SignInButton( - Buttons.Google, - text: - "Login with Google", - onPressed: () {}, - ), - Padding( - padding: - EdgeInsets.only( - top: 20), - child: RichText( - textAlign: - TextAlign.center, - text: TextSpan( - text: - 'Pas encore inscrit?', - style: GoogleFonts - .plusJakartaSans( - color: Colors - .white, - fontWeight: - FontWeight - .w400, - fontSize: - 13), - children: < - TextSpan>[ - TextSpan( - text: - " S’inscire", - style: GoogleFonts.plusJakartaSans( - fontSize: - 13, - fontWeight: - FontWeight - .w400, - color: - primaryColor)), - ], - ), - ), - ) - ], - ), - )) - ], - )))) - ], - )), - ); - } else { - return Align( - child: SizedBox( - height: double.infinity, - width: 600, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Padding( - padding: - EdgeInsets.only(left: 40, right: 40), - child: Form( - key: _formKey, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - Flexible( - flex: 2, - child: Padding( - padding: - EdgeInsets.only(bottom: 30), - child: Column( - mainAxisAlignment: - MainAxisAlignment.end, - children: [ - Text( - "Te revoilà!", - style: GoogleFonts - .plusJakartaSans( - color: - Colors.white, - fontWeight: - FontWeight - .w600, - fontSize: 38.h), - ), - SizedBox( - height: 10, - ), - SizedBox( - width: 230, - child: Text( - "Bon retour parmis nous tu nous as manqué!", - style: GoogleFonts - .plusJakartaSans( - color: Colors - .white, - fontWeight: - FontWeight - .w400, - fontSize: 20.h), - textAlign: - TextAlign.center, - ), - ), - ], - ), - ), - ), - Expanded( - flex: 4, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - TextFormField( - keyboardAppearance: - Brightness.dark, - validator: (value) { - if (value == null || - value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: - TextInputType - .emailAddress, - style: GoogleFonts - .plusJakartaSans( - color: - primaryColor), - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius.all( - Radius.circular( - 10))), - contentPadding: - EdgeInsets.only( - top: 0, - bottom: 0, - left: - defaultPadding), - fillColor: - bgTextField, - filled: true, - focusColor: Color.fromRGBO( - 255, 255, 255, 0.30), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius.all(Radius.circular(10))), - hintText: 'Email', - hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField, fontSize: 15)), - ), - SizedBox( - height: 18, - ), - TextFormField( - keyboardAppearance: - Brightness.dark, - obscureText: passenable, - validator: (value) { - if (value == null || - value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: - TextInputType - .emailAddress, - style: GoogleFonts - .plusJakartaSans( - color: - primaryColor), - decoration: - InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius - .all(Radius - .circular( - 10))), - contentPadding: - EdgeInsets.only( - top: 0, - bottom: 0, - left: - defaultPadding), - fillColor: bgTextField, - filled: true, - focusColor: - Color.fromRGBO(255, - 255, 255, 0.30), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, - color: - strokeTextField), - borderRadius: - BorderRadius - .all(Radius - .circular( - 10))), - hintText: - 'Mot de passe', - hintStyle: GoogleFonts - .plusJakartaSans( - color: - strokeTextField), - suffixIcon: Container( - padding: - EdgeInsets.only( - right: 10), - margin: - EdgeInsets.all( - 5), - height: 3, - child: InkWell( - onTap: () { - setState(() { - if (passenable) { - passenable = - false; - } else { - passenable = - true; - } - }); - }, // Image tapped - splashColor: Colors - .white10, // Splash color over image - child: Image( - image: passenable - ? AssetImage( - "assets/images/show_icon.png") - : AssetImage( - "assets/images/hide_icon.png"), - height: 2, - ), - )), - ), - ), - Padding( - padding: EdgeInsets.only( - top: 10.h), - child: Text( - "Mot de passe oublié?", - style: GoogleFonts - .plusJakartaSans( - color: Colors - .white), - ), - ), - SizedBox( - height: defaultPadding, - ), - SizedBox( - width: 600, - child: LoginButton()), - ], - )), - Expanded( - flex: 3, - child: Padding( - padding: - EdgeInsets.only(top: 20), - child: Column( - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment - .center, - children: [ - ConstrainedBox( - constraints: - BoxConstraints( - maxWidth: 600), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceEvenly, - children: [ - Expanded( - child: Container( - color: Color( - 0xFF3D3D3D), - height: 1, - ), - ), - Padding( - padding: const EdgeInsets - .only( - left: - defaultPadding, - right: - defaultPadding), - child: Text( - 'Ou', - style: GoogleFonts.plusJakartaSans( - color: Colors - .white, - fontWeight: - FontWeight - .bold), - ), - ), - Expanded( - child: - Container( - height: 1, - color: Color( - 0xFF3D3D3D), - )), - ], - ), - ), - SizedBox( - height: - defaultPadding), - SignInButton( - Buttons.Google, - text: - "Login with Google", - onPressed: () {}, - ), - Padding( - padding: - EdgeInsets.only( - top: 20), - child: RichText( - textAlign: - TextAlign.center, - text: TextSpan( - text: - 'Pas encore inscrit?', - style: GoogleFonts - .plusJakartaSans( - color: Colors - .white, - fontWeight: - FontWeight - .w400, - fontSize: - 13), - children: < - TextSpan>[ - TextSpan( - text: - " S’inscire", - style: GoogleFonts.plusJakartaSans( - fontSize: - 13, - fontWeight: - FontWeight - .w400, - color: - primaryColor)), - ], - ), - ), - ) - ], - ), - )) - ], - )))) - ], - )), - ); - } - }, - ))); - } -} +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_signin_button/button_list.dart'; +import 'package:flutter_signin_button/button_view.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 LoginScreen extends StatefulWidget { + const LoginScreen({Key? key}) : super(key: key); + + @override + State createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + bool passenable = true; + final _formKey = GlobalKey(); + final _userMailTextField = TextEditingController(); + final _passwordTextField = TextEditingController(); + + handleLogin() async { + if (_formKey.currentState!.validate()) { + try { + await MyApp.userViewModel + .login(_userMailTextField.text, _passwordTextField.text); + Navigator.pushNamed(context, '/feed'); + } 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 GestureDetector( + onTap: () => FocusManager.instance.primaryFocus?.unfocus(), + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: bgColor, + body: Align( + child: SizedBox( + height: double.infinity, + width: 600, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 40, right: 40), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Flexible( + flex: 4, + child: Padding( + padding: EdgeInsets.only(bottom: 60), + child: Column( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + Text( + "Te revoilà!", + style: + GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: + FontWeight.w600, + fontSize: 38.h), + ), + SizedBox( + height: 10, + ), + SizedBox( + width: 230.w, + child: Text( + "Bon retour parmis nous tu nous as manqué!", + style: GoogleFonts + .plusJakartaSans( + color: Colors.white, + fontWeight: + FontWeight.w400, + fontSize: 20.h), + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ), + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + TextFormField( + controller: _userMailTextField, + keyboardAppearance: + Brightness.dark, + validator: (value) { + if (value == null || + value.isEmpty) { + return 'entrez un email valide'; + } + return null; + }, + cursorColor: primaryColor, + keyboardType: + TextInputType.emailAddress, + style: + GoogleFonts.plusJakartaSans( + color: primaryColor), + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1, + color: + strokeTextField), + borderRadius: BorderRadius.all( + Radius.circular(10))), + prefix: const Padding( + padding: EdgeInsets.only( + left: 20.0)), + suffix: const Padding( + padding: EdgeInsets.only( + left: 20.0)), + fillColor: bgTextField, + filled: true, + errorStyle: TextStyle( + fontSize: 9, height: 0.3), + focusColor: Color.fromRGBO( + 255, 255, 255, 0.30), + enabledBorder: OutlineInputBorder( + borderSide: + BorderSide(width: 1, color: strokeTextField), + borderRadius: BorderRadius.all(Radius.circular(10))), + hintText: 'Email', + hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)), + ), + SizedBox( + height: 18, + ), + TextFormField( + controller: _passwordTextField, + keyboardAppearance: + Brightness.dark, + obscureText: passenable, + validator: (value) { + if (value == null || + value.isEmpty) { + return 'entrez un mot de passe valide'; + } + return null; + }, + cursorColor: primaryColor, + style: + GoogleFonts.plusJakartaSans( + color: primaryColor), + decoration: InputDecoration( + focusedBorder: + OutlineInputBorder( + borderSide: BorderSide( + width: 1, + color: + strokeTextField), + borderRadius: + BorderRadius.all( + Radius.circular( + 10))), + fillColor: bgTextField, + filled: true, + focusColor: Color.fromRGBO( + 255, 255, 255, 0.30), + enabledBorder: + OutlineInputBorder( + borderSide: BorderSide( + width: 1, + color: + strokeTextField), + borderRadius: + BorderRadius.all( + Radius.circular( + 10))), + hintText: 'Mot de passe', + hintStyle: + GoogleFonts.plusJakartaSans( + color: strokeTextField), + prefix: const Padding( + padding: EdgeInsets.only( + left: 20.0)), + suffixIcon: Container( + padding: EdgeInsets.only( + right: 10), + margin: EdgeInsets.all(5), + height: 3, + child: InkWell( + onTap: () { + setState(() { + if (passenable) { + passenable = false; + } else { + passenable = true; + } + }); + }, + // Image tapped + splashColor: + Colors.white10, + // Splash color over image + child: Image( + image: passenable + ? AssetImage( + "assets/images/show_icon.png") + : AssetImage( + "assets/images/hide_icon.png"), + height: 2, + ), + )), + errorStyle: TextStyle( + fontSize: 9, height: 0.3), + ), + ), + Padding( + padding: EdgeInsets.only(top: 10), + child: Text( + "Mot de passe oublié?", + style: + GoogleFonts.plusJakartaSans( + color: Colors.white), + ), + ), + SizedBox( + height: defaultPadding, + ), + SizedBox( + width: 600, + child: LoginButton( + callback: handleLogin, + )), + Align( + child: GestureDetector( + onTap: () { + Navigator.pushNamed( + context, '/register'); + }, + child: Padding( + padding: + EdgeInsets.only(top: 20), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: + 'Pas encore inscrit?', + style: GoogleFonts + .plusJakartaSans( + color: + Colors.white, + fontWeight: + FontWeight + .w400, + fontSize: 15), + children: [ + TextSpan( + text: " S’inscire", + style: GoogleFonts + .plusJakartaSans( + fontSize: + 15, + fontWeight: + FontWeight + .w400, + color: + primaryColor)), + ], + ), + ), + ), + ), + ), + ], + ), + ), + Expanded( + flex: 3, + child: Padding( + padding: EdgeInsets.only(top: 20), + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + ConstrainedBox( + constraints: BoxConstraints( + maxWidth: 600), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceEvenly, + children: [ + Expanded( + child: Container( + color: + Color(0xFF3D3D3D), + height: 1, + ), + ), + Padding( + padding: const EdgeInsets + .only( + left: + defaultPadding, + right: + defaultPadding), + child: Text( + 'Ou', + style: GoogleFonts + .plusJakartaSans( + color: Colors + .white, + fontWeight: + FontWeight + .bold), + ), + ), + Expanded( + child: Container( + height: 1, + color: + Color(0xFF3D3D3D), + )), + ], + ), + ), + SizedBox( + height: defaultPadding), + SignInButton( + Buttons.Google, + text: "Login with Google", + onPressed: () {}, + ), + ], + ), + )) + ], + )))) + ], + )), + ))); + } +} diff --git a/Sources/justMUSIC/lib/screens/registration_screen.dart b/Sources/justMUSIC/lib/screens/registration_screen.dart index 679fd11..e7d9ecc 100644 --- a/Sources/justMUSIC/lib/screens/registration_screen.dart +++ b/Sources/justMUSIC/lib/screens/registration_screen.dart @@ -1,376 +1,458 @@ -import 'dart:ui'; - -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:flutter_signin_button/button_list.dart'; -import 'package:flutter_signin_button/button_view.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/values/constants.dart'; - -import '../components/login_button.dart'; - -class RegistrationScreen extends StatefulWidget { - const RegistrationScreen({Key? key}) : super(key: key); - - @override - State createState() => _RegistrationScreenState(); -} - -class _RegistrationScreenState extends State { - bool passenable = true; - - @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: 100.h), - child: AutoSizeText( - "On a besoin de ça!", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w600, - fontSize: 30.w), - maxLines: 1, - maxFontSize: 50, - overflow: TextOverflow.fade, - ), - ), - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 600), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - 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: 230.h, - child: AutoSizeText( - "Promis c’est rapide.", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w400, - fontSize: 17.w), - maxFontSize: 20, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - Padding( - padding: EdgeInsets.only( - bottom: 16.h, - left: defaultPadding, - right: defaultPadding), - child: TextFormField( - keyboardAppearance: Brightness.dark, - validator: (value) { - if (value == null || value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: TextInputType.emailAddress, - style: GoogleFonts.plusJakartaSans( - color: primaryColor, fontSize: 15), - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1.sp, color: strokeTextField), - borderRadius: const BorderRadius.all( - Radius.circular(10))), - contentPadding: const EdgeInsets.only( - top: 0, bottom: 0, left: defaultPadding), - fillColor: bgTextField, - filled: true, - focusColor: - const Color.fromRGBO(255, 255, 255, 0.30), - enabledBorder: const OutlineInputBorder( - borderSide: BorderSide( - width: 1, color: strokeTextField), - borderRadius: BorderRadius.all( - Radius.circular(10))), - hintText: 'Pseudo', - hintStyle: GoogleFonts.plusJakartaSans( - color: strokeTextField)), - )), - Padding( - padding: EdgeInsets.only( - bottom: 16.h, - left: defaultPadding, - right: defaultPadding), - child: TextFormField( - keyboardAppearance: Brightness.dark, - validator: (value) { - if (value == null || value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: TextInputType.emailAddress, - style: GoogleFonts.plusJakartaSans( - color: primaryColor), - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, color: strokeTextField), - borderRadius: BorderRadius.all( - Radius.circular(10))), - contentPadding: EdgeInsets.only( - top: 0, bottom: 0, left: defaultPadding), - fillColor: bgTextField, - filled: true, - focusColor: - Color.fromRGBO(255, 255, 255, 0.30), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, color: strokeTextField), - borderRadius: BorderRadius.all( - Radius.circular(10))), - hintText: 'Email', - hintStyle: GoogleFonts.plusJakartaSans( - color: strokeTextField)), - )), - Padding( - padding: EdgeInsets.only( - bottom: 16.h, - left: defaultPadding, - right: defaultPadding), - child: TextFormField( - keyboardAppearance: Brightness.dark, - obscureText: passenable, - validator: (value) { - if (value == null || value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: TextInputType.emailAddress, - style: GoogleFonts.plusJakartaSans( - color: primaryColor), - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, color: strokeTextField), - borderRadius: - BorderRadius.all(Radius.circular(10))), - contentPadding: EdgeInsets.only( - top: 0, bottom: 0, left: defaultPadding), - fillColor: bgTextField, - filled: true, - focusColor: Color.fromRGBO(255, 255, 255, 0.30), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, color: strokeTextField), - borderRadius: - BorderRadius.all(Radius.circular(10))), - hintText: 'Mot de passe', - hintStyle: GoogleFonts.plusJakartaSans( - color: strokeTextField), - suffixIcon: Container( - padding: EdgeInsets.only(right: 10), - margin: EdgeInsets.all(5), - height: 3, - child: InkWell( - onTap: () { - setState(() { - if (passenable) { - passenable = false; - } else { - passenable = true; - } - }); - }, // Image tapped - splashColor: Colors - .white10, // Splash color over image - child: Image( - image: passenable - ? AssetImage( - "assets/images/show_icon.png") - : AssetImage( - "assets/images/hide_icon.png"), - height: 2, - ), - )), - ), - ), - ), - Padding( - padding: EdgeInsets.only( - bottom: 16.h, - left: defaultPadding, - right: defaultPadding), - child: TextFormField( - keyboardAppearance: Brightness.dark, - obscureText: passenable, - validator: (value) { - if (value == null || value.isEmpty) { - return 'TODO'; - } - return null; - }, - cursorColor: primaryColor, - keyboardType: TextInputType.emailAddress, - style: GoogleFonts.plusJakartaSans( - color: primaryColor), - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, color: strokeTextField), - borderRadius: - BorderRadius.all(Radius.circular(10))), - contentPadding: EdgeInsets.only( - top: 0, bottom: 0, left: defaultPadding), - fillColor: bgTextField, - filled: true, - focusColor: Color.fromRGBO(255, 255, 255, 0.30), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - width: 1, color: strokeTextField), - borderRadius: - BorderRadius.all(Radius.circular(10))), - hintText: 'Confirmation du Mot de passe', - hintStyle: GoogleFonts.plusJakartaSans( - color: strokeTextField), - suffixIcon: Container( - padding: EdgeInsets.only(right: 10), - margin: EdgeInsets.all(5), - height: 3, - child: InkWell( - onTap: () { - setState(() { - if (passenable) { - passenable = false; - } else { - passenable = true; - } - }); - }, // Image tapped - splashColor: Colors - .white10, // Splash color over image - child: Image( - image: passenable - ? AssetImage( - "assets/images/show_icon.png") - : AssetImage( - "assets/images/hide_icon.png"), - height: 2, - ), - )), - ), - ), - ), - Padding( - padding: - EdgeInsets.symmetric(horizontal: defaultPadding), - child: SizedBox(width: 600, child: LoginButton()), - ), - ], - )), - SizedBox(height: 50.h), - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 600), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: Container( - color: Color(0xFF3D3D3D), - height: 1, - ), - ), - Padding( - padding: const EdgeInsets.only( - left: defaultPadding, right: defaultPadding), - child: Text( - 'Ou', - style: GoogleFonts.plusJakartaSans( - color: Colors.white, fontWeight: FontWeight.bold), - ), - ), - Expanded( - child: Container( - height: 1, - color: Color(0xFF3D3D3D), - )), - ], - ), - ), - SizedBox(height: 47.h), - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 540), - child: SizedBox( - width: 300.sp, - height: 50, - child: SignInButton( - Buttons.Google, - text: "Login with Google", - onPressed: () {}, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(20))), - ), - ), - ), - ], - ), - )), - IgnorePointer( - child: Container( - height: 240.h, - decoration: BoxDecoration( - gradient: LinearGradient(begin: Alignment.topRight, stops: [ - 0, - 1 - ], colors: [ - bgColor.withOpacity(1), - bgColor.withOpacity(0) - ])), - ), - ), - 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, - ), - ), - ), - ), - ), - ], - ), - ); - } -} +import 'dart:ui'; + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_signin_button/button_list.dart'; +import 'package:flutter_signin_button/button_view.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/values/constants.dart'; + +import '../components/login_button.dart'; +import '../main.dart'; + +class RegistrationScreen extends StatefulWidget { + const RegistrationScreen({Key? key}) : super(key: key); + + @override + State createState() => _RegistrationScreenState(); +} + +class _RegistrationScreenState extends State { + bool passenable = true; + final _formKey = GlobalKey(); + final _userPseudoTextField = TextEditingController(); + final _userMailTextField = TextEditingController(); + final _passwordTextField = TextEditingController(); + final _passwordConfirmTextField = TextEditingController(); + + handleRegister() async { + if (_formKey.currentState!.validate()) { + try { + await MyApp.userViewModel.register(_userPseudoTextField.text, + _passwordTextField.text, _userMailTextField.text); + Navigator.pushNamed(context, '/explanation'); + } 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: Form( + key: _formKey, + child: Stack( + children: [ + SingleChildScrollView( + child: SizedBox( + width: double.infinity, + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 100.h), + child: AutoSizeText( + "On a besoin de ça!", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w600, + fontSize: 30.w), + maxLines: 1, + maxFontSize: 50, + overflow: TextOverflow.fade, + ), + ), + ConstrainedBox( + constraints: BoxConstraints(maxWidth: 600), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + 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: 230.h, + child: AutoSizeText( + "Promis c’est rapide.", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 17.w), + maxFontSize: 20, + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.only( + bottom: 16.h, + left: defaultPadding, + right: defaultPadding), + child: TextFormField( + controller: _userPseudoTextField, + keyboardAppearance: Brightness.dark, + validator: (value) { + if (value == null || value.isEmpty) { + return 'entrez un pseudo valide'; + } + return null; + }, + cursorColor: primaryColor, + keyboardType: TextInputType.emailAddress, + style: GoogleFonts.plusJakartaSans( + color: primaryColor, fontSize: 15), + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1.sp, + color: strokeTextField), + borderRadius: const BorderRadius.all( + Radius.circular(10))), + prefix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + suffix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + fillColor: bgTextField, + filled: true, + focusColor: const Color.fromRGBO( + 255, 255, 255, 0.30), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide( + width: 1, color: strokeTextField), + borderRadius: BorderRadius.all( + Radius.circular(10))), + hintText: 'Pseudo', + hintStyle: GoogleFonts.plusJakartaSans( + color: strokeTextField)), + )), + Padding( + padding: EdgeInsets.only( + bottom: 16.h, + left: defaultPadding, + right: defaultPadding), + child: TextFormField( + controller: _userMailTextField, + keyboardAppearance: Brightness.dark, + validator: (value) { + if (value == null || value.isEmpty) { + return 'entrez un email valide'; + } + return null; + }, + cursorColor: primaryColor, + keyboardType: TextInputType.emailAddress, + style: GoogleFonts.plusJakartaSans( + color: primaryColor), + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1, color: strokeTextField), + borderRadius: BorderRadius.all( + Radius.circular(10))), + prefix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + suffix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + fillColor: bgTextField, + filled: true, + focusColor: + Color.fromRGBO(255, 255, 255, 0.30), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1, color: strokeTextField), + borderRadius: BorderRadius.all( + Radius.circular(10))), + hintText: 'Email', + hintStyle: GoogleFonts.plusJakartaSans( + color: strokeTextField)), + )), + Padding( + padding: EdgeInsets.only( + bottom: 16.h, + left: defaultPadding, + right: defaultPadding), + child: TextFormField( + controller: _passwordTextField, + keyboardAppearance: Brightness.dark, + obscureText: passenable, + validator: (value) { + if (value == null || value.isEmpty) { + return 'entrez un mot de passe valide'; + } + return null; + }, + cursorColor: primaryColor, + style: GoogleFonts.plusJakartaSans( + color: primaryColor), + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1, color: strokeTextField), + borderRadius: + BorderRadius.all(Radius.circular(10))), + prefix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + suffix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + fillColor: bgTextField, + filled: true, + focusColor: Color.fromRGBO(255, 255, 255, 0.30), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1, color: strokeTextField), + borderRadius: + BorderRadius.all(Radius.circular(10))), + hintText: 'Mot de passe', + hintStyle: GoogleFonts.plusJakartaSans( + color: strokeTextField), + suffixIcon: Container( + padding: EdgeInsets.only(right: 10), + margin: EdgeInsets.all(5), + height: 3, + child: InkWell( + onTap: () { + setState(() { + if (passenable) { + passenable = false; + } else { + passenable = true; + } + }); + }, + // Image tapped + splashColor: Colors.white10, + // Splash color over image + child: Image( + image: passenable + ? AssetImage( + "assets/images/show_icon.png") + : AssetImage( + "assets/images/hide_icon.png"), + height: 2, + ), + )), + ), + ), + ), + Padding( + padding: EdgeInsets.only( + bottom: 16.h, + left: defaultPadding, + right: defaultPadding), + child: TextFormField( + controller: _passwordConfirmTextField, + keyboardAppearance: Brightness.dark, + obscureText: passenable, + validator: (value) { + if (value == null || value.isEmpty) { + return 'entrez un mot de passe valide'; + } else if (_passwordTextField.text != value) { + return 'les mots de passes ne sont pas identiques'; + } + return null; + }, + cursorColor: primaryColor, + keyboardType: TextInputType.emailAddress, + style: GoogleFonts.plusJakartaSans( + color: primaryColor), + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1, color: strokeTextField), + borderRadius: + BorderRadius.all(Radius.circular(10))), + prefix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + suffix: const Padding( + padding: EdgeInsets.only(left: 20.0)), + fillColor: bgTextField, + filled: true, + focusColor: Color.fromRGBO(255, 255, 255, 0.30), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + width: 1, color: strokeTextField), + borderRadius: + BorderRadius.all(Radius.circular(10))), + hintText: 'Confirmation du Mot de passe', + hintStyle: GoogleFonts.plusJakartaSans( + color: strokeTextField), + suffixIcon: Container( + padding: EdgeInsets.only(right: 10), + margin: EdgeInsets.all(5), + height: 3, + child: InkWell( + onTap: () { + setState(() { + if (passenable) { + passenable = false; + } else { + passenable = true; + } + }); + }, + // Image tapped + splashColor: Colors.white10, + // Splash color over image + child: Image( + image: passenable + ? AssetImage( + "assets/images/show_icon.png") + : AssetImage( + "assets/images/hide_icon.png"), + height: 2, + ), + )), + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric( + horizontal: defaultPadding), + child: SizedBox( + width: 600, + child: LoginButton( + callback: handleRegister, + )), + ), + Align( + child: GestureDetector( + onTap: () { + Navigator.pushNamed(context, '/login'); + }, + child: Padding( + padding: EdgeInsets.only(top: 20), + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: 'Tu as déjà un compte?', + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 15), + children: [ + TextSpan( + text: " Connexion", + style: GoogleFonts.plusJakartaSans( + fontSize: 15, + fontWeight: FontWeight.w400, + color: primaryColor)), + ], + ), + ), + ), + ), + ), + ], + )), + SizedBox(height: 50.h), + ConstrainedBox( + constraints: BoxConstraints(maxWidth: 600), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Container( + color: Color(0xFF3D3D3D), + height: 1, + ), + ), + Padding( + padding: const EdgeInsets.only( + left: defaultPadding, right: defaultPadding), + child: Text( + 'Ou', + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.bold), + ), + ), + Expanded( + child: Container( + height: 1, + color: Color(0xFF3D3D3D), + )), + ], + ), + ), + SizedBox(height: 47.h), + ConstrainedBox( + constraints: BoxConstraints(maxWidth: 540), + child: SizedBox( + width: 300.sp, + height: 50, + child: SignInButton( + Buttons.Google, + text: "Login with Google", + onPressed: () {}, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.all(Radius.circular(20))), + ), + ), + ), + ], + ), + )), + IgnorePointer( + child: Container( + height: 240.h, + decoration: BoxDecoration( + gradient: LinearGradient(begin: Alignment.topRight, stops: [ + 0, + 1 + ], colors: [ + bgColor.withOpacity(1), + bgColor.withOpacity(0) + ])), + ), + ), + 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/screens/welcome_screen.dart b/Sources/justMUSIC/lib/screens/welcome_screen.dart index 5ba91e5..0180102 100644 --- a/Sources/justMUSIC/lib/screens/welcome_screen.dart +++ b/Sources/justMUSIC/lib/screens/welcome_screen.dart @@ -1,90 +1,98 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/values/constants.dart'; - -import '../components/join_button.dart'; - -class WellcomeScreen extends StatelessWidget { - const WellcomeScreen({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Container( - padding: EdgeInsets.all(defaultPadding), - width: double.infinity, - height: double.infinity, - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/images/wellcome_background.png"), - fit: BoxFit.cover, - ), - ), - child: Align( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 10, - child: Padding( - padding: EdgeInsets.only(bottom: 100), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Bienvenue sur,", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 34), - ), - Image( - image: AssetImage("assets/images/logo.png"), - width: 230, - ), - SizedBox( - height: 25, - ), - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 520), - child: Text( - "Explore les nouvelles découvertes musicales de tes amis, et partage leur ton mood.", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w200, - fontSize: 15), - ), - ), - ], - ), - ), - ), - Expanded( - flex: 3, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - JoinButton(), - SizedBox( - height: defaultPadding, - ), - Text( - "Tu as déja un compte? Connexion", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w400, - fontSize: 15), - ), - ], - ), - ), - ], - ), - ) /* add child content here */, - ), - ); - } -} +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/values/constants.dart'; + +import '../components/join_button.dart'; + +class WellcomeScreen extends StatelessWidget { + const WellcomeScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + padding: EdgeInsets.all(defaultPadding), + width: double.infinity, + height: double.infinity, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/wellcome_background.png"), + fit: BoxFit.cover, + ), + ), + child: Align( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + flex: 10, + child: Padding( + padding: EdgeInsets.only(bottom: 100), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Bienvenue sur,", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 34), + ), + Image( + image: AssetImage("assets/images/logo.png"), + width: 230, + ), + SizedBox( + height: 25, + ), + ConstrainedBox( + constraints: BoxConstraints(maxWidth: 520), + child: Text( + "Explore les nouvelles découvertes musicales de tes amis, et partage leur ton mood.", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w200, + fontSize: 15), + ), + ), + ], + ), + ), + ), + Expanded( + flex: 3, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + JoinButton(), + SizedBox( + height: defaultPadding, + ), + GestureDetector( + onTap: () { + Navigator.pushNamed(context, '/login'); + }, + child: Padding( + padding: const EdgeInsets.all(3.0), + child: Text( + "Tu as déja un compte? Connexion", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 15), + ), + ), + ), + ], + ), + ), + ], + ), + ) /* add child content here */, + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/service/AuthService.dart b/Sources/justMUSIC/lib/service/AuthService.dart new file mode 100644 index 0000000..d7e39fa --- /dev/null +++ b/Sources/justMUSIC/lib/service/AuthService.dart @@ -0,0 +1,80 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import '../main.dart'; + +class AuthService { + register(String pseudo, String email, String password) async { + try { + final data = await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: password, + ); + + String uniqueId = await generateUniqueId(pseudo); + + final user = { + "mail": email, + "pseudo": pseudo, + "phone_number": "", + "unique_id": uniqueId, + "picture": + "https://media.licdn.com/dms/image/D4E03AQHvc_b89ogFtQ/profile-displayphoto-shrink_400_400/0/1665060931103?e=1695859200&v=beta&t=wVLbxqeokYiPJ13nJ3SMq97iZvcm3ra0ufWFZCSzhjg", + "friends": [] + }; + + MyApp.db + .collection("users") + .doc(data.user?.uid) + .set(user) + .then((value) => print("User Added")) + .catchError((error) => print("Failed to add user: $error")); + } on FirebaseAuthException catch (e) { + if (e.code == 'weak-password') { + throw ('Mot de passe trop court'); + } else if (e.code == 'email-already-in-use') { + throw ('Mail déjà utilisé'); + } else if (e.code == 'invalid-email') { + throw ('Mauvais format de mail'); + } + rethrow; + } + } + + Future generateUniqueId(String pseudo) async { + String uniqueId = '$pseudo#0001'; + int suffix = 1; + final CollectionReference usersCollection = + FirebaseFirestore.instance.collection("users"); + final QuerySnapshot querySnapshot = + await usersCollection.where('pseudo', isEqualTo: pseudo).get(); + + for (final doc in querySnapshot.docs) { + suffix++; + uniqueId = '$pseudo#${suffix.toString().padLeft(4, '0')}'; + } + + return uniqueId; + } + + login(String email, String password) async { + try { + await FirebaseAuth.instance + .signInWithEmailAndPassword(email: email, password: password); + } on FirebaseAuthException catch (e) { + if (e.code == 'user-not-found') { + throw ('Mail incorrect'); + } else if (e.code == 'wrong-password') { + throw ('Mot de passe incorrect'); + } else if (e.code == 'invalid-email') { + throw ('Format de mail incorrect'); + } else if (e.code == 'too-many-requests') { + throw ('L\'accès à ce compte a été temporairement désactivé en raison de nombreuses tentatives de connexion infructueuses. Réessayer plus tard.'); + } + rethrow; + } + } + + void signOut() async { + await FirebaseAuth.instance.signOut(); + } +} diff --git a/Sources/justMUSIC/lib/service/UserService.dart b/Sources/justMUSIC/lib/service/UserService.dart new file mode 100644 index 0000000..d91e886 --- /dev/null +++ b/Sources/justMUSIC/lib/service/UserService.dart @@ -0,0 +1,15 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '../model/User.dart'; +import '../main.dart'; + +class UserService { + acceptFriend(User user, String idFriend) { + MyApp.db.collection("users").doc(user.id).update({ + "friends": FieldValue.arrayUnion([idFriend]) + }); + MyApp.db.collection("users").doc(idFriend).update({ + "friends": FieldValue.arrayUnion([user.id]) + }); + } +} diff --git a/Sources/justMUSIC/lib/values/keys.dart b/Sources/justMUSIC/lib/values/keys.dart new file mode 100644 index 0000000..4654117 --- /dev/null +++ b/Sources/justMUSIC/lib/values/keys.dart @@ -0,0 +1 @@ +const geoKey = "85a2724ad38b3994c2b7ebe1d239bbff"; diff --git a/Sources/justMUSIC/lib/view_model/UserViewModel.dart b/Sources/justMUSIC/lib/view_model/UserViewModel.dart index 2aaa1fb..5d41ebc 100644 --- a/Sources/justMUSIC/lib/view_model/UserViewModel.dart +++ b/Sources/justMUSIC/lib/view_model/UserViewModel.dart @@ -1,19 +1,66 @@ -import '../model/User.dart'; - -class UserViewModel { - User _userCurrent = User( - 1, "MelinaShow", "France", "test@gmail.com", "zezrzrzr", 5, 12, 114, []); - - User get userCurrent => _userCurrent; - - set userCurrent(User value) { - _userCurrent = value; - } // Constructor - - UserViewModel(); - - // Methods - User getUser(int id) { - throw new Error(); - } -} +import 'package:firebase_auth/firebase_auth.dart' as firebase_auth; +import 'package:justmusic/service/AuthService.dart'; + +import '../model/User.dart'; +import '../model/mapper/UserMapper.dart'; +import '../main.dart'; + +class UserViewModel { + late User _userCurrent; + final AuthService _authService = AuthService(); + + User get userCurrent => _userCurrent; + + set userCurrent(User value) { + _userCurrent = value; + } // Constructor + + UserViewModel(); + + // Methods + Future getUser(String id) async { + final user = await MyApp.db.collection("users").doc(id).get(); + return UserMapper.toModel(user, null); + } + + login(String pseudo, String password) async { + try { + await _authService.login(pseudo, password); + final user = await MyApp.db + .collection("users") + .doc(firebase_auth.FirebaseAuth.instance.currentUser?.uid) + .get(); + User data = UserMapper.toModel(user, null); + _userCurrent = data; + } catch (e) { + rethrow; + } + } + + bool _isAlphaNumeric(String input) { + final RegExp alphaNumericRegExp = RegExp(r'^[a-zA-Z0-9]+$'); + return alphaNumericRegExp.hasMatch(input); + } + + register(String pseudo, String password, String email) async { + if (!_isAlphaNumeric(pseudo)) { + throw ("Le pseudo doit contenir seulement des lettres et des chiffres"); + } + + try { + await _authService.register(pseudo.toLowerCase(), email, password); + final user = await MyApp.db + .collection("users") + .doc(firebase_auth.FirebaseAuth.instance.currentUser?.uid) + .get(); + User data = UserMapper.toModel(user, null); + _userCurrent = data; + } catch (e) { + rethrow; + } + } + + logout() { + _authService.signOut(); + } +} diff --git a/Sources/justMUSIC/pubspec.lock b/Sources/justMUSIC/pubspec.lock index 7f77bef..7903bf2 100644 --- a/Sources/justMUSIC/pubspec.lock +++ b/Sources/justMUSIC/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "5dce45a06d386358334eb1689108db6455d90ceb0d75848d5f4819283d4ee2b8" + url: "https://pub.dev" + source: hosted + version: "1.3.4" animated_appear: dependency: "direct main" description: @@ -113,6 +121,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + cloud_firestore: + dependency: "direct main" + description: + name: cloud_firestore + sha256: f1a06ad4499ed9ab73703560d44893e6b9e66ce3923c9121f4ef3981c972057f + url: "https://pub.dev" + source: hosted + version: "4.8.4" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + sha256: "86bd1865abbeb09a7d09da3e70364a09f894937270651fc611a1c6d6a9f7b02c" + url: "https://pub.dev" + source: hosted + version: "5.15.3" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + sha256: ac2eeb2a7ab1928c3aacc30eed750fa839d6f620e112a5459e321df217be2f47 + url: "https://pub.dev" + source: hosted + version: "3.6.3" collection: dependency: transitive description: @@ -209,6 +241,54 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: "49fd35ce06f2530dd460e5dc123235731cb61dd7c76b0af4b6e190404880d04d" + url: "https://pub.dev" + source: hosted + version: "4.7.2" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: "817f3ceb84ef5e9adaaf50cf7a19255f6ffcdd12c6f9e9aa4cf00fc7f2eb3cfb" + url: "https://pub.dev" + source: hosted + version: "6.16.1" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: e9044778287f1ff8f9f4cee7e247b03ec87bb8977e0e65ad27dc337e196132e8 + url: "https://pub.dev" + source: hosted + version: "5.6.2" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "2e9324f719e90200dc7d3c4f5d2abc26052f9f2b995d3b6626c47a0dfe1c8192" + url: "https://pub.dev" + source: hosted + version: "2.15.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: b63e3be6c96ef5c33bdec1aab23c91eb00696f6452f0519401d640938c94cba2 + url: "https://pub.dev" + source: hosted + version: "4.8.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "0fd5c4b228de29b55fac38aed0d9e42514b3d3bd47675de52bf7f8fccaf922fa" + url: "https://pub.dev" + source: hosted + version: "2.6.0" flutter: dependency: "direct main" description: flutter diff --git a/Sources/justMUSIC/pubspec.yaml b/Sources/justMUSIC/pubspec.yaml index 4afb32a..808fac1 100644 --- a/Sources/justMUSIC/pubspec.yaml +++ b/Sources/justMUSIC/pubspec.yaml @@ -53,6 +53,9 @@ dependencies: audioplayers: ^4.1.0 ionicons: ^0.2.2 top_snackbar_flutter: ^3.1.0 + firebase_core: ^2.15.0 + firebase_auth: ^4.7.2 + cloud_firestore: ^4.8.4 image_picker: ^1.0.1 insta_image_viewer: ^1.0.2 pinch_zoom: ^1.0.0 diff --git a/Sources/justMUSIC/test/Music_test.dart b/Sources/justMUSIC/test/Music_test.dart index f98529a..482f4ff 100644 --- a/Sources/justMUSIC/test/Music_test.dart +++ b/Sources/justMUSIC/test/Music_test.dart @@ -80,3 +80,4 @@ Future main() async { } } +