diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml
index 36e15e8..70bceed 100644
--- a/.idea/libraries/Dart_Packages.xml
+++ b/.idea/libraries/Dart_Packages.xml
@@ -387,34 +387,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -611,132 +583,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -905,20 +751,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1017,41 +849,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1101,34 +898,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Sources/justMUSIC/assets/images/empty_collection.png b/Sources/justMUSIC/assets/images/empty_collection.png
new file mode 100644
index 0000000..c140ccf
Binary files /dev/null and b/Sources/justMUSIC/assets/images/empty_collection.png differ
diff --git a/Sources/justMUSIC/lib/main.dart b/Sources/justMUSIC/lib/main.dart
index 1cf347a..3c5ae57 100644
--- a/Sources/justMUSIC/lib/main.dart
+++ b/Sources/justMUSIC/lib/main.dart
@@ -57,26 +57,10 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State {
late StreamSubscription user;
- Stream userCurrent = Stream.empty();
@override
void initState() {
super.initState();
- checkSignIn();
- }
-
- Future checkSignIn() async {
- user = FirebaseAuth.instance.authStateChanges().listen((user) async {
- if (user == null) {
- print('User is currently signed out!');
- return null;
- } else {
- MyApp.userViewModel.userCurrent = (await (MyApp.userViewModel.getUser(user.uid)))!;
- userCurrent = Stream.value(MyApp.userViewModel.userCurrent);
- print('User is signed in!');
- }
- });
- return null;
}
@override
@@ -94,25 +78,68 @@ class _MyAppState extends State {
return ScreenUtilInit(
useInheritedMediaQuery: true,
builder: (context, child) {
- return MaterialApp(
- routes: {
- '/welcome': (context) => const WellcomeScreen(),
- '/feed': (context) => const FeedScreen(),
- '/login': (context) => const LoginScreen(),
- '/register': (context) => const RegistrationScreen(),
- '/post': (context) => const PostScreen(),
- '/profile': (context) => const ProfileScreen(),
- '/explanation': (context) => const ExplanationsScreen(),
- '/addFriend': (context) => const AddFriendScreen(),
- '/launchingRocket': (context) => const LaunchingRocketScreen(),
- '/verifyEmail': (context) => const VerifyEmailScreen(),
- '/forgetPassword': (context) => const ForgetPasswordScreen(),
- },
- debugShowCheckedModeBanner: false,
- theme: ThemeData(
- primarySwatch: Colors.blue,
- ),
- home: WellcomeScreen());
+ return StreamBuilder(
+ stream: FirebaseAuth.instance.authStateChanges(),
+ builder: (context, snapshot) {
+ if (ConnectionState.waiting == snapshot.connectionState) {
+ return const CupertinoActivityIndicator();
+ }
+ if (snapshot.hasData) {
+ return FutureBuilder(
+ future: MyApp.userViewModel.getUser(snapshot.data!.uid),
+ builder: (context, userSnapshot) {
+ if (userSnapshot.connectionState == ConnectionState.waiting) {
+ return const CupertinoActivityIndicator();
+ } else {
+ if (userSnapshot.hasData) {
+ MyApp.userViewModel.userCurrent = userSnapshot.data!;
+ return MaterialApp(
+ routes: {
+ '/welcome': (context) => const WellcomeScreen(),
+ '/feed': (context) => const FeedScreen(),
+ '/login': (context) => const LoginScreen(),
+ '/register': (context) => const RegistrationScreen(),
+ '/post': (context) => const PostScreen(),
+ '/profile': (context) => const ProfileScreen(),
+ '/explanation': (context) => const ExplanationsScreen(),
+ '/addFriend': (context) => const AddFriendScreen(),
+ '/launchingRocket': (context) => const LaunchingRocketScreen(),
+ '/verifyEmail': (context) => const VerifyEmailScreen(),
+ '/forgetPassword': (context) => const ForgetPasswordScreen(),
+ },
+ debugShowCheckedModeBanner: false,
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: FeedScreen());
+ } else {
+ return const Text('User data not found');
+ }
+ }
+ },
+ );
+ } else {
+ return MaterialApp(
+ routes: {
+ '/welcome': (context) => const WellcomeScreen(),
+ '/feed': (context) => const FeedScreen(),
+ '/login': (context) => const LoginScreen(),
+ '/register': (context) => const RegistrationScreen(),
+ '/post': (context) => const PostScreen(),
+ '/profile': (context) => const ProfileScreen(),
+ '/explanation': (context) => const ExplanationsScreen(),
+ '/addFriend': (context) => const AddFriendScreen(),
+ '/launchingRocket': (context) => const LaunchingRocketScreen(),
+ '/verifyEmail': (context) => const VerifyEmailScreen(),
+ '/forgetPassword': (context) => const ForgetPasswordScreen(),
+ },
+ debugShowCheckedModeBanner: false,
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: WellcomeScreen());
+ }
+ });
},
designSize: Size(390, 844),
);
diff --git a/Sources/justMUSIC/lib/screens/login_screen.dart b/Sources/justMUSIC/lib/screens/login_screen.dart
index eb44ba8..01280f8 100644
--- a/Sources/justMUSIC/lib/screens/login_screen.dart
+++ b/Sources/justMUSIC/lib/screens/login_screen.dart
@@ -27,18 +27,14 @@ class _LoginScreenState extends State {
handleLogin() async {
if (_formKey.currentState!.validate()) {
try {
- await MyApp.userViewModel
- .login(_userMailTextField.text, _passwordTextField.text);
+ 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),
+ style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w400, fontSize: 20.h),
),
backgroundColor: Colors.red,
),
@@ -79,25 +75,19 @@ class _LoginScreenState extends State {
child: Form(
key: _formKey,
child: Column(
- crossAxisAlignment:
- CrossAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
flex: 4,
child: Padding(
padding: EdgeInsets.only(bottom: 60),
child: Column(
- mainAxisAlignment:
- MainAxisAlignment.end,
+ mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"Te revoilà!",
- style:
- GoogleFonts.plusJakartaSans(
- color: Colors.white,
- fontWeight:
- FontWeight.w600,
- fontSize: 38.h),
+ style: GoogleFonts.plusJakartaSans(
+ color: Colors.white, fontWeight: FontWeight.w600, fontSize: 38.h),
),
SizedBox(
height: 10,
@@ -106,12 +96,8 @@ class _LoginScreenState extends State {
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),
+ style: GoogleFonts.plusJakartaSans(
+ color: Colors.white, fontWeight: FontWeight.w400, fontSize: 20.h),
textAlign: TextAlign.center,
),
),
@@ -122,51 +108,33 @@ class _LoginScreenState extends State {
Expanded(
flex: 5,
child: Column(
- crossAxisAlignment:
- CrossAxisAlignment.end,
- mainAxisAlignment:
- MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.end,
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: _userMailTextField,
- keyboardAppearance:
- Brightness.dark,
+ keyboardAppearance: Brightness.dark,
validator: (value) {
- if (value == null ||
- value.isEmpty) {
+ if (value == null || value.isEmpty) {
return 'entrez un email valide';
}
return null;
},
cursorColor: primaryColor,
- keyboardType:
- TextInputType.emailAddress,
- style:
- GoogleFonts.plusJakartaSans(
- color: 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)),
+ 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),
+ errorStyle: TextStyle(fontSize: 9, height: 0.3),
+ focusColor: Color.fromRGBO(255, 255, 255, 0.30),
enabledBorder: OutlineInputBorder(
- borderSide:
- BorderSide(width: 1, color: strokeTextField),
+ borderSide: BorderSide(width: 1, color: strokeTextField),
borderRadius: BorderRadius.all(Radius.circular(10))),
hintText: 'Email',
hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)),
@@ -176,55 +144,31 @@ class _LoginScreenState extends State {
),
TextFormField(
controller: _passwordTextField,
- keyboardAppearance:
- Brightness.dark,
+ keyboardAppearance: Brightness.dark,
obscureText: passenable,
validator: (value) {
- if (value == null ||
- value.isEmpty) {
+ if (value == null || value.isEmpty) {
return 'entrez un mot de passe valide';
}
return null;
},
cursorColor: primaryColor,
- style:
- GoogleFonts.plusJakartaSans(
- color: primaryColor),
+ style: GoogleFonts.plusJakartaSans(color: primaryColor),
decoration: InputDecoration(
- focusedBorder:
- OutlineInputBorder(
- borderSide: BorderSide(
- width: 1,
- color:
- strokeTextField),
- borderRadius:
- BorderRadius.all(
- Radius.circular(
- 10))),
+ 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))),
+ 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)),
+ hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField),
+ prefix: const Padding(padding: EdgeInsets.only(left: 20.0)),
suffixIcon: Container(
- padding: EdgeInsets.only(
- right: 10),
+ padding: EdgeInsets.only(right: 10),
margin: EdgeInsets.all(5),
height: 3,
child: InkWell(
@@ -238,38 +182,28 @@ class _LoginScreenState extends State {
});
},
// Image tapped
- splashColor:
- Colors.white10,
+ splashColor: Colors.white10,
// Splash color over image
child: Image(
image: passenable
- ? AssetImage(
- "assets/images/show_icon.png")
- : AssetImage(
- "assets/images/hide_icon.png"),
+ ? AssetImage("assets/images/show_icon.png")
+ : AssetImage("assets/images/hide_icon.png"),
height: 2,
),
)),
- errorStyle: TextStyle(
- fontSize: 9, height: 0.3),
+ errorStyle: TextStyle(fontSize: 9, height: 0.3),
),
),
GestureDetector(
- behavior:
- HitTestBehavior.translucent,
+ behavior: HitTestBehavior.translucent,
onTap: () {
- Navigator.pushNamed(
- context, '/forgetPassword');
+ Navigator.pushNamed(context, '/forgetPassword');
},
child: Padding(
- padding:
- EdgeInsets.only(top: 10),
+ padding: EdgeInsets.only(top: 10),
child: Text(
"Mot de passe oublié?",
- style: GoogleFonts
- .plusJakartaSans(
- color:
- Colors.white),
+ style: GoogleFonts.plusJakartaSans(color: Colors.white),
),
)),
SizedBox(
@@ -283,40 +217,27 @@ class _LoginScreenState extends State {
)),
Align(
child: GestureDetector(
- behavior:
- HitTestBehavior.translucent,
+ behavior: HitTestBehavior.translucent,
onTap: () {
- Navigator.pushNamed(
- context, '/register');
+ Navigator.pushNamed(context, '/register');
},
child: Padding(
- padding:
- EdgeInsets.only(top: 20),
+ 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),
+ 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)),
+ style: GoogleFonts.plusJakartaSans(
+ fontSize: 15,
+ fontWeight: FontWeight.w400,
+ color: primaryColor)),
],
),
),
@@ -331,59 +252,51 @@ class _LoginScreenState extends State {
child: Padding(
padding: EdgeInsets.only(top: 20),
child: Column(
- mainAxisAlignment:
- MainAxisAlignment.start,
- crossAxisAlignment:
- CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.center,
children: [
ConstrainedBox(
- constraints: BoxConstraints(
- maxWidth: 600),
+ constraints: BoxConstraints(maxWidth: 600),
child: Row(
- mainAxisAlignment:
- MainAxisAlignment
- .spaceEvenly,
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Container(
- color:
- Color(0xFF3D3D3D),
+ color: Color(0xFF3D3D3D),
height: 1,
),
),
Padding(
- padding: const EdgeInsets
- .only(
- left:
- defaultPadding,
- right:
- defaultPadding),
+ padding: const EdgeInsets.only(
+ left: defaultPadding, right: defaultPadding),
child: Text(
'Ou',
- style: GoogleFonts
- .plusJakartaSans(
- color: Colors
- .white,
- fontWeight:
- FontWeight
- .bold),
+ style: GoogleFonts.plusJakartaSans(
+ color: Colors.white, fontWeight: FontWeight.bold),
),
),
Expanded(
child: Container(
height: 1,
- color:
- Color(0xFF3D3D3D),
+ color: Color(0xFF3D3D3D),
)),
],
),
),
- SizedBox(
- height: defaultPadding),
- SignInButton(
- Buttons.Google,
- text: "Login with Google",
- onPressed: signInWithGoogle,
+ SizedBox(height: defaultPadding),
+ ConstrainedBox(
+ constraints: BoxConstraints(maxWidth: 540),
+ child: SizedBox(
+ width: 300.sp,
+ height: 50,
+ child: SignInButton(
+ Buttons.Google,
+ text: "Login with Google",
+ onPressed: signInWithGoogle,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.all(Radius.circular(20))),
+ ),
+ ),
),
],
),
diff --git a/Sources/justMUSIC/lib/screens/search_song_screen.dart b/Sources/justMUSIC/lib/screens/search_song_screen.dart
index 017e5c2..aac095b 100644
--- a/Sources/justMUSIC/lib/screens/search_song_screen.dart
+++ b/Sources/justMUSIC/lib/screens/search_song_screen.dart
@@ -269,40 +269,139 @@ class _SearchSongScreenState extends State {
future: _fetchSavedSong(),
builder: (BuildContext context, AsyncSnapshot> snapshot) {
if (snapshot.hasData) {
- return ListView.builder(
- physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
- controller: _scrollController,
- itemCount: snapshot.data?.length,
- itemBuilder: (context, index) {
- if (playingIndex == index) {
+ if (snapshot.data?.length == 0) {
+ return Container(
+ width: double.infinity,
+ height: double.infinity,
+ child: Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(
+ "Votre collection est vide.",
+ style: GoogleFonts.plusJakartaSans(
+ color: Colors.white, fontWeight: FontWeight.w800, fontSize: 18),
+ ),
+ ),
+ Image.asset(
+ "assets/images/empty_collection.png",
+ width: 300,
+ )
+ ],
+ ),
+ );
+ } else {
+ return ListView.builder(
+ physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
+ controller: _scrollController,
+ itemCount: snapshot.data?.length,
+ itemBuilder: (context, index) {
+ if (playingIndex == index) {
+ return InkWell(
+ onTap: () {
+ widget.callback((snapshot.data?[index])!);
+ },
+ onLongPress: () {
+ showCupertinoModalPopup(
+ context: context,
+ builder: (BuildContext context) => CupertinoAlertDialog(
+ title: const Text('Supprimer la musique'),
+ content: Text(
+ 'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'),
+ actions: [
+ CupertinoDialogAction(
+ /// This parameter indicates this action is the default,
+ /// and turns the action's text to bold text.
+ isDefaultAction: true,
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ child: const Text('Annuler'),
+ ),
+ CupertinoDialogAction(
+ /// This parameter indicates the action would perform
+ /// a destructive action such as deletion, and turns
+ /// the action's text color to red.
+ isDestructiveAction: true,
+ onPressed: () async {
+ Navigator.pop(context);
+ await MyApp.musicViewModel
+ .addOrDeleteFavoriteMusic((snapshot.data?[index])!.id);
+ MyApp.userViewModel.userCurrent.musics_likes
+ .remove((snapshot.data?[index])!.id);
+
+ MyApp.audioPlayer.release();
+ setState(() {
+ playingIndex = null;
+ });
+ },
+ child: const Text('Supprimer'),
+ ),
+ ],
+ ),
+ );
+ },
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 20),
+ child: MusicListComponent(
+ music: (snapshot.data?[index])!,
+ playing: true,
+ callback: playMusic,
+ index: index,
+ ),
+ ));
+ }
return InkWell(
onTap: () {
- widget.callback(filteredData[index]);
+ widget.callback((snapshot.data?[index])!);
+ },
+ onLongPress: () {
+ showCupertinoModalPopup(
+ context: context,
+ builder: (BuildContext context) => CupertinoAlertDialog(
+ title: const Text('Supprimer la musique'),
+ content: Text(
+ 'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'),
+ actions: [
+ CupertinoDialogAction(
+ /// This parameter indicates this action is the default,
+ /// and turns the action's text to bold text.
+ isDefaultAction: true,
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ child: const Text('Annuler'),
+ ),
+ CupertinoDialogAction(
+ /// This parameter indicates the action would perform
+ /// a destructive action such as deletion, and turns
+ /// the action's text color to red.
+ isDestructiveAction: true,
+ onPressed: () async {
+ Navigator.pop(context);
+ await MyApp.musicViewModel
+ .addOrDeleteFavoriteMusic((snapshot.data?[index])!.id);
+ MyApp.userViewModel.userCurrent.musics_likes
+ .remove((snapshot.data?[index])!.id);
+ setState(() {});
+ },
+ child: const Text('Supprimer'),
+ ),
+ ],
+ ),
+ );
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: MusicListComponent(
music: (snapshot.data?[index])!,
- playing: true,
+ playing: false,
callback: playMusic,
index: index,
),
));
- }
- return InkWell(
- onTap: () {
- widget.callback((snapshot.data?[index])!);
- },
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 20),
- child: MusicListComponent(
- music: (snapshot.data?[index])!,
- playing: false,
- callback: playMusic,
- index: index,
- ),
- ));
- });
+ });
+ }
} else {
return CupertinoActivityIndicator();
}