Compare commits

..

No commits in common. 'master' and 'ui/fix-web-responsive' have entirely different histories.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 KiB

@ -39,9 +39,9 @@ C'est un réseau social donc l'utilisateur pourra publier et commenter des posts
La racine de notre gitlab est composé de deux dossier essentielles au projet: La racine de notre gitlab est composé de deux dossier essentielles au projet:
[**Sources**](Sources) : **Code de l'application** [**src**](src) : **Code de l'application**
[**Documentation**](Documentation) : **Regroupe l'entièreté de la documentation** [**doc**](doc) : **Regroupe l'entièreté de la documentation**
</br> </br>
@ -49,33 +49,10 @@ La racine de notre gitlab est composé de deux dossier essentielles au projet:
## Fonctionnement ## Fonctionnement
<div align = center>
<img src="Documentation/Images/Overview.png" />
</div>
### Feeds
Une fois authentifié vous aurez la possibilité de voir les posts capsules de vos amis, de voir les musiques qu'ils mettent en avant accompagner éventuellement d'une image, d'une description, de leurs localisations... (Vous n'avez pas d'amis, pas de soucis, cliquer seulement sur l'icon en haut a gauche de la page pour suivre nimporte quel personne que vous voulez), Mais aussi juste d'un simple mouvement du doigt swiper pour vous retrouvez sur la page Discovery où vous verrais les posts récents en tendance dans le monde 🌎
Amuser vous à cliquer sur les posts pour ecouter la music mais aussi connaître les détails et savoir qui a commenter 💬 et liker ❤️. Si la musique vous plaît enregistrer la et vous la retrouverez lorsque vous aurez envie de poster.
### Post
Pour participer à cette aventure musicale avec des gens du monde entier, cliquez simplement sur l'icône JustMusic. Gardez à l'esprit que vous ne pourrez poster qu'une fois par jour, donc réfléchissez bien à la musique que vous souhaitez mettre en avant. N'hésitez pas à ajouter une photo et une description pour rendre votre publication plus chaleureuse 😃.
### Profil
Consultez l'aperçu de votre profil pour savoir combien de personnes vous suivent et que vous suivez. Vous pouvez également voir le nombre de capsules que vous avez publiées, personnaliser les paramètres de votre compte selon vos préférences, et explorez votre historique de capsules pour vous remémorer vos précédentes publications 🎧.
#### Bonne aventure musicale 🎵🌟
## Deploiement ## Deploiement
- [x] &nbsp; ![IOS](https://img.shields.io/badge/IOS-000?style=for-the-badge&logo=apple&logoColor=black&color=white) - [x] &nbsp; ![IOS](https://img.shields.io/badge/IOS-000?style=for-the-badge&logo=apple&logoColor=black&color=white)
- [x] &nbsp; ![Android](https://img.shields.io/badge/Android-000?style=for-the-badge&logo=android&logoColor=white&color=green) - [x] &nbsp; ![Android](https://img.shields.io/badge/Android-000?style=for-the-badge&logo=android&logoColor=white&color=green)
- [x] &nbsp; ![Safari](https://img.shields.io/badge/Safari-000000.svg?style=for-the-badge&logo=Safari&logoColor=white)
## Techniciens ## Techniciens
@ -87,7 +64,7 @@ Consultez l'aperçu de votre profil pour savoir combien de personnes vous suiven
<img src ="https://codefirst.iut.uca.fr/git/avatars/1ff65c9c5ab0e8c8883fb48adbcf972f?size=870" height="50px"> <img src ="https://codefirst.iut.uca.fr/git/avatars/1ff65c9c5ab0e8c8883fb48adbcf972f?size=870" height="50px">
</a> </a>
<a href = "https://codefirst.iut.uca.fr/git/david.d_almeida"> <a href = "https://codefirst.iut.uca.fr/git/david.d_almeida">
<img src ="https://codefirst.iut.uca.fr/git/avatars/a16fa2dc52ceae18d8923c91121caa66?size=870" height="50px"> <img src ="https://codefirst.iut.uca.fr/git/avatars/0f8eaaad1e26d3de644ca522eccaea7c?size=870" height="50px">
</a> </a>
<a href = "https://codefirst.iut.uca.fr/git/rayhan.hassou"> <a href = "https://codefirst.iut.uca.fr/git/rayhan.hassou">
<img src ="https://codefirst.iut.uca.fr/git/avatars/84062b2bb326d9e9154a9859b375e599?size=870" height="50px"> <img src ="https://codefirst.iut.uca.fr/git/avatars/84062b2bb326d9e9154a9859b375e599?size=870" height="50px">

@ -1,4 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'dart:html' as html;
import 'package:animated_appear/animated_appear.dart'; import 'package:animated_appear/animated_appear.dart';
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
@ -9,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:image_picker_for_web/image_picker_for_web.dart';
import 'package:insta_image_viewer/insta_image_viewer.dart'; import 'package:insta_image_viewer/insta_image_viewer.dart';
import 'package:justmusic/values/constants.dart'; import 'package:justmusic/values/constants.dart';
import 'package:text_scroll/text_scroll.dart'; import 'package:text_scroll/text_scroll.dart';
@ -62,7 +64,21 @@ class _EditablePostComponentState extends State<EditablePostComponent> with Tick
} }
Future pickImage(ImageSource source) async { Future pickImage(ImageSource source) async {
if(kIsWeb){
print('you are on web');
try {
final image = await ImagePicker().pickImage(source: source, imageQuality: 20);
if (image == null) return;
final imageTemp = File(image.path);
setState(() {
this.image = imageTemp;
widget.callBackImage(imageTemp);
});
} on PlatformException catch (e) {
print('Failed to pick image: $e');
}
}
else{
try { try {
final image = await ImagePicker().pickImage(source: source, imageQuality: 20); final image = await ImagePicker().pickImage(source: source, imageQuality: 20);
if (image == null) return; if (image == null) return;
@ -74,6 +90,7 @@ class _EditablePostComponentState extends State<EditablePostComponent> with Tick
} on PlatformException catch (e) { } on PlatformException catch (e) {
print('Failed to pick image: $e'); print('Failed to pick image: $e');
} }
}
} }

@ -35,7 +35,7 @@ class _HistoricComponentState extends State<HistoricComponent> {
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
return Container( return Container(
constraints: const BoxConstraints( maxWidth: 600), constraints: const BoxConstraints( maxWidth: 420),
child: Wrap( child: Wrap(
spacing: 14, spacing: 14,
runSpacing: 14, runSpacing: 14,
@ -65,19 +65,13 @@ class _HistoricComponentState extends State<HistoricComponent> {
); );
} }
if (checkCapsule != null) { if (checkCapsule != null) {
return Tooltip( return Container(
message: "${checkCapsule.item2.artists.first.name} - ${checkCapsule.item2.title}".length < 30? "${checkCapsule.item2.artists.first.name} - ${checkCapsule.item2.title}": "${checkCapsule.item2.artists.first.name} - ${checkCapsule.item2.title}".substring(0,30)+"...",
decoration: const BoxDecoration(
border: Border.fromBorderSide(BorderSide(color: Color(0xFF3A3A3A), width: 1)),
color: tooltipBackground, borderRadius: BorderRadius.all(Radius.circular(20))
),
child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage(image: NetworkImage((checkCapsule.item2.cover)!)), image: DecorationImage(image: NetworkImage((checkCapsule.item2.cover)!)),
borderRadius: BorderRadius.circular(5)), borderRadius: BorderRadius.circular(5)),
height: 60, height: 60,
width: 60, width: 60,
)); );
} else { } else {
return Container( return Container(
color: bgColor, color: bgColor,

@ -152,8 +152,10 @@ class _PostComponentState extends State<PostComponent> with TickerProviderStateM
children: [ children: [
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
child: Image.network( child: FadeInImage.assetNetwork(
widget.post.music.cover!, image: widget.post.music.cover!,
fadeInDuration: const Duration(milliseconds: 100),
placeholder: "assets/images/loadingPlaceholder.gif",
), ),
), ),
Image( Image(
@ -194,9 +196,11 @@ class _PostComponentState extends State<PostComponent> with TickerProviderStateM
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(13), borderRadius: BorderRadius.circular(13),
// implement image // implement image
child: Image.network( child: FadeInImage.assetNetwork(
widget.post.selfie!, image: widget.post.selfie!,
fit: BoxFit.cover, fit: BoxFit.cover,
fadeInDuration: const Duration(milliseconds: 100),
placeholder: "assets/images/loadingPlaceholder.gif",
), ),
), ),
), ),

@ -1,34 +0,0 @@
import 'package:tuple/tuple.dart';
import 'Music.dart';
class Capsule {
final String _id;
late Music _music;
Tuple2<String?,String?> _location;
DateTime _date;
// Constructor
Capsule(this._id, this._location, this._date);
//Getters and setters
String get id => _id;
Music get music => _music;
set music(Music value) {
_music = value;
}
Tuple2<String?, String?> get location => _location;
set location(Tuple2<String?, String?> value) {
_location = value;
}
DateTime get date => _date;
set date(DateTime value) {
_date = value;
}
}

@ -78,8 +78,8 @@ class _CapsuleHistoricScreenState extends State<CapsuleHistoricScreen> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Container( Container(
padding: const EdgeInsets.only(top: 80, left: 30, right: 30), padding: const EdgeInsets.only(top: 80, left: 60, right: 60),
constraints: const BoxConstraints( maxWidth: 700), constraints: const BoxConstraints( maxWidth: 450),
child: Align( child: Align(
alignment: Alignment.center, alignment: Alignment.center,
child: Row( child: Row(
@ -131,6 +131,7 @@ class _CapsuleHistoricScreenState extends State<CapsuleHistoricScreen> {
child: SizedBox( child: SizedBox(
width: double.infinity, width: double.infinity,
child: Container( child: Container(
padding: EdgeInsets.symmetric(horizontal: 15),
child: Column( child: Column(
children: [ children: [
HistoricComponent( HistoricComponent(

@ -612,7 +612,6 @@ class _DetailPostScreenState extends State<DetailPostScreen> {
Expanded( Expanded(
child: TextField( child: TextField(
keyboardAppearance: Brightness.dark, keyboardAppearance: Brightness.dark,
keyboardType: TextInputType.text,
controller: _textController, controller: _textController,
focusNode: myFocusNode, focusNode: myFocusNode,
onSubmitted: (value) async { onSubmitted: (value) async {
@ -627,6 +626,7 @@ class _DetailPostScreenState extends State<DetailPostScreen> {
setState(() {}); setState(() {});
}, },
cursorColor: primaryColor, cursorColor: primaryColor,
keyboardType: TextInputType.emailAddress,
style: GoogleFonts.plusJakartaSans(color: Colors.white), style: GoogleFonts.plusJakartaSans(color: Colors.white),
decoration: InputDecoration( decoration: InputDecoration(
suffixIcon: _textController.text.isEmpty suffixIcon: _textController.text.isEmpty

@ -25,15 +25,13 @@ class _FeedScreenState extends State<FeedScreen> with SingleTickerProviderStateM
late Animation<double> animation; late Animation<double> animation;
late List<Post> friendFeed; late List<Post> friendFeed;
Timer? timer; Timer? timer;
var pageFriend = 0;
late List<Post> discoveryFeed; late List<Post> discoveryFeed;
late Tuple2<List<Post>, List<Post>> displayFeed; late Tuple2<List<Post>, List<Post>> displayFeed;
bool isDismissed = true; bool isDismissed = true;
bool choiceFeed = true; bool choiceFeed = true;
PageController controller = PageController(); PageController controller = PageController();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -126,26 +124,9 @@ class _FeedScreenState extends State<FeedScreen> with SingleTickerProviderStateM
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
displayFeed = displayFeed =
Tuple2(MyApp.postViewModel.postsFriends.toList(), MyApp.postViewModel.bestPosts.toList()); Tuple2(MyApp.postViewModel.postsFriends.reversed.toList(), MyApp.postViewModel.bestPosts.reversed.toList());
bool empty = bool empty =
(choiceFeed == true && displayFeed.item1.isEmpty) || (choiceFeed == false && displayFeed.item2.isEmpty); (choiceFeed == true && displayFeed.item1.isEmpty) || (choiceFeed == false && displayFeed.item2.isEmpty);
ScrollController _scrollController = ScrollController();
_scrollController.addListener(() {
if (_scrollController.position.maxScrollExtent ==
_scrollController.position.pixels) {
print("fin");
if (choiceFeed) {
setState(() {
MyApp.postViewModel.getMorePostsFriends();
});
} else {
setState(() {
MyApp.postViewModel.getMoreBestPosts();
});
}
}
});
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
backgroundColor: bgColor, backgroundColor: bgColor,
@ -204,7 +185,6 @@ class _FeedScreenState extends State<FeedScreen> with SingleTickerProviderStateM
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
clipBehavior: Clip.none, clipBehavior: Clip.none,
shrinkWrap: false, shrinkWrap: false,
controller: _scrollController,
itemCount: displayFeed.item1.length, itemCount: displayFeed.item1.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Padding( return Padding(
@ -213,7 +193,6 @@ class _FeedScreenState extends State<FeedScreen> with SingleTickerProviderStateM
PostComponent(callback: openDetailPost, post: displayFeed.item1[index], index: index), PostComponent(callback: openDetailPost, post: displayFeed.item1[index], index: index),
); );
}, },
), ),
), ),
), ),
@ -233,7 +212,6 @@ class _FeedScreenState extends State<FeedScreen> with SingleTickerProviderStateM
triggerMode: RefreshIndicatorTriggerMode.onEdge, triggerMode: RefreshIndicatorTriggerMode.onEdge,
onRefresh: _refresh, onRefresh: _refresh,
child: ListView.builder( child: ListView.builder(
controller: _scrollController,
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
clipBehavior: Clip.none, clipBehavior: Clip.none,
shrinkWrap: false, shrinkWrap: false,

@ -52,9 +52,9 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
setState(() => canResendEmail = true); setState(() => canResendEmail = true);
} on FirebaseAuthException catch (e) { } on FirebaseAuthException catch (e) {
if (e.code == "invalid-email") { if (e.code == "invalid-email") {
error = "Format de mail incorrect";
} else if (e.code == "user-not-found") {
error = "Mail incorrect"; error = "Mail incorrect";
} else if (e.code == "user-not-found") {
error = "Format de mail incorrect";
} else if (e.code == "too-many-requests") { } else if (e.code == "too-many-requests") {
error = error =
"Trop de tentatives. Veuillez réessayer plus tard"; "Trop de tentatives. Veuillez réessayer plus tard";

@ -1,310 +1,310 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_signin_button/button_list.dart'; import 'package:flutter_signin_button/button_list.dart';
import 'package:flutter_signin_button/button_view.dart'; import 'package:flutter_signin_button/button_view.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:justmusic/main.dart'; import 'package:justmusic/main.dart';
import 'package:justmusic/values/constants.dart'; import 'package:justmusic/values/constants.dart';
import '../components/login_button.dart'; import '../components/login_button.dart';
import '../exceptions/user_exception.dart'; import '../exceptions/user_exception.dart';
class LoginScreen extends StatefulWidget { class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key); const LoginScreen({Key? key}) : super(key: key);
@override @override
State<LoginScreen> createState() => _LoginScreenState(); State<LoginScreen> createState() => _LoginScreenState();
} }
class _LoginScreenState extends State<LoginScreen> { class _LoginScreenState extends State<LoginScreen> {
bool passenable = true; bool passenable = true;
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final _userMailTextField = TextEditingController(); final _userMailTextField = TextEditingController();
final _passwordTextField = TextEditingController(); final _passwordTextField = TextEditingController();
handleLogin() async { handleLogin() async {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
try { try {
await MyApp.userViewModel.login(_userMailTextField.text, _passwordTextField.text); await MyApp.userViewModel.login(_userMailTextField.text, _passwordTextField.text);
Navigator.pushNamed(context, '/feed'); Navigator.pushNamed(context, '/feed');
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
e.toString(), 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, backgroundColor: Colors.red,
), ),
); );
} }
} }
} }
signInWithGoogle() async { signInWithGoogle() async {
try { try {
await MyApp.userViewModel.signInWithGoogle(); await MyApp.userViewModel.signInWithGoogle();
} on UserException catch (e) { } on UserException catch (e) {
if (e.code == 'user-created') { if (e.code == 'user-created') {
Navigator.pushNamed(context, '/explanation'); Navigator.pushNamed(context, '/explanation');
} else if (e.code == 'user-already-exist') { } else if (e.code == 'user-already-exist') {
Navigator.pushNamed(context, '/feed'); Navigator.pushNamed(context, '/feed');
} }
} }
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(), onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
backgroundColor: bgColor, backgroundColor: bgColor,
body: Align( body: Align(
child: SizedBox( child: SizedBox(
height: double.infinity, height: double.infinity,
width: 600, width: 600,
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Expanded( Expanded(
child: Padding( child: Padding(
padding: EdgeInsets.only(left: 40, right: 40), padding: EdgeInsets.only(left: 40, right: 40),
child: Form( child: Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Flexible( Flexible(
flex: 4, flex: 4,
child: Padding( child: Padding(
padding: EdgeInsets.only(bottom: 60), padding: EdgeInsets.only(bottom: 60),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Text(
"Te revoilà !", "Te revoilà!",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w600, fontSize: 38.h), color: Colors.white, fontWeight: FontWeight.w600, fontSize: 38.h),
), ),
SizedBox( SizedBox(
height: 10, height: 10,
), ),
SizedBox( SizedBox(
width: 230.w, width: 230.w,
child: Text( child: Text(
"Bon retour parmis nous. Tu nous as manqué !", "Bon retour parmis nous tu nous as manqué!",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 20.h), color: Colors.white, fontWeight: FontWeight.w400, fontSize: 20.h),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
], ],
), ),
), ),
), ),
Expanded( Expanded(
flex: 5, flex: 5,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
TextFormField( TextFormField(
controller: _userMailTextField, controller: _userMailTextField,
keyboardAppearance: Brightness.dark, keyboardAppearance: Brightness.dark,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'Entrez un email valide'; return 'entrez un email valide';
} }
return null; return null;
}, },
cursorColor: primaryColor, cursorColor: primaryColor,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
style: GoogleFonts.plusJakartaSans(color: primaryColor), style: GoogleFonts.plusJakartaSans(color: primaryColor),
decoration: InputDecoration( decoration: InputDecoration(
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 1, color: strokeTextField), borderSide: BorderSide(width: 1, color: strokeTextField),
borderRadius: BorderRadius.all(Radius.circular(10))), borderRadius: BorderRadius.all(Radius.circular(10))),
prefix: const Padding(padding: EdgeInsets.only(left: 20.0)), prefix: const Padding(padding: EdgeInsets.only(left: 20.0)),
suffix: const Padding(padding: EdgeInsets.only(left: 20.0)), suffix: const Padding(padding: EdgeInsets.only(left: 20.0)),
fillColor: bgTextField, fillColor: bgTextField,
filled: true, filled: true,
errorStyle: TextStyle(fontSize: 9, height: 0.3), errorStyle: TextStyle(fontSize: 9, height: 0.3),
focusColor: Color.fromRGBO(255, 255, 255, 0.30), focusColor: Color.fromRGBO(255, 255, 255, 0.30),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 1, color: strokeTextField), borderSide: BorderSide(width: 1, color: strokeTextField),
borderRadius: BorderRadius.all(Radius.circular(10))), borderRadius: BorderRadius.all(Radius.circular(10))),
hintText: 'Email', hintText: 'Email',
hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)), hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField)),
), ),
SizedBox( SizedBox(
height: 18, height: 18,
), ),
TextFormField( TextFormField(
controller: _passwordTextField, controller: _passwordTextField,
keyboardAppearance: Brightness.dark, keyboardAppearance: Brightness.dark,
obscureText: passenable, obscureText: passenable,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'Entrez un mot de passe valide'; return 'entrez un mot de passe valide';
} }
return null; return null;
}, },
cursorColor: primaryColor, cursorColor: primaryColor,
style: GoogleFonts.plusJakartaSans(color: primaryColor), style: GoogleFonts.plusJakartaSans(color: primaryColor),
decoration: InputDecoration( decoration: InputDecoration(
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 1, color: strokeTextField), borderSide: BorderSide(width: 1, color: strokeTextField),
borderRadius: BorderRadius.all(Radius.circular(10))), borderRadius: BorderRadius.all(Radius.circular(10))),
fillColor: bgTextField, fillColor: bgTextField,
filled: true, filled: true,
focusColor: Color.fromRGBO(255, 255, 255, 0.30), focusColor: Color.fromRGBO(255, 255, 255, 0.30),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 1, color: strokeTextField), borderSide: BorderSide(width: 1, color: strokeTextField),
borderRadius: BorderRadius.all(Radius.circular(10))), borderRadius: BorderRadius.all(Radius.circular(10))),
hintText: 'Mot de passe', hintText: 'Mot de passe',
hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField), hintStyle: GoogleFonts.plusJakartaSans(color: strokeTextField),
prefix: const Padding(padding: EdgeInsets.only(left: 20.0)), prefix: const Padding(padding: EdgeInsets.only(left: 20.0)),
suffixIcon: Container( suffixIcon: Container(
padding: EdgeInsets.only(right: 10), padding: EdgeInsets.only(right: 10),
margin: EdgeInsets.all(5), margin: EdgeInsets.all(5),
height: 3, height: 3,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
setState(() { setState(() {
if (passenable) { if (passenable) {
passenable = false; passenable = false;
} else { } else {
passenable = true; passenable = true;
} }
}); });
}, },
// Image tapped // Image tapped
splashColor: Colors.white10, splashColor: Colors.white10,
// Splash color over image // Splash color over image
child: Image( child: Image(
image: passenable image: passenable
? AssetImage("assets/images/show_icon.png") ? AssetImage("assets/images/show_icon.png")
: AssetImage("assets/images/hide_icon.png"), : AssetImage("assets/images/hide_icon.png"),
height: 2, height: 2,
), ),
)), )),
errorStyle: TextStyle(fontSize: 9, height: 0.3), errorStyle: TextStyle(fontSize: 9, height: 0.3),
), ),
), ),
GestureDetector( GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () { onTap: () {
Navigator.pushNamed(context, '/forgetPassword'); Navigator.pushNamed(context, '/forgetPassword');
}, },
child: Padding( child: Padding(
padding: EdgeInsets.only(top: 10), padding: EdgeInsets.only(top: 10),
child: Text( child: Text(
"Mot de passe oublié ?", "Mot de passe oublié?",
style: GoogleFonts.plusJakartaSans(color: Colors.white), style: GoogleFonts.plusJakartaSans(color: Colors.white),
), ),
)), )),
SizedBox( SizedBox(
height: defaultPadding, height: defaultPadding,
), ),
SizedBox( SizedBox(
width: 600, width: 600,
child: LoginButton( child: LoginButton(
callback: handleLogin, callback: handleLogin,
text: "Se connecter", text: "Se connecter",
)), )),
Align( Align(
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () { onTap: () {
Navigator.pushNamed(context, '/register'); Navigator.pushNamed(context, '/register');
}, },
child: Padding( child: Padding(
padding: EdgeInsets.only(top: 20), padding: EdgeInsets.only(top: 20),
child: RichText( child: RichText(
textAlign: TextAlign.center, textAlign: TextAlign.center,
text: TextSpan( text: TextSpan(
text: 'Pas encore inscrit ?', text: 'Pas encore inscrit?',
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 15), fontSize: 15),
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
text: " Sinscrire", text: " Sinscire",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
fontSize: 15, fontSize: 15,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: primaryColor)), color: primaryColor)),
], ],
), ),
), ),
), ),
), ),
), ),
], ],
), ),
), ),
Expanded( Expanded(
flex: 3, flex: 3,
child: Padding( child: Padding(
padding: EdgeInsets.only(top: 20), padding: EdgeInsets.only(top: 20),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints(maxWidth: 600), constraints: BoxConstraints(maxWidth: 600),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
Expanded( Expanded(
child: Container( child: Container(
color: Color(0xFF3D3D3D), color: Color(0xFF3D3D3D),
height: 1, height: 1,
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
left: defaultPadding, right: defaultPadding), left: defaultPadding, right: defaultPadding),
child: Text( child: Text(
'Ou', 'Ou',
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.bold), color: Colors.white, fontWeight: FontWeight.bold),
), ),
), ),
Expanded( Expanded(
child: Container( child: Container(
height: 1, height: 1,
color: Color(0xFF3D3D3D), color: Color(0xFF3D3D3D),
)), )),
], ],
), ),
), ),
SizedBox(height: defaultPadding), SizedBox(height: defaultPadding),
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints(maxWidth: 540), constraints: BoxConstraints(maxWidth: 540),
child: SizedBox( child: SizedBox(
width: 300.sp, width: 300.sp,
height: 50, height: 50,
child: SignInButton( child: SignInButton(
Buttons.Google, Buttons.Google,
text: "Login with Google", text: "Login with Google",
onPressed: signInWithGoogle, onPressed: signInWithGoogle,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20))), borderRadius: BorderRadius.all(Radius.circular(20))),
), ),
), ),
), ),
], ],
), ),
)) ))
], ],
)))) ))))
], ],
)), )),
))); )));
} }
} }

@ -2,7 +2,6 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:justmusic/services/AuthService.dart';
import 'package:justmusic/values/icons.dart'; import 'package:justmusic/values/icons.dart';
import '../components/profile_component.dart'; import '../components/profile_component.dart';
import '../components/setting_part_component.dart'; import '../components/setting_part_component.dart';
@ -33,40 +32,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
Navigator.of(context).push(routeUser(MyApp.userViewModel.userCurrent)); Navigator.of(context).push(routeUser(MyApp.userViewModel.userCurrent));
} }
void openConfirmationDelete() { void _openPassword() {
showCupertinoModalPopup<void>(
context: context,
barrierColor: Colors.black.withOpacity(0.7),
builder: (BuildContext context) => Container(
child: CupertinoActionSheet(
title: Text(
'Supprimer mon compte',
style: GoogleFonts.plusJakartaSans(fontWeight: FontWeight.bold),
),
actions: <CupertinoActionSheetAction>[
CupertinoActionSheetAction(
onPressed: () {
MyApp.userViewModel.delete();
Navigator.pop(context);
Navigator.of(context).push(routeWelcome());
},
child: Text('Confirmer', style: TextStyle(color: Colors.blue),),
),
],
cancelButton: CupertinoActionSheetAction(
isDestructiveAction: true,
onPressed: () {
Navigator.pop(context);
},
child: const Text('Annuler'),
),
),
),
);
}
void openPassword() {
Navigator.of(context).push(routePassword()); Navigator.of(context).push(routePassword());
} }
@ -156,12 +122,12 @@ class _ProfileScreenState extends State<ProfileScreen> {
SettingPartComponent( SettingPartComponent(
icon: JustMusicIcon.password, icon: JustMusicIcon.password,
label: 'Modifier mon mot de passe', label: 'Modifier mon mot de passe',
action: openPassword, action: _openPassword,
), ),
SettingPartComponent( const SettingPartComponent(
icon: JustMusicIcon.trash, icon: JustMusicIcon.trash,
label: 'Supprimer mon compte', label: 'Supprimer mon compte',
action: openConfirmationDelete, action: null,
), ),
SettingPartComponent( SettingPartComponent(
icon: JustMusicIcon.cross, icon: JustMusicIcon.cross,

@ -1,98 +1,98 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:justmusic/values/constants.dart'; import 'package:justmusic/values/constants.dart';
import '../components/join_button.dart'; import '../components/join_button.dart';
class WellcomeScreen extends StatelessWidget { class WellcomeScreen extends StatelessWidget {
const WellcomeScreen({Key? key}) : super(key: key); const WellcomeScreen({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: Container( body: Container(
padding: EdgeInsets.all(defaultPadding), padding: EdgeInsets.all(defaultPadding),
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
decoration: const BoxDecoration( decoration: const BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage("assets/images/wellcome_background.png"), image: AssetImage("assets/images/wellcome_background.png"),
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
child: Align( child: Align(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
flex: 10, flex: 10,
child: Padding( child: Padding(
padding: EdgeInsets.only(bottom: 100), padding: EdgeInsets.only(bottom: 100),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Bienvenue sur,", "Bienvenue sur,",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 34), fontSize: 34),
), ),
Image( Image(
image: AssetImage("assets/images/logo.png"), image: AssetImage("assets/images/logo.png"),
width: 230, width: 230,
), ),
SizedBox( SizedBox(
height: 25, height: 25,
), ),
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints(maxWidth: 520), constraints: BoxConstraints(maxWidth: 520),
child: Text( child: Text(
"Explore les nouvelles découvertes musicales de tes amis, et partage leur ton mood.", "Explore les nouvelles découvertes musicales de tes amis, et partage leur ton mood.",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w200, fontWeight: FontWeight.w200,
fontSize: 15), fontSize: 15),
), ),
), ),
], ],
), ),
), ),
), ),
Expanded( Expanded(
flex: 3, flex: 3,
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
JoinButton(), JoinButton(),
SizedBox( SizedBox(
height: defaultPadding, height: defaultPadding,
), ),
GestureDetector( GestureDetector(
onTap: () { onTap: () {
Navigator.pushNamed(context, '/login'); Navigator.pushNamed(context, '/login');
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.all(3.0), padding: const EdgeInsets.all(3.0),
child: Text( child: Text(
"Tu as déja un compte ? Connexion", "Tu as déja un compte? Connexion",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 15), fontSize: 15),
), ),
), ),
), ),
], ],
), ),
), ),
], ],
), ),
) /* add child content here */, ) /* add child content here */,
), ),
); );
} }
} }

@ -1,33 +0,0 @@
import 'package:cloud_firestore/cloud_firestore.dart';
class CapsuleService {
Future<List<bool>> recapSevenDays(String id) async {
List<bool> recapList = [];
DateTime sevenDaysAgo = DateTime.now().subtract(Duration(days: 6));
QuerySnapshot<Map<String, dynamic>> response = await FirebaseFirestore
.instance
.collection("capsules")
.where("user_id", isEqualTo: id)
.get();
List<Map<String, dynamic>?> capsuleList = response.docs
.map((DocumentSnapshot<Map<String, dynamic>> doc) => doc.data())
.toList();
for (int i = 0; i < 7; i++) {
DateTime date = sevenDaysAgo.add(Duration(days: i));
bool capsuleExists = capsuleList.any((post) =>
post?["date"] != null &&
post?["date"].toDate().year == date.year &&
post?["date"].toDate().month == date.month &&
post?["date"].toDate().day == date.day);
recapList.add(capsuleExists);
}
return recapList;
}
}

@ -37,7 +37,7 @@ class MusicService {
List<Tuple2<int, String>> capsules = []; List<Tuple2<int, String>> capsules = [];
var querySnapshot = await FirebaseFirestore.instance var querySnapshot = await FirebaseFirestore.instance
.collection('capsules') .collection('posts')
.where('user_id', isEqualTo: idUser) .where('user_id', isEqualTo: idUser)
.where('date', isGreaterThanOrEqualTo: DateTime(year, month)) .where('date', isGreaterThanOrEqualTo: DateTime(year, month))
.where('date', isLessThan: DateTime(year, month + 1)) .where('date', isLessThan: DateTime(year, month + 1))

@ -23,15 +23,6 @@ class PostService {
var userRef = MyApp.db.collection("users").doc(id); var userRef = MyApp.db.collection("users").doc(id);
var capsule = {
"user_id": id,
"date": DateTime.now(),
"place": [location?.item1, location?.item2],
"song_id": idMusic,
};
await MyApp.db.collection("capsules").doc(postAdd.id).set(capsule);
await MyApp.db.runTransaction((transaction) async { await MyApp.db.runTransaction((transaction) async {
var userSnapshot = await transaction.get(userRef); var userSnapshot = await transaction.get(userRef);
if (userSnapshot.exists) { if (userSnapshot.exists) {
@ -51,41 +42,16 @@ class PostService {
deletePost() {} deletePost() {}
Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPopularPosts(int limit) async { Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPopularPosts(
DateTime twentyFourHoursAgo = DateTime.now().subtract(Duration(hours: 24)); {int limit = 10,
var response = await FirebaseFirestore.instance QueryDocumentSnapshot<Map<String, dynamic>>? offset}) async {
.collection("posts")
.where("date", isGreaterThan: twentyFourHoursAgo)
.orderBy("date", descending: true)
.limit(limit)
.get();
MyApp.postViewModel.lastPostDiscovery = response.docs.isNotEmpty
? response.docs.last
: MyApp.postViewModel.lastPostDiscovery;
var filteredPosts = response.docs.where((doc) {
String user = doc["user_id"];
return user != MyApp.userViewModel.userCurrent.id;
}).toList();
return filteredPosts;
}
Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getMorePopularPosts(int limit) async {
DateTime twentyFourHoursAgo = DateTime.now().subtract(Duration(hours: 24));
QuerySnapshot<Map<String, dynamic>> response; QuerySnapshot<Map<String, dynamic>> response;
response = await FirebaseFirestore.instance response = await FirebaseFirestore.instance
.collection("posts") .collection("posts")
.where("date", isGreaterThan: twentyFourHoursAgo) .orderBy("date")
.orderBy("date", descending: true)
.limit(limit) .limit(limit)
.startAfterDocument(MyApp.postViewModel.lastPostDiscovery)
.get(); .get();
MyApp.postViewModel.lastPostDiscovery = response.docs.isNotEmpty
? response.docs.last
: MyApp.postViewModel.lastPostDiscovery;
var filteredPosts = response.docs.where((doc) { var filteredPosts = response.docs.where((doc) {
String user = doc["user_id"]; String user = doc["user_id"];
return user != MyApp.userViewModel.userCurrent.id; return user != MyApp.userViewModel.userCurrent.id;
@ -93,41 +59,18 @@ class PostService {
return filteredPosts; return filteredPosts;
} }
Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPostsFriends(int limit) async { Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPostsFriends(
var response = await FirebaseFirestore.instance {int limit = 10, int offset = 0}) async {
.collection("posts")
.where("user_id", whereIn: [
MyApp.userViewModel.userCurrent.id,
...MyApp.userViewModel.userCurrent.followed
])
.where("")
.orderBy("date", descending: true)
.limit(limit)
.get();
MyApp.postViewModel.lastPostFriend = response.docs.isNotEmpty
? response.docs.last
: MyApp.postViewModel.lastPostFriend;
return response.docs;
}
Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getMorePostsFriends(int limit) async {
var response = await FirebaseFirestore.instance var response = await FirebaseFirestore.instance
.collection("posts") .collection("posts")
.where("user_id", whereIn: [ .where("user_id", whereIn: [
MyApp.userViewModel.userCurrent.id, MyApp.userViewModel.userCurrent.id,
...MyApp.userViewModel.userCurrent.followed ...MyApp.userViewModel.userCurrent.followed
]) ])
.orderBy("date", descending: true) .orderBy("date")
.limit(limit) .limit(limit)
.startAfterDocument(MyApp.postViewModel.lastPostFriend)
.get(); .get();
MyApp.postViewModel.lastPostFriend = response.docs.isNotEmpty
? response.docs.last
: MyApp.postViewModel.lastPostFriend;
return response.docs; return response.docs;
} }
@ -150,6 +93,35 @@ class PostService {
return !isTodayAvailable; return !isTodayAvailable;
} }
Future<List<bool>> recapSevenDays(String id) async {
List<bool> recapList = [];
DateTime sevenDaysAgo = DateTime.now().subtract(Duration(days: 6));
QuerySnapshot<Map<String, dynamic>> response = await FirebaseFirestore
.instance
.collection("posts")
.where("user_id", isEqualTo: id)
.get();
List<Map<String, dynamic>?> postList = response.docs
.map((DocumentSnapshot<Map<String, dynamic>> doc) => doc.data())
.toList();
for (int i = 0; i < 7; i++) {
DateTime date = sevenDaysAgo.add(Duration(days: i));
bool postExists = postList.any((post) =>
post?["date"] != null &&
post?["date"].toDate().year == date.year &&
post?["date"].toDate().month == date.month &&
post?["date"].toDate().day == date.day);
recapList.add(postExists);
}
return recapList;
}
Future<List<String>> getLikesByPostId(String id) async { Future<List<String>> getLikesByPostId(String id) async {
var response = var response =
await FirebaseFirestore.instance.collection("posts").doc(id).get(); await FirebaseFirestore.instance.collection("posts").doc(id).get();

@ -24,7 +24,6 @@ const searchBarColor = Color(0xFF161616);
const postbutton = Color(0xFF1B1B1B); const postbutton = Color(0xFF1B1B1B);
const fillButton = Color(0xFF633AF4); const fillButton = Color(0xFF633AF4);
const selectedButton = Color(0xFF1F1B2E); const selectedButton = Color(0xFF1F1B2E);
const tooltipBackground = Color(0xFF2D2D2D);
// All constants important too us // All constants important too us
const defaultPadding = 30.0; const defaultPadding = 30.0;

@ -241,13 +241,9 @@ class MusicViewModel {
var musics = await getMusicsWithIds(capsulesData.map((capsule) => capsule.item2).toList()); var musics = await getMusicsWithIds(capsulesData.map((capsule) => capsule.item2).toList());
for (var capsule in capsulesData) { for (var capsule in capsulesData) {
var music = musics.firstWhere( var music = musics.firstWhere((music) => music.id == capsule.item2);
(music) => music.id == capsule.item2, print(capsule.item1);
orElse: () => Music("-1", "", "", "", 0, 0, false, []), capsules.add(Tuple2(capsule.item1, music));
);
if (music.id != "-1")
capsules.add(Tuple2(capsule.item1, music));
} }
return capsules; return capsules;
} catch (e) { } catch (e) {

@ -1,7 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:justmusic/model/Post.dart'; import 'package:justmusic/model/Post.dart';
import 'package:justmusic/services/CapsuleService.dart';
import 'package:justmusic/services/PostService.dart'; import 'package:justmusic/services/PostService.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -12,10 +11,7 @@ import '../model/mapper/PostMapper.dart';
class PostViewModel { class PostViewModel {
List<Post> _postsFriends = []; List<Post> _postsFriends = [];
List<Post> _bestPosts = []; List<Post> _bestPosts = [];
var lastPostFriend;
var lastPostDiscovery;
final PostService _postService = PostService(); final PostService _postService = PostService();
final CapsuleService _capsuleService = CapsuleService();
// Constructor // Constructor
PostViewModel(); PostViewModel();
@ -30,10 +26,10 @@ class PostViewModel {
await _postService.createPost(description, idMusic, image, location); await _postService.createPost(description, idMusic, image, location);
} }
Future<List<Post>> getPostsFriends({int limit = 10}) async { Future<List<Post>> getPostsFriends() async {
try { try {
_postsFriends = []; _postsFriends = [];
var responseData = await _postService.getPostsFriends(limit); var responseData = await _postService.getPostsFriends();
List<String> ids = []; List<String> ids = [];
var postsFutures = responseData.map((value) { var postsFutures = responseData.map((value) {
ids.add(value.data()["song_id"]); ids.add(value.data()["song_id"]);
@ -44,7 +40,7 @@ class PostViewModel {
for (int i = 0; i < posts.length; i++) { for (int i = 0; i < posts.length; i++) {
posts[i].music = musics[i]; posts[i].music = musics[i];
} }
_postsFriends.addAll(posts); _postsFriends = posts;
return _postsFriends; return _postsFriends;
} catch (e) { } catch (e) {
print(e); print(e);
@ -53,29 +49,13 @@ class PostViewModel {
} }
} }
void getMorePostsFriends({int limit = 10}) async { List<Post> getMorePostsFriends() {
try { throw new Error();
var responseData = await _postService.getMorePostsFriends(limit);
List<String> ids = [];
var postsFutures = responseData.map((value) {
ids.add(value.data()["song_id"]);
return PostMapper.toModel(value);
}).toList();
var posts = await Future.wait(postsFutures);
List<Music> musics = await MyApp.musicViewModel.getMusicsWithIds(ids);
for (int i = 0; i < posts.length; i++) {
posts[i].music = musics[i];
}
_postsFriends.addAll(posts);
} catch (e) {
print(e);
}
} }
Future<List<Post>> getBestPosts({int limit = 10}) async { Future<List<Post>> getBestPosts() async {
try { try {
_bestPosts = []; var responseData = await _postService.getPopularPosts();
var responseData = await _postService.getPopularPosts(limit);
List<String> ids = []; List<String> ids = [];
var postsFutures = responseData.map((value) async { var postsFutures = responseData.map((value) async {
ids.add(value.data()["song_id"]); ids.add(value.data()["song_id"]);
@ -86,7 +66,7 @@ class PostViewModel {
for (int i = 0; i < posts.length; i++) { for (int i = 0; i < posts.length; i++) {
posts[i].music = musics[i]; posts[i].music = musics[i];
} }
_bestPosts.addAll(posts); _bestPosts = posts;
return _bestPosts; return _bestPosts;
} catch (e) { } catch (e) {
print(e); print(e);
@ -95,28 +75,13 @@ class PostViewModel {
} }
} }
void getMoreBestPosts({int limit = 10}) async { List<Post> getMoreBestPosts() {
try { throw new Error();
var responseData = await _postService.getMorePopularPosts(limit);
List<String> ids = [];
var postsFutures = responseData.map((value) async {
ids.add(value.data()["song_id"]);
return await PostMapper.toModel(value);
}).toList();
var posts = await Future.wait(postsFutures);
List<Music> musics = await MyApp.musicViewModel.getMusicsWithIds(ids);
for (int i = 0; i < posts.length; i++) {
posts[i].music = musics[i];
}
_bestPosts.addAll(posts);
} catch (e) {
print(e);
}
} }
Future<List<bool>> recapSevenDays(String id) async { Future<List<bool>> recapSevenDays(String id) async {
try { try {
return await _capsuleService.recapSevenDays(id); return await _postService.recapSevenDays(id);
} catch (e) { } catch (e) {
print(e); print(e);
rethrow; rethrow;
@ -147,6 +112,7 @@ class PostViewModel {
print(bool); print(bool);
return bool; return bool;
} catch (e) { } catch (e) {
print("haaaaaaaaa");
rethrow; rethrow;
} }
} }

@ -784,6 +784,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.9.0" version: "2.9.0"
image_picker_web:
dependency: "direct main"
description:
name: image_picker_web
sha256: e1656f1ce48a614aefdf22ab73c0cc7e498fa7b78893ffdcc83171e7289092e0
url: "https://pub.dev"
source: hosted
version: "3.1.1"
image_picker_windows: image_picker_windows:
dependency: transitive dependency: transitive
description: description:

@ -78,6 +78,7 @@ dependencies:
google_sign_in: ^6.1.4 google_sign_in: ^6.1.4
flutter_launcher_icons: ^0.13.1 flutter_launcher_icons: ^0.13.1
fullscreen_window: ^1.0.3 fullscreen_window: ^1.0.3
image_picker_web: ^3.1.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save