Merge branch 'PROFIL_PAGE_LDE'
continuous-integration/drone/push Build is passing Details

FAVORITE_MUSICS_EKA^2
Lucas Delanier 2 years ago
commit 9c3f3024cc

@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.justmusic"> package="com.example.justmusic">
<application <application
android:label="justmusic" android:label="JustMUSIC"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">

@ -44,7 +44,7 @@ class _ButtonPlayComponentState extends State<ButtonPlayComponent> {
child: Icon( child: Icon(
isPlaying ? Icons.pause_circle : Icons.play_circle, isPlaying ? Icons.pause_circle : Icons.play_circle,
color: Colors.white, color: Colors.white,
size: 53, size: 45,
), ),
)); ));
} }

@ -1,8 +1,6 @@
import 'dart:io'; import 'dart:io';
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:circular_reveal_animation/circular_reveal_animation.dart';
import 'package:flutter/Material.dart'; import 'package:flutter/Material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -143,8 +141,14 @@ class _EditablePostComponentState extends State<EditablePostComponent> with Tick
// implement image // implement image
child: widget.music == null child: widget.music == null
? Container( ? Container(
color: grayColor,
width: double.infinity, width: double.infinity,
child: Center(
child: Icon(
Icons.headphones,
color: grayColor.withOpacity(0.4),
size: 150,
),
),
) )
: Image( : Image(
image: NetworkImage(widget.music?.cover ?? ""), image: NetworkImage(widget.music?.cover ?? ""),

@ -0,0 +1,52 @@
import 'package:flutter/Material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../values/constants.dart';
class LittleCapsule extends StatelessWidget {
final bool isEmpty;
final DateTime date;
const LittleCapsule({super.key, required this.isEmpty, required this.date});
@override
Widget build(BuildContext context) {
if (isEmpty) {
return Flexible(
child: Container(
constraints: BoxConstraints(maxWidth: 45, maxHeight: 45),
decoration: BoxDecoration(
color: searchBarColor,
borderRadius: BorderRadius.circular(5),
border: Border.all(color: Color(0xFF282828), width: 1),
),
child: const Center(
child: Icon(
Icons.rocket_launch,
color: Color(0xFF464646),
size: 18,
),
),
),
);
}
return Flexible(
child: Container(
constraints: BoxConstraints(maxWidth: 45, maxHeight: 45),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [bgModal, bgModal.withOpacity(0)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [0, 1]),
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: Text(
date.day.toString(),
style: GoogleFonts.plusJakartaSans(color: Color(0xFF464646), fontWeight: FontWeight.w800, fontSize: 17),
),
),
),
);
}
}

@ -3,6 +3,7 @@ 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:gradient_borders/box_borders/gradient_box_border.dart'; import 'package:gradient_borders/box_borders/gradient_box_border.dart';
import 'package:justmusic/components/profil_picture_component.dart';
import 'package:text_scroll/text_scroll.dart'; import 'package:text_scroll/text_scroll.dart';
import 'package:zoom_tap_animation/zoom_tap_animation.dart'; import 'package:zoom_tap_animation/zoom_tap_animation.dart';
@ -39,170 +40,157 @@ class _PostComponentState extends State<PostComponent> with TickerProviderStateM
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
onTap: switchChoice, onTap: switchChoice,
child: LayoutBuilder( child: SizedBox(
builder: (BuildContext context, BoxConstraints constraints) { width: double.infinity,
if (widget.callback == null) { child: Column(
return SizedBox( children: [
width: double.infinity, Row(
child: Column( crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Row( ProfilPictureComponent(user: widget.post.user),
crossAxisAlignment: CrossAxisAlignment.end, Expanded(
children: [ flex: 8,
ClipOval( child: Padding(
child: SizedBox.fromSize( padding: const EdgeInsets.only(left: 10),
// Image radius child: Column(
child: Image( crossAxisAlignment: CrossAxisAlignment.start,
image: NetworkImage(widget.post.user.pp), children: [
width: 40, Text(
widget.post.user.pseudo,
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w600),
), ),
), widget.post.location.item2 != null
? Text(
"${widget.post.location.item1}, ${widget.post.location.item2}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
fontSize: 13),
)
: Text(
"",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
fontSize: 13),
)
],
), ),
Expanded( ),
flex: 8, ),
child: Padding( DateTime(today.year, today.month, today.day).isAtSameMomentAs(
padding: const EdgeInsets.only(left: 10), DateTime(widget.post.date.year, widget.post.date.month, widget.post.date.day))
child: Column( ? Text(
crossAxisAlignment: CrossAxisAlignment.start, "Aujourd'hui, ${widget.post.date.hour}:${widget.post.date.minute}",
children: [ style: GoogleFonts.plusJakartaSans(
Text( color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
widget.post.user.pseudo, )
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w600), : Text(
), "hier, ${widget.post.date.hour}:${widget.post.date.minute}",
widget.post.location.item2 != null style: GoogleFonts.plusJakartaSans(
? Text( color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
"${widget.post.location.item1}, ${widget.post.location.item2}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
fontSize: 13),
)
: Text(
"",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
fontSize: 13),
)
],
),
), ),
],
),
SizedBox(height: 10),
ZoomTapAnimation(
onTap: () {
widget.callback!(widget.post);
},
enableLongTapRepeatEvent: false,
longTapRepeatDuration: const Duration(milliseconds: 100),
begin: 1.0,
end: 0.99,
beginDuration: const Duration(milliseconds: 70),
endDuration: const Duration(milliseconds: 100),
beginCurve: Curves.decelerate,
endCurve: Curves.easeInOutSine,
child: AspectRatio(
aspectRatio: 1 / 1,
child: Container(
decoration: BoxDecoration(
// add border
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Colors.transparent,
Color(0xFF323232),
], begin: Alignment.topCenter, end: Alignment.bottomCenter),
width: 2.5,
),
// set border radius
borderRadius: BorderRadius.circular(20),
), ),
DateTime(today.year, today.month, today.day).isAtSameMomentAs( child: ClipRRect(
DateTime(widget.post.date.year, widget.post.date.month, widget.post.date.day)) borderRadius: BorderRadius.circular(18),
? Text( // implement image
"Aujourd'hui, ${widget.post.date.hour}:${widget.post.date.minute}", child: Stack(
style: GoogleFonts.plusJakartaSans( alignment: Alignment.bottomCenter,
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13), children: [
) Image(
: Text( image: NetworkImage(widget.post.music.cover!),
"${widget.post.date.day}/${widget.post.date.month}/${widget.post.date.year}-${widget.post.date.hour}:${widget.post.date.minute}", fit: BoxFit.cover,
style: GoogleFonts.plusJakartaSans( width: double.infinity,
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
), ),
], Image(
), image: AssetImage("assets/images/shadow_post.png"),
SizedBox(height: 10), opacity: AnimationController(vsync: this, value: 0.7),
ZoomTapAnimation( fit: BoxFit.fitHeight,
onTap: () { width: double.infinity,
if (widget.post.selfie != null) {
switchChoice();
}
},
enableLongTapRepeatEvent: false,
longTapRepeatDuration: const Duration(milliseconds: 100),
begin: 1.0,
end: 0.99,
beginDuration: const Duration(milliseconds: 70),
endDuration: const Duration(milliseconds: 100),
beginCurve: Curves.decelerate,
endCurve: Curves.easeInOutSine,
child: AspectRatio(
aspectRatio: 1 / 1,
child: Container(
decoration: BoxDecoration(
// add border
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Colors.transparent,
Color(0xFF323232),
], begin: Alignment.topCenter, end: Alignment.bottomCenter),
width: 2.5,
), ),
// set border radius widget.post.description == null
borderRadius: BorderRadius.circular(20), ? Container()
), : Padding(
child: ClipRRect( padding: EdgeInsets.all(15),
borderRadius: BorderRadius.circular(18), child: AutoSizeText(
// implement image '${widget.post.description}',
child: Stack( style: GoogleFonts.plusJakartaSans(
alignment: Alignment.bottomCenter, color: Colors.white, fontWeight: FontWeight.w400, fontSize: 15.sp),
children: [ maxFontSize: 20,
Image( maxLines: 1,
image: NetworkImage(choice ? widget.post.selfie! : widget.post.music.cover!), ),
fit: BoxFit.cover, ),
width: double.infinity, widget.post.selfie != null
), ? Positioned(
widget.post.selfie != null top: 0,
? Positioned( right: 0,
top: 0, child: Padding(
right: 0, padding: EdgeInsets.all(12),
child: Padding( child: Container(
padding: EdgeInsets.all(12), constraints: BoxConstraints(maxWidth: 140, maxHeight: 140),
child: Container( width: 90.sp,
constraints: BoxConstraints(maxWidth: 140, maxHeight: 140), height: 90.sp,
width: 90.sp, decoration: BoxDecoration(
height: 90.sp, color: Colors.white,
decoration: BoxDecoration( // add border
color: Colors.white, border: Border.all(width: 3, color: Colors.white),
// add border // set border radius
border: Border.all(width: 3, color: Colors.white), borderRadius: BorderRadius.circular(15),
// set border radius ),
borderRadius: BorderRadius.circular(15), child: ClipRRect(
), borderRadius: BorderRadius.circular(13),
child: ClipRRect( // implement image
borderRadius: BorderRadius.circular(13), child: Image(
// implement image image: NetworkImage(widget.post.selfie!),
child: Image( fit: BoxFit.cover,
image: NetworkImage(
choice ? widget.post.music.cover! : widget.post.selfie!),
fit: BoxFit.cover,
),
),
), ),
)) ),
: Container(), ),
], ))
), : Container(),
), ],
), ),
)), ),
SizedBox(height: 15), ),
)),
SizedBox(height: 15),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Flexible(
flex: 8,
child: TextScroll(
widget.post.music.artists.first.name!,
style: GoogleFonts.plusJakartaSans(
height: 1, color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
mode: TextScrollMode.endless,
pauseBetween: Duration(milliseconds: 500),
velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
)),
Padding(
padding: EdgeInsets.only(bottom: 10.h, right: 5.w, left: 5.w),
child: ClipOval(
child: Container(
width: 5.h,
height: 5.h,
color: Colors.white,
),
),
),
Expanded( Expanded(
flex: 8, flex: 8,
child: Padding( child: Padding(
@ -210,7 +198,7 @@ class _PostComponentState extends State<PostComponent> with TickerProviderStateM
child: TextScroll( child: TextScroll(
widget.post.music.title!, widget.post.music.title!,
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
height: 1, color: Colors.white, fontWeight: FontWeight.w300, fontSize: 16.h), height: 1, color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
mode: TextScrollMode.endless, mode: TextScrollMode.endless,
velocity: Velocity(pixelsPerSecond: Offset(50, 20)), velocity: Velocity(pixelsPerSecond: Offset(50, 20)),
pauseBetween: Duration(milliseconds: 500), pauseBetween: Duration(milliseconds: 500),
@ -220,219 +208,23 @@ class _PostComponentState extends State<PostComponent> with TickerProviderStateM
AutoSizeText( AutoSizeText(
widget.post.music.date.toString(), widget.post.music.date.toString(),
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.5), fontWeight: FontWeight.w300, fontSize: 16.h), color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
textAlign: TextAlign.end, textAlign: TextAlign.end,
maxFontSize: 20, maxFontSize: 20,
), ),
], ],
), ),
], TextScroll(
)); widget.post.music.artists.first.name!,
} style: GoogleFonts.plusJakartaSans(
height: 1, color: Colors.white.withOpacity(0.5), fontWeight: FontWeight.w300, fontSize: 16.h),
return SizedBox( mode: TextScrollMode.endless,
width: double.infinity, pauseBetween: Duration(milliseconds: 500),
child: Column( velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
ClipOval(
child: SizedBox.fromSize(
// Image radius
child: Image(
image: NetworkImage(widget.post.user.pp),
width: 40,
),
),
),
Expanded(
flex: 8,
child: Padding(
padding: const EdgeInsets.only(left: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.post.user.pseudo,
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w600),
),
widget.post.location.item2 != null
? Text(
"${widget.post.location.item1}, ${widget.post.location.item2}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
fontSize: 13),
)
: Text(
"",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
fontSize: 13),
)
],
),
),
),
DateTime(today.year, today.month, today.day).isAtSameMomentAs(
DateTime(widget.post.date.year, widget.post.date.month, widget.post.date.day))
? Text(
"Aujourd'hui, ${widget.post.date.hour}:${widget.post.date.minute}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
)
: Text(
"hier, ${widget.post.date.hour}:${widget.post.date.minute}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
),
],
),
SizedBox(height: 10),
ZoomTapAnimation(
onTap: () {
widget.callback!(widget.post);
},
enableLongTapRepeatEvent: false,
longTapRepeatDuration: const Duration(milliseconds: 100),
begin: 1.0,
end: 0.99,
beginDuration: const Duration(milliseconds: 70),
endDuration: const Duration(milliseconds: 100),
beginCurve: Curves.decelerate,
endCurve: Curves.easeInOutSine,
child: AspectRatio(
aspectRatio: 1 / 1,
child: Container(
decoration: BoxDecoration(
// add border
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Colors.transparent,
Color(0xFF323232),
], begin: Alignment.topCenter, end: Alignment.bottomCenter),
width: 2.5,
),
// set border radius
borderRadius: BorderRadius.circular(20),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(18),
// implement image
child: Stack(
alignment: Alignment.bottomCenter,
children: [
Image(
image: NetworkImage(widget.post.music.cover!),
fit: BoxFit.cover,
width: double.infinity,
),
Image(
image: AssetImage("assets/images/shadow_post.png"),
opacity: AnimationController(vsync: this, value: 0.7),
fit: BoxFit.fitHeight,
width: double.infinity,
),
widget.post.description == null
? Container()
: Padding(
padding: EdgeInsets.all(15),
child: AutoSizeText(
'${widget.post.description}',
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 15.sp),
maxFontSize: 20,
maxLines: 1,
),
),
widget.post.selfie != null
? Positioned(
top: 0,
right: 0,
child: Padding(
padding: EdgeInsets.all(12),
child: Container(
constraints: BoxConstraints(maxWidth: 140, maxHeight: 140),
width: 90.sp,
height: 90.sp,
decoration: BoxDecoration(
color: Colors.white,
// add border
border: Border.all(width: 3, color: Colors.white),
// set border radius
borderRadius: BorderRadius.circular(15),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(13),
// implement image
child: Image(
image: NetworkImage(widget.post.selfie!),
fit: BoxFit.cover,
),
),
),
))
: Container(),
],
),
),
),
)),
SizedBox(height: 15),
SizedBox(
height: 40,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 8,
child: Padding(
padding: EdgeInsets.only(bottom: 2),
child: TextScroll(
widget.post.music.title!,
style: GoogleFonts.plusJakartaSans(
height: 1, color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
mode: TextScrollMode.endless,
velocity: Velocity(pixelsPerSecond: Offset(50, 20)),
pauseBetween: Duration(milliseconds: 500),
),
)),
Container(width: 10),
AutoSizeText(
widget.post.music.date.toString(),
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
textAlign: TextAlign.end,
maxFontSize: 20,
),
],
),
Expanded(
flex: 8,
child: TextScroll(
widget.post.music.artists.first.name!,
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white.withOpacity(0.5),
fontWeight: FontWeight.w300,
fontSize: 16.h),
mode: TextScrollMode.endless,
pauseBetween: Duration(milliseconds: 500),
velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
)),
],
), ),
) ],
], ),
)); ],
}, )));
),
);
} }
} }

@ -0,0 +1,33 @@
import 'package:flutter/Material.dart';
import 'package:justmusic/screens/user_screen.dart';
import '../config/routes.dart';
import '../model/User.dart';
class ProfilPictureComponent extends StatelessWidget {
final User user;
const ProfilPictureComponent({super.key, required this.user});
void _openDetail(BuildContext context) {
print("cc");
Navigator.of(context).push(routeUser(user));
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
_openDetail(context);
},
child: ClipOval(
child: SizedBox.fromSize(
// Image radius
child: Image(
image: NetworkImage(user.pp),
width: 40,
),
),
),
);
}
}

@ -1,6 +1,7 @@
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/components/profil_picture_component.dart';
import '../main.dart'; import '../main.dart';
import '../model/User.dart'; import '../model/User.dart';
import '../values/constants.dart'; import '../values/constants.dart';
@ -23,13 +24,7 @@ class _ProfileListComponentState extends State<ProfileListComponent> {
padding: const EdgeInsets.only(bottom: 5), padding: const EdgeInsets.only(bottom: 5),
child: Row( child: Row(
children: [ children: [
ClipOval( ProfilPictureComponent(user: widget.user),
child: FadeInImage.assetNetwork(
height: 50,
width: 50,
fit: BoxFit.cover,
placeholder: "assets/images/loadingPlaceholder.gif",
image: widget.user.pp)),
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),

@ -0,0 +1,125 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/Material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../main.dart';
import '../model/User.dart' as justMusic;
import '../values/constants.dart';
import 'little_post_recap_component.dart';
class RecapComponent extends StatelessWidget {
final justMusic.User user;
const RecapComponent({super.key, required this.user});
Future<List<bool>>? _fetchdata() async {
return await MyApp.postViewModel.recapSevenDays(user.id);
}
@override
Widget build(BuildContext context) {
List<String> weekDays = ['L', 'M', 'M', 'J', 'V', 'S', 'D'];
DateTime currentDate = DateTime.now();
return Container(
decoration: BoxDecoration(
color: profileBttnColor,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: grayColor, width: 1)),
height: 120,
clipBehavior: Clip.hardEdge,
child: Column(
children: [
Expanded(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: postbutton,
borderRadius: BorderRadius.only(topRight: Radius.circular(10), topLeft: Radius.circular(10)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
child: Center(
child: Text(
weekDays[currentDate.subtract(Duration(days: 6)).weekday - 1].substring(0, 1),
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 17),
),
)),
Flexible(
child: Center(
child: Text(
weekDays[currentDate.subtract(Duration(days: 5)).weekday - 1].substring(0, 1),
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 17),
),
)),
Flexible(
child: Center(
child: Text(
weekDays[currentDate.subtract(Duration(days: 4)).weekday - 1].substring(0, 1),
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 17),
),
)),
Flexible(
child: Center(
child: Text(
weekDays[currentDate.subtract(Duration(days: 3)).weekday - 1].substring(0, 1),
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 17),
),
)),
Flexible(
child: Center(
child: Text(
weekDays[currentDate.subtract(Duration(days: 2)).weekday - 1].substring(0, 1),
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 17),
),
)),
Flexible(
child: Center(
child: Text(
weekDays[currentDate.subtract(Duration(days: 1)).weekday - 1].substring(0, 1),
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 17),
),
)),
Flexible(
child: Center(
child: Text(
weekDays[currentDate.subtract(Duration(days: 0)).weekday - 1].substring(0, 1),
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w800, fontSize: 17),
),
)),
],
),
)),
FutureBuilder<List<bool>>(
future: _fetchdata(), // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<List<bool>> snapshot) {
if (snapshot.hasData) {
return Padding(
padding: EdgeInsets.all(12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
LittleCapsule(
isEmpty: snapshot.data![0],
date: currentDate.subtract(const Duration(days: 6)),
),
LittleCapsule(isEmpty: snapshot.data![1], date: currentDate.subtract(const Duration(days: 5))),
LittleCapsule(isEmpty: snapshot.data![2], date: currentDate.subtract(const Duration(days: 4))),
LittleCapsule(isEmpty: snapshot.data![3], date: currentDate.subtract(const Duration(days: 3))),
LittleCapsule(isEmpty: snapshot.data![4], date: currentDate.subtract(const Duration(days: 2))),
LittleCapsule(isEmpty: snapshot.data![5], date: currentDate.subtract(const Duration(days: 1))),
LittleCapsule(isEmpty: snapshot.data![6], date: currentDate.subtract(const Duration(days: 0))),
],
),
);
} else {
return Container();
}
}),
],
),
);
}
}

@ -9,7 +9,9 @@ class SettingPartComponent extends StatelessWidget {
final JustMusicIcon icon; final JustMusicIcon icon;
final String label; final String label;
final bool important; final bool important;
const SettingPartComponent({Key? key, required this.icon, required this.label, this.important = false}) final VoidCallback? action;
const SettingPartComponent(
{Key? key, required this.icon, required this.label, this.important = false, required this.action})
: super(key: key); : super(key: key);
@override @override
@ -24,11 +26,7 @@ class SettingPartComponent extends StatelessWidget {
color: important ? warningBttnColor : settingColor, color: important ? warningBttnColor : settingColor,
borderOnForeground: false, borderOnForeground: false,
child: InkWell( child: InkWell(
onTap: () { onTap: action,
if (icon == JustMusicIcon.cross) {
logout();
}
},
splashColor: Colors.transparent, splashColor: Colors.transparent,
highlightColor: Colors.white.withOpacity(0.08), highlightColor: Colors.white.withOpacity(0.08),
child: Container( child: Container(

@ -27,8 +27,7 @@ class _TopNavBarComponentState extends State<TopNavBarComponent> with TickerProv
bool isDismissed = true; bool isDismissed = true;
final DateTime midnight = DateTime( final DateTime midnight = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day + 1);
DateTime.now().year, DateTime.now().month, DateTime.now().day + 1);
void actionSurBouton(bool choice) async { void actionSurBouton(bool choice) async {
widget.callback(choice); widget.callback(choice);
@ -47,8 +46,7 @@ class _TopNavBarComponentState extends State<TopNavBarComponent> with TickerProv
var now = tz.TZDateTime.now(franceTimeZone); var now = tz.TZDateTime.now(franceTimeZone);
// Calculate the midnight time for the next day in France timezone // Calculate the midnight time for the next day in France timezone
var midnight = var midnight = tz.TZDateTime(franceTimeZone, now.year, now.month, now.day + 1);
tz.TZDateTime(franceTimeZone, now.year, now.month, now.day + 1);
bool res = await MyApp.postViewModel.getAvailable(); bool res = await MyApp.postViewModel.getAvailable();
if (res) { if (res) {
@ -67,8 +65,7 @@ class _TopNavBarComponentState extends State<TopNavBarComponent> with TickerProv
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
"Capsule disponible", "Capsule disponible",
style: style: GoogleFonts.plusJakartaSans(color: Colors.grey, fontSize: 15),
GoogleFonts.plusJakartaSans(color: Colors.grey, fontSize: 15),
), ),
), ),
flushbarStyle: FlushbarStyle.FLOATING, flushbarStyle: FlushbarStyle.FLOATING,
@ -105,8 +102,7 @@ class _TopNavBarComponentState extends State<TopNavBarComponent> with TickerProv
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: CountdownTimer( child: CountdownTimer(
endTime: midnight.millisecondsSinceEpoch, endTime: midnight.millisecondsSinceEpoch,
textStyle: textStyle: GoogleFonts.plusJakartaSans(color: Colors.grey, fontSize: 15),
GoogleFonts.plusJakartaSans(color: Colors.grey, fontSize: 15),
), ),
), ),
flushbarStyle: FlushbarStyle.FLOATING, flushbarStyle: FlushbarStyle.FLOATING,
@ -153,7 +149,7 @@ class _TopNavBarComponentState extends State<TopNavBarComponent> with TickerProv
flex: 1, flex: 1,
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () async { onTap: () {
Navigator.of(context).push(routeAddFriend()); Navigator.of(context).push(routeAddFriend());
}, },
child: const Icon( child: const Icon(
@ -199,30 +195,23 @@ class _TopNavBarComponentState extends State<TopNavBarComponent> with TickerProv
} }
}, },
child: LayoutBuilder( child: LayoutBuilder(
builder: (BuildContext context, builder: (BuildContext context, BoxConstraints constraints) {
BoxConstraints constraints) {
if (choice) { if (choice) {
return Padding( return Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(left: 8, top: 0, right: 8, bottom: 6),
left: 8, top: 0, right: 8, bottom: 6),
child: AutoSizeText( child: AutoSizeText(
"Mes amis", "Mes amis",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500, fontSize: 16, color: Colors.white),
fontSize: 16,
color: Colors.white),
), ),
); );
} else { } else {
return Padding( return Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(left: 8, top: 0, right: 8, bottom: 6),
left: 8, top: 0, right: 8, bottom: 6),
child: AutoSizeText( child: AutoSizeText(
"Mes amis", "Mes amis",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
fontWeight: FontWeight.w300, fontWeight: FontWeight.w300, fontSize: 16, color: unactiveFeed),
fontSize: 16,
color: unactiveFeed),
)); ));
} }
}, },
@ -239,29 +228,22 @@ class _TopNavBarComponentState extends State<TopNavBarComponent> with TickerProv
} }
}, },
child: LayoutBuilder( child: LayoutBuilder(
builder: (BuildContext context, builder: (BuildContext context, BoxConstraints constraints) {
BoxConstraints constraints) {
if (choice) { if (choice) {
return Padding( return Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(left: 8, top: 0, right: 8, bottom: 6),
left: 8, top: 0, right: 8, bottom: 6),
child: AutoSizeText( child: AutoSizeText(
"Discovery", "Discovery",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
fontWeight: FontWeight.w300, fontWeight: FontWeight.w300, fontSize: 16, color: unactiveFeed),
fontSize: 16,
color: unactiveFeed),
)); ));
} else { } else {
return Padding( return Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(left: 8, top: 0, right: 8, bottom: 6),
left: 8, top: 0, right: 8, bottom: 6),
child: AutoSizeText( child: AutoSizeText(
"Discovery", "Discovery",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500, fontSize: 16, color: Colors.white),
fontSize: 16,
color: Colors.white),
)); ));
} }
}, },

@ -2,6 +2,9 @@ import 'package:flutter/Material.dart';
import 'package:justmusic/screens/add_friend_screen.dart'; import 'package:justmusic/screens/add_friend_screen.dart';
import 'package:justmusic/screens/feed_screen.dart'; import 'package:justmusic/screens/feed_screen.dart';
import 'package:justmusic/screens/profile_screen.dart'; import 'package:justmusic/screens/profile_screen.dart';
import 'package:justmusic/screens/user_screen.dart';
import '../model/User.dart';
Route routeProfile() { Route routeProfile() {
return PageRouteBuilder( return PageRouteBuilder(
@ -50,3 +53,21 @@ Route routeRocket() {
}, },
); );
} }
Route routeUser(User user) {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => UserScreen(user: user),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(1.0, 0.0);
const end = Offset.zero;
const curve = Curves.ease;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
return SlideTransition(
position: animation.drive(tween),
child: child,
);
},
);
}

@ -17,6 +17,7 @@ import 'package:justmusic/screens/launching_rocker_screen.dart';
import 'package:justmusic/screens/post_screen.dart'; import 'package:justmusic/screens/post_screen.dart';
import 'package:justmusic/screens/profile_screen.dart'; import 'package:justmusic/screens/profile_screen.dart';
import 'package:justmusic/screens/registration_screen.dart'; import 'package:justmusic/screens/registration_screen.dart';
import 'package:justmusic/screens/user_screen.dart';
import 'package:justmusic/screens/welcome_screen.dart'; import 'package:justmusic/screens/welcome_screen.dart';
import 'package:justmusic/view_model/CommentViewModel.dart'; import 'package:justmusic/view_model/CommentViewModel.dart';
import 'package:justmusic/view_model/MusicViewModel.dart'; import 'package:justmusic/view_model/MusicViewModel.dart';
@ -67,8 +68,7 @@ class _MyAppState extends State<MyApp> {
print('User is currently signed out!'); print('User is currently signed out!');
return null; return null;
} else { } else {
MyApp.userViewModel.userCurrent = MyApp.userViewModel.userCurrent = (await (MyApp.userViewModel.getUser(user.uid)))!;
(await (MyApp.userViewModel.getUser(user.uid)))!;
userCurrent = Stream.value(MyApp.userViewModel.userCurrent); userCurrent = Stream.value(MyApp.userViewModel.userCurrent);
print('User is signed in!'); print('User is signed in!');
} }
@ -106,38 +106,7 @@ class _MyAppState extends State<MyApp> {
theme: ThemeData( theme: ThemeData(
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
), ),
home: StreamBuilder<User?>( home: WellcomeScreen());
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return LoadingScreen();
} else if (snapshot.hasData) {
return FutureBuilder<userJustMusic.User?>(
future: MyApp.userViewModel.getUser(snapshot.data!.uid),
builder: (context, userSnapshot) {
if (userSnapshot.connectionState ==
ConnectionState.waiting) {
return LoadingScreen();
} else if (userSnapshot.hasData) {
MyApp.userViewModel.userCurrent = userSnapshot.data!;
return AnimatedSwitcher(
duration: Duration(milliseconds: 1000),
transitionBuilder: (child, animation) {
return FadeTransition(
opacity: animation, child: child);
},
child: FeedScreen(),
);
} else {
return WellcomeScreen();
}
},
);
} else {
return WellcomeScreen();
}
},
));
}, },
designSize: Size(390, 844), designSize: Size(390, 844),
); );

@ -9,6 +9,7 @@ import 'package:text_scroll/text_scroll.dart';
import 'package:zoom_tap_animation/zoom_tap_animation.dart'; import 'package:zoom_tap_animation/zoom_tap_animation.dart';
import '../components/button_play_component.dart'; import '../components/button_play_component.dart';
import '../components/comment_component.dart'; import '../components/comment_component.dart';
import '../components/profil_picture_component.dart';
import '../main.dart'; import '../main.dart';
import '../model/Post.dart'; import '../model/Post.dart';
import '../model/Comment.dart'; import '../model/Comment.dart';
@ -60,439 +61,460 @@ class _DetailPostScreenState extends State<DetailPostScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return GestureDetector(
height: 760.h, onTap: () {
child: Column( FocusScopeNode currentFocus = FocusScope.of(context);
children: [ if (!currentFocus.hasPrimaryFocus) {
Expanded( currentFocus.unfocus();
child: Stack( resetFullScreen();
children: [ }
ScrollConfiguration( },
behavior: MyBehavior(), child: Container(
child: SingleChildScrollView( height: 760.h,
controller: _scrollController, child: Column(
physics: AlwaysScrollableScrollPhysics(), children: [
child: Stack( Expanded(
clipBehavior: Clip.hardEdge, child: Stack(
children: [ children: [
Align( ScrollConfiguration(
alignment: Alignment.topCenter, behavior: MyBehavior(),
child: Container( child: SingleChildScrollView(
height: 400, controller: _scrollController,
width: double.infinity, physics: AlwaysScrollableScrollPhysics(),
child: FadeInImage.assetNetwork( child: Stack(
placeholder: "assets/images/loadingPlaceholder.gif", clipBehavior: Clip.hardEdge,
image: choice ? widget.post.selfie! : widget.post.music.cover!,
width: double.infinity,
fit: BoxFit.cover,
),
),
),
Column(
children: [ children: [
Container( Align(
height: 200, alignment: Alignment.topCenter,
margin: EdgeInsets.only(top: 230), child: Container(
width: double.infinity, height: 400,
decoration: const BoxDecoration( width: double.infinity,
gradient: LinearGradient( child: FadeInImage.assetNetwork(
begin: Alignment.topCenter, placeholder: "assets/images/loadingPlaceholder.gif",
end: Alignment.bottomCenter, image: choice ? widget.post.selfie! : widget.post.music.cover!,
colors: [Colors.transparent, bgModal], width: double.infinity,
stops: [0, 0.8], fit: BoxFit.cover,
), ),
), ),
child: Padding( ),
padding: const EdgeInsets.fromLTRB(20, 0, 20, 10), Column(
child: Row( children: [
crossAxisAlignment: CrossAxisAlignment.end, Container(
children: [ height: 200,
Padding( margin: EdgeInsets.only(top: 230),
padding: const EdgeInsets.only(right: 10), width: double.infinity,
child: choice decoration: const BoxDecoration(
? Padding( gradient: LinearGradient(
padding: const EdgeInsets.all(4), begin: Alignment.topCenter,
child: ClipOval( end: Alignment.bottomCenter,
child: SizedBox.fromSize( colors: [Colors.transparent, bgModal],
// Image radius stops: [0, 0.8],
child: Image(
image: NetworkImage(widget.post.user.pp),
width: 45,
),
),
),
)
: widget.post.music.previewUrl != null
? ButtonPlayComponent(music: widget.post.music)
: Container(),
), ),
Flexible( ),
child: Column( child: Padding(
mainAxisAlignment: MainAxisAlignment.end, padding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
crossAxisAlignment: CrossAxisAlignment.start, child: Row(
children: [ crossAxisAlignment: CrossAxisAlignment.end,
Flexible( children: [
child: Row( Padding(
crossAxisAlignment: CrossAxisAlignment.end, padding: const EdgeInsets.only(right: 10),
children: [ child: choice
Expanded( ? Padding(
child: ScrollConfiguration( padding: const EdgeInsets.all(4),
behavior: ScrollBehavior().copyWith(scrollbars: false), child: ClipOval(
child: TextScroll( child: SizedBox.fromSize(
choice ? widget.post.user.pseudo : widget.post.music.title!, // Image radius
style: GoogleFonts.plusJakartaSans( child: ProfilPictureComponent(user: widget.post.user),
height: 1,
color: Colors.white,
fontWeight: FontWeight.w800,
fontSize: 22,
),
mode: TextScrollMode
.endless,
pauseBetween: Duration(
milliseconds: 500),
velocity: Velocity(
pixelsPerSecond:
Offset(20, 0)),
), ),
), ),
), )
Padding( : widget.post.music.previewUrl != null
padding: const EdgeInsets.only(left: 20.0), ? ButtonPlayComponent(music: widget.post.music)
child: choice : Container(),
? DateTime(today.year, today.month, today.day).isAtSameMomentAs( ),
DateTime( Flexible(
widget.post.date.year, child: Column(
widget.post.date.month, mainAxisAlignment: MainAxisAlignment.end,
widget.post.date.day, crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: ScrollConfiguration(
behavior: ScrollBehavior().copyWith(scrollbars: false),
child: TextScroll(
choice ? widget.post.user.pseudo : widget.post.music.title!,
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white,
fontWeight: FontWeight.w800,
fontSize: 22,
), ),
) mode: TextScrollMode.endless,
? Text( pauseBetween: Duration(milliseconds: 500),
"Aujourd'hui, ${widget.post.date.hour}:${widget.post.date.minute}", velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
style: GoogleFonts.plusJakartaSans( ),
height: 1, ),
color: Colors.white, ),
fontWeight: FontWeight.w900, Padding(
fontSize: 18, padding: const EdgeInsets.only(left: 20.0),
child: choice
? DateTime(today.year, today.month, today.day)
.isAtSameMomentAs(
DateTime(
widget.post.date.year,
widget.post.date.month,
widget.post.date.day,
), ),
) )
? Text(
"Aujourd'hui, ${widget.post.date.hour}:${widget.post.date.minute}",
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: 18,
),
)
: Text(
"hier, ${widget.post.date.hour}:${widget.post.date.minute}",
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: 18,
),
)
: Text( : Text(
"hier, ${widget.post.date.hour}:${widget.post.date.minute}", widget.post.music.date.toString(),
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
height: 1, height: 1,
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
fontSize: 18, fontSize: 18,
), ),
) ),
),
],
),
),
choice
? widget.post.location.item2 != null
? Text(
"${widget.post.location.item1}, ${widget.post.location.item2}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.5),
fontWeight: FontWeight.w400,
fontSize: 15,
),
)
: Text( : Text(
widget.post.music.date.toString(), "",
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
height: 1, color: Colors.white.withOpacity(0.4),
color: Colors.white, fontWeight: FontWeight.w300,
fontWeight: FontWeight.w900, fontSize: 13,
fontSize: 18,
), ),
)
: ScrollConfiguration(
behavior: ScrollBehavior().copyWith(scrollbars: false),
child: TextScroll(
widget.post.music.artists.first.name!,
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 17,
), ),
), mode: TextScrollMode.endless,
], pauseBetween: Duration(milliseconds: 500),
), velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
),
choice
? widget.post.location.item2 != null
? Text(
"${widget.post.location.item1}, ${widget.post.location.item2}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.5),
fontWeight: FontWeight.w400,
fontSize: 15,
),
)
: Text(
"",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
fontSize: 13,
), ),
)
: ScrollConfiguration(
behavior: ScrollBehavior().copyWith(scrollbars: false),
child: TextScroll(
widget.post.music.artists.first.name!,
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 17,
), ),
mode: TextScrollMode.endless, ],
pauseBetween: Duration(milliseconds: 500), ),
velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
),
),
],
),
),
],
),
),
),
widget.post.description != null
? Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: const EdgeInsets.fromLTRB(50, 35, 50, 35),
child: Text(
widget.post.description!,
textAlign: TextAlign.left,
style: GoogleFonts.plusJakartaSans(
height: 1,
color: Colors.white,
fontWeight: FontWeight.w400,
fontSize: 14,
), ),
), ],
), ),
)
: Container(
height: 30,
),
Container(
width: double.infinity,
decoration: const BoxDecoration(
color: bgAppBar,
border: Border(
top: BorderSide(
color: Color(0xFF262626),
width: 1.0,
), ),
), ),
), widget.post.description != null
child: Column( ? Align(
children: [ alignment: Alignment.bottomLeft,
Padding( child: Padding(
padding: EdgeInsets.symmetric(vertical: 20), padding: const EdgeInsets.fromLTRB(50, 35, 50, 35),
child: Row( child: Text(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, widget.post.description!,
children: [ textAlign: TextAlign.left,
SvgPicture.asset("assets/images/heart.svg", semanticsLabel: 'Like Logo'), style: GoogleFonts.plusJakartaSans(
GestureDetector( height: 1,
onTap: () { color: Colors.white,
myFocusNode.requestFocus(); fontWeight: FontWeight.w400,
}, fontSize: 14,
child: ),
SvgPicture.asset("assets/images/chat.svg", semanticsLabel: 'Chat Logo'), ),
), ),
SvgPicture.asset("assets/images/add.svg", semanticsLabel: 'Add playlist Logo'), )
SvgPicture.asset("assets/images/save.svg", semanticsLabel: 'Save Logo'), : Container(
SvgPicture.asset("assets/images/report.svg", semanticsLabel: 'Report Logo'), height: 30,
], ),
Container(
width: double.infinity,
decoration: const BoxDecoration(
color: bgAppBar,
border: Border(
top: BorderSide(
color: Color(0xFF262626),
width: 1.0,
),
), ),
), ),
FutureBuilder<List<Comment>>( child: Column(
future: MyApp.commentViewModel.getCommentsByPostId(widget.post.id), children: [
builder: (BuildContext context, AsyncSnapshot<List<Comment>> snapshot) { Padding(
if (snapshot.hasData) { padding: EdgeInsets.symmetric(vertical: 20),
print("test:"); child: Row(
return Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
snapshot.data!.length > 0 SvgPicture.asset("assets/images/heart.svg", semanticsLabel: 'Like Logo'),
? Padding( GestureDetector(
padding: const EdgeInsets.all(15.0), onTap: () {
child: RichText( myFocusNode.requestFocus();
text: TextSpan( },
text: snapshot.data!.length.toString(), child: SvgPicture.asset("assets/images/chat.svg",
style: GoogleFonts.plusJakartaSans( semanticsLabel: 'Chat Logo'),
color: Colors.white, ),
fontWeight: FontWeight.w800, SvgPicture.asset("assets/images/add.svg",
), semanticsLabel: 'Add playlist Logo'),
children: [ SvgPicture.asset("assets/images/save.svg", semanticsLabel: 'Save Logo'),
TextSpan( SvgPicture.asset("assets/images/report.svg", semanticsLabel: 'Report Logo'),
text: snapshot.data!.length > 1 ],
? " commentaires" ),
: " commentaire", ),
FutureBuilder<List<Comment>>(
future: MyApp.commentViewModel.getCommentsByPostId(widget.post.id),
builder: (BuildContext context, AsyncSnapshot<List<Comment>> snapshot) {
if (snapshot.hasData) {
return Column(
children: [
snapshot.data!.length > 0
? Padding(
padding: const EdgeInsets.all(15.0),
child: RichText(
text: TextSpan(
text: snapshot.data!.length.toString(),
style: GoogleFonts.plusJakartaSans( style: GoogleFonts.plusJakartaSans(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w800,
), ),
children: [
TextSpan(
text: snapshot.data!.length > 1
? " commentaires"
: " commentaire",
style: GoogleFonts.plusJakartaSans(
color: Colors.white,
fontWeight: FontWeight.w400,
),
),
],
), ),
], ),
), )
), : Container(),
) snapshot.data!.length > 0
: Container(), ? Padding(
snapshot.data!.length > 0 padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
? Padding( child: ListView.builder(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), shrinkWrap: true,
child: ListView.builder( physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, itemCount: snapshot.data?.length,
physics: NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) {
itemCount: snapshot.data?.length, return CommentComponent(comment: snapshot.data![index]);
itemBuilder: (BuildContext context, int index) { },
return CommentComponent(comment: snapshot.data![index]); ),
}, )
), : Container(),
) ],
: Container(), );
], } else {
); return Container(
} else { child: Center(
return Container( child: CupertinoActivityIndicator(),
child: Center( ),
child: CupertinoActivityIndicator(), );
), }
); },
} ),
}, ],
), ),
], ),
), ],
), ),
], widget.post.selfie != null
), ? Align(
widget.post.selfie != null alignment: Alignment.topRight,
? Align( child: ZoomTapAnimation(
alignment: Alignment.topRight, onTap: () {
child: ZoomTapAnimation( if (widget.post.selfie != null) {
onTap: () { switchChoice();
if (widget.post.selfie != null) { }
switchChoice(); },
} enableLongTapRepeatEvent: false,
}, longTapRepeatDuration: const Duration(milliseconds: 100),
enableLongTapRepeatEvent: false, begin: 1.0,
longTapRepeatDuration: const Duration(milliseconds: 100), end: 0.96,
begin: 1.0, beginDuration: const Duration(milliseconds: 70),
end: 0.96, endDuration: const Duration(milliseconds: 100),
beginDuration: const Duration(milliseconds: 70), beginCurve: Curves.decelerate,
endDuration: const Duration(milliseconds: 100), endCurve: Curves.easeInOutSine,
beginCurve: Curves.decelerate, child: Container(
endCurve: Curves.easeInOutSine, margin: EdgeInsets.all(20),
child: Container( width: 120,
margin: EdgeInsets.all(20), height: 120,
width: 120, decoration: BoxDecoration(
height: 120, borderRadius: BorderRadius.circular(20),
decoration: BoxDecoration( border: Border.all(width: 4, color: Colors.white),
borderRadius: BorderRadius.circular(20), ),
border: Border.all(width: 4, color: Colors.white), child: ClipRRect(
), borderRadius: BorderRadius.circular(15),
child: ClipRRect( // implementer l'image
borderRadius: BorderRadius.circular(15), child: Image(
// implementer l'image image:
child: Image( NetworkImage(choice ? widget.post.music.cover! : widget.post.selfie!),
image: NetworkImage(choice ? widget.post.music.cover! : widget.post.selfie!), fit: BoxFit.cover,
fit: BoxFit.cover, ),
),
), ),
), ),
), )
), : Container(),
) ],
: Container(), ),
], ),
), ),
), Align(
),
Align(
alignment: Alignment.topCenter,
child: Container(
height: 50,
width: double.infinity,
color: Colors.transparent,
child: Align(
alignment: Alignment.topCenter, alignment: Alignment.topCenter,
child: Container( child: Container(
margin: EdgeInsets.only(top: 10), height: 50,
width: 60, width: double.infinity,
height: 5, color: Colors.transparent,
decoration: BoxDecoration( child: Align(
color: Colors.white.withOpacity(0.6), alignment: Alignment.topCenter,
borderRadius: BorderRadius.circular(20), child: Container(
margin: EdgeInsets.only(top: 10),
width: 60,
height: 5,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.6),
borderRadius: BorderRadius.circular(20),
),
),
), ),
), ),
), ),
), ],
), ),
],
),
),
Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 70,
width: double.infinity,
decoration: BoxDecoration(
border: Border(top: BorderSide(color: grayColor, width: 2)),
color: textFieldMessage,
), ),
child: Center( Padding(
child: Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
padding: const EdgeInsets.symmetric(horizontal: 20), child: Container(
child: Row( height: 70,
children: [ width: double.infinity,
ClipOval( decoration: BoxDecoration(
child: SizedBox.fromSize( border: Border(top: BorderSide(color: grayColor, width: 2)),
// Rayon de l'image color: textFieldMessage,
child: Image.network( ),
MyApp.userViewModel.userCurrent.pp, child: Center(
width: 45, child: Padding(
), padding: const EdgeInsets.symmetric(horizontal: 20),
), child: Row(
), children: [
SizedBox(width: 10), ClipOval(
Expanded( child: SizedBox.fromSize(
child: TextField( // Rayon de l'image
keyboardAppearance: Brightness.dark, child: Image.network(
controller: _textController, MyApp.userViewModel.userCurrent.pp,
focusNode: myFocusNode, width: 45,
onSubmitted: (value) async { ),
if (value.isNotEmpty) {
await MyApp.commentViewModel.addComment(value, widget.post.id);
}
setState(() {
_textController.clear();
});
},
cursorColor: primaryColor,
keyboardType: TextInputType.emailAddress,
style: GoogleFonts.plusJakartaSans(color: Colors.white),
decoration: InputDecoration(
suffixIcon: Icon(
Icons.send,
color: grayText,
size: 20,
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 1, color: grayText),
borderRadius: BorderRadius.all(Radius.circular(100)),
), ),
contentPadding: EdgeInsets.only(top: 0, bottom: 0, left: 20, right: 20), ),
fillColor: bgModal, SizedBox(width: 10),
filled: true, Expanded(
focusColor: Color.fromRGBO(255, 255, 255, 0.30), child: TextField(
enabledBorder: OutlineInputBorder( keyboardAppearance: Brightness.dark,
borderSide: BorderSide(width: 1, color: grayText), controller: _textController,
borderRadius: BorderRadius.all(Radius.circular(100)), focusNode: myFocusNode,
onSubmitted: (value) async {
if (value.isNotEmpty) {
await MyApp.commentViewModel.addComment(value, widget.post.id, widget.post.user);
}
setState(() {
_textController.clear();
});
},
onChanged: (value) {
setState(() {});
},
cursorColor: primaryColor,
keyboardType: TextInputType.emailAddress,
style: GoogleFonts.plusJakartaSans(color: Colors.white),
decoration: InputDecoration(
suffixIcon: _textController.text.isEmpty
? Container(
height: 20,
width: 20,
)
: IconButton(
onPressed: () async {
if (_textController.text.isNotEmpty) {
await MyApp.commentViewModel
.addComment(_textController.text, widget.post.id, widget.post.user);
}
myFocusNode.unfocus();
setState(() {
_textController.clear();
});
},
icon: Icon(
Icons.send,
color: primaryColor,
size: 20,
)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 1, color: grayText),
borderRadius: BorderRadius.all(Radius.circular(100)),
),
contentPadding: EdgeInsets.only(top: 0, bottom: 0, left: 20, right: 20),
fillColor: bgModal,
filled: true,
focusColor: Color.fromRGBO(255, 255, 255, 0.30),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 1, color: grayText),
borderRadius: BorderRadius.all(Radius.circular(100)),
),
hintText: 'Ajoutez une réponse...',
hintStyle: GoogleFonts.plusJakartaSans(color: grayText),
),
), ),
hintText: 'Ajoutez une réponse...',
hintStyle: GoogleFonts.plusJakartaSans(color: grayText),
), ),
), ],
), ),
], ),
), ),
), ),
), ),
), ],
), ),
], ));
),
);
} }
} }
class MyBehavior extends ScrollBehavior { class MyBehavior extends ScrollBehavior {
@override @override
Widget buildOverscrollIndicator( Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
BuildContext context, Widget child, ScrollableDetails details) {
return child; return child;
} }
} }

@ -56,6 +56,7 @@ class _FeedScreenState extends State<FeedScreen> with SingleTickerProviderStateM
@override @override
void dispose() { void dispose() {
controller.dispose();
animationController.dispose(); animationController.dispose();
super.dispose(); super.dispose();
} }
@ -120,7 +121,7 @@ class _FeedScreenState extends State<FeedScreen> with SingleTickerProviderStateM
bool empty = bool empty =
(choiceFeed == true && displayFeed.item1.isEmpty) || (choiceFeed == false && displayFeed.item2.isEmpty); (choiceFeed == true && displayFeed.item1.isEmpty) || (choiceFeed == false && displayFeed.item2.isEmpty);
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: false,
backgroundColor: bgColor, backgroundColor: bgColor,
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
body: Container( body: Container(

@ -1,3 +1,4 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart'; 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';
@ -5,6 +6,7 @@ import 'package:google_fonts/google_fonts.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';
import '../config/routes.dart';
import '../main.dart'; import '../main.dart';
import '../values/constants.dart'; import '../values/constants.dart';
@ -18,6 +20,16 @@ class ProfileScreen extends StatefulWidget {
class _ProfileScreenState extends State<ProfileScreen> { class _ProfileScreenState extends State<ProfileScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Future<void> logout() async {
print("cc");
await FirebaseAuth.instance.signOut();
Navigator.pushNamed(context, '/welcome');
}
void _openDetail() {
Navigator.of(context).push(routeUser(MyApp.userViewModel.userCurrent));
}
return Scaffold( return Scaffold(
appBar: PreferredSize( appBar: PreferredSize(
preferredSize: Size(double.infinity, 58), preferredSize: Size(double.infinity, 58),
@ -84,23 +96,28 @@ class _ProfileScreenState extends State<ProfileScreen> {
SettingPartComponent( SettingPartComponent(
icon: JustMusicIcon.profile, icon: JustMusicIcon.profile,
label: 'Compte', label: 'Compte',
action: _openDetail,
), ),
SettingPartComponent( const SettingPartComponent(
icon: JustMusicIcon.history, icon: JustMusicIcon.history,
label: 'Historiques des capsules', label: 'Historiques des capsules',
action: null,
), ),
SettingPartComponent( const SettingPartComponent(
icon: JustMusicIcon.spotify, icon: JustMusicIcon.spotify,
label: 'Lier un compte Spotify', label: 'Lier un compte Spotify',
action: null,
), ),
SettingPartComponent( const SettingPartComponent(
icon: JustMusicIcon.trash, icon: JustMusicIcon.trash,
label: 'Supprimer mon compte', label: 'Supprimer mon compte',
action: null,
), ),
SettingPartComponent( SettingPartComponent(
icon: JustMusicIcon.cross, icon: JustMusicIcon.cross,
label: 'Déconnexion', label: 'Déconnexion',
important: true, important: true,
action: logout,
), ),
], ],
), ),
@ -114,15 +131,17 @@ class _ProfileScreenState extends State<ProfileScreen> {
), ),
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: Column( child: const Column(
children: const [ children: [
SettingPartComponent( SettingPartComponent(
icon: JustMusicIcon.theme, icon: JustMusicIcon.theme,
label: 'Thême de l\'application', label: 'Thême de l\'application',
action: null,
), ),
SettingPartComponent( SettingPartComponent(
icon: JustMusicIcon.notification, icon: JustMusicIcon.notification,
label: 'Notifications', label: 'Notifications',
action: null,
), ),
], ],
), ),

@ -21,6 +21,7 @@ class SearchSongScreen extends StatefulWidget {
class _SearchSongScreenState extends State<SearchSongScreen> { class _SearchSongScreenState extends State<SearchSongScreen> {
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
final TextEditingController _textEditingController = TextEditingController(); final TextEditingController _textEditingController = TextEditingController();
int? playingIndex; int? playingIndex;
Future<void> resetFullScreen() async { Future<void> resetFullScreen() async {
@ -32,9 +33,18 @@ class _SearchSongScreenState extends State<SearchSongScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
fetchTrendingMusic();
_scrollController.addListener(_scrollListener); _scrollController.addListener(_scrollListener);
} }
Future<void> fetchTrendingMusic() async {
await MyApp.musicViewModel.getMusicsWithPlaylistId('37i9dQZF1DX1X23oiQRTB5').then((value) {
setState(() {
filteredData = value;
});
});
}
Future<void> _scrollListener() async { Future<void> _scrollListener() async {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
filteredData.addAll(await MyApp.musicViewModel filteredData.addAll(await MyApp.musicViewModel
@ -120,8 +130,7 @@ class _SearchSongScreenState extends State<SearchSongScreen> {
onEditingComplete: resetFullScreen, onEditingComplete: resetFullScreen,
onSubmitted: (value) async { onSubmitted: (value) async {
if (_textEditingController.text.isEmpty) { if (_textEditingController.text.isEmpty) {
} else if (value == " ") { fetchTrendingMusic();
print("popular");
} else { } else {
filteredData = await MyApp.musicViewModel.getMusicsWithNameOrArtistName(value); filteredData = await MyApp.musicViewModel.getMusicsWithNameOrArtistName(value);
setState(() { setState(() {

@ -0,0 +1,157 @@
import 'package:flutter/Material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:google_fonts/google_fonts.dart';
import '../components/profile_component.dart';
import '../components/recap_component.dart';
import '../main.dart';
import '../model/User.dart';
import '../values/constants.dart';
class UserScreen extends StatefulWidget {
final User user;
const UserScreen({super.key, required this.user});
@override
State<UserScreen> createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
late bool isClicked;
@override
Widget build(BuildContext context) {
isClicked = MyApp.userViewModel.isFriend(widget.user.id);
return Scaffold(
appBar: PreferredSize(
preferredSize: Size(double.infinity, 58),
child: Container(
height: double.infinity,
color: bgAppBar,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: defaultPadding),
child: Stack(
alignment: Alignment.centerLeft,
children: [
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.pop(context, true);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
height: 30,
width: 30,
child: Image(
image: AssetImage("assets/images/return_icon.png"),
height: 8,
),
)),
Align(
child: Text(
widget.user.pseudo,
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold),
),
)
],
),
),
),
),
body: Container(
width: double.infinity,
height: double.infinity,
color: bgColor,
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: settingPadding),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 68.h, bottom: 40),
child: ProfileComponent(user: widget.user),
),
MyApp.userViewModel.userCurrent.id != widget.user.id
? Align(
alignment: Alignment.topCenter,
child: isClicked
? SizedBox(
// Définir une largeur minimale pour le bouton "Ajouter"
width: 120, // Réglez cette valeur en fonction de vos besoins
child: Material(
borderRadius: BorderRadius.all(Radius.circular(5)),
color: selectedButton,
child: InkWell(
splashColor: Colors.white.withOpacity(0.3),
onTap: () async {
await MyApp.userViewModel.addOrDeleteFriend(widget.user.id);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
"Vous ne suivez plus ${widget.user.pseudo}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 20.h),
),
backgroundColor: Colors.red,
closeIconColor: Colors.white,
),
);
setState(() {});
},
child: Container(
padding: EdgeInsets.fromLTRB(28, 7, 28, 7),
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(7))),
child: Center(
child: Text("Ajouté",
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w600, fontSize: 13)),
),
))),
)
: SizedBox(
// Définir une largeur minimale pour le bouton "Ajouter"
width: 120, // Réglez cette valeur en fonction de vos besoins
child: Material(
borderRadius: BorderRadius.all(Radius.circular(5)),
color: primaryColor,
child: InkWell(
splashColor: Colors.white.withOpacity(0.3),
onTap: () async {
await MyApp.userViewModel.addOrDeleteFriend(widget.user.id);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: primaryColor,
content: Text(
"Vous suivez à present ${widget.user.pseudo}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 20.h),
),
),
);
setState(() {});
},
child: Container(
padding: EdgeInsets.fromLTRB(25, 7, 25, 7),
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(7))),
child: Center(
child: Text("Ajouter",
style: GoogleFonts.plusJakartaSans(
color: Colors.white, fontWeight: FontWeight.w600, fontSize: 13)),
),
)))),
)
: Container(),
SizedBox(
height: 40,
),
RecapComponent(user: widget.user)
],
),
),
),
),
);
}
}

@ -7,8 +7,7 @@ import 'package:firebase_storage/firebase_storage.dart';
import '../main.dart'; import '../main.dart';
class PostService { class PostService {
createPost(String? description, String idMusic, File? image, createPost(String? description, String idMusic, File? image, Tuple2<String, String>? location) async {
Tuple2<String, String>? location) async {
var id = MyApp.userViewModel.userCurrent.id; var id = MyApp.userViewModel.userCurrent.id;
final post = <String, dynamic>{ final post = <String, dynamic>{
"user_id": id, "user_id": id,
@ -42,14 +41,11 @@ class PostService {
deletePost() {} deletePost() {}
Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPopularPosts( Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPopularPosts({int limit = 10, int offset = 0}) async {
{int limit = 10, int offset = 0}) async {
DateTime twentyFourHoursAgo = DateTime.now().subtract(Duration(hours: 24)); DateTime twentyFourHoursAgo = DateTime.now().subtract(Duration(hours: 24));
Timestamp twentyFourHoursAgoTimestamp = Timestamp twentyFourHoursAgoTimestamp = Timestamp.fromDate(twentyFourHoursAgo);
Timestamp.fromDate(twentyFourHoursAgo);
QuerySnapshot<Map<String, dynamic>> response = await FirebaseFirestore QuerySnapshot<Map<String, dynamic>> response = await FirebaseFirestore.instance
.instance
.collection("posts") .collection("posts")
.where("date", isGreaterThan: twentyFourHoursAgoTimestamp) .where("date", isGreaterThan: twentyFourHoursAgoTimestamp)
.limit(limit) .limit(limit)
@ -67,8 +63,7 @@ class PostService {
return Timestamp.fromDate(twentyFourHoursAgo); return Timestamp.fromDate(twentyFourHoursAgo);
} }
Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPostsFriends( Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> getPostsFriends({int limit = 10, int offset = 0}) async {
{int limit = 10, int offset = 0}) async {
var timestamp = _getTwentyFourHoursAgoTimestamp(); var timestamp = _getTwentyFourHoursAgoTimestamp();
var response = await FirebaseFirestore.instance var response = await FirebaseFirestore.instance
.collection("posts") .collection("posts")
@ -84,17 +79,12 @@ class PostService {
Future<bool> getAvailable(String idUser) async { Future<bool> getAvailable(String idUser) async {
DateTime today = DateTime.now(); DateTime today = DateTime.now();
QuerySnapshot<Map<String, dynamic>> response = await FirebaseFirestore QuerySnapshot<Map<String, dynamic>> response =
.instance await FirebaseFirestore.instance.collection("posts").where("user_id", isEqualTo: idUser).get();
.collection("posts")
.where("user_id", isEqualTo: idUser)
.get();
bool isTodayAvailable = response.docs.any((doc) { bool isTodayAvailable = response.docs.any((doc) {
DateTime date = doc["date"].toDate(); // Assuming the field name is "date" DateTime date = doc["date"].toDate(); // Assuming the field name is "date"
return date.day == today.day && return date.day == today.day && date.month == today.month && date.year == today.year;
date.month == today.month &&
date.year == today.year;
}); });
return !isTodayAvailable; return !isTodayAvailable;
@ -103,17 +93,13 @@ class PostService {
Future<List<bool>> recapSevenDays(String id) async { Future<List<bool>> recapSevenDays(String id) async {
List<bool> recapList = []; List<bool> recapList = [];
DateTime sevenDaysAgo = DateTime.now().subtract(Duration(days: 7)); DateTime sevenDaysAgo = DateTime.now().subtract(Duration(days: 6));
QuerySnapshot<Map<String, dynamic>> response = await FirebaseFirestore QuerySnapshot<Map<String, dynamic>> response =
.instance await FirebaseFirestore.instance.collection("posts").where("user_id", isEqualTo: id).get();
.collection("posts")
.where("user_id", isEqualTo: id)
.get();
List<Map<String, dynamic>?> postList = response.docs List<Map<String, dynamic>?> postList =
.map((DocumentSnapshot<Map<String, dynamic>> doc) => doc.data()) response.docs.map((DocumentSnapshot<Map<String, dynamic>> doc) => doc.data()).toList();
.toList();
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
DateTime date = sevenDaysAgo.add(Duration(days: i)); DateTime date = sevenDaysAgo.add(Duration(days: i));

@ -1,19 +1,24 @@
import 'package:justmusic/model/mapper/CommentMapper.dart'; import 'package:justmusic/model/mapper/CommentMapper.dart';
import '../model/Comment.dart'; import '../model/Comment.dart';
import '../model/User.dart';
import '../services/CommentService.dart'; import '../services/CommentService.dart';
import '../services/NotificationService.dart';
class CommentViewModel { class CommentViewModel {
List<Comment> _comments = []; List<Comment> _comments = [];
final CommentService _commentService = CommentService(); final CommentService _commentService = CommentService();
final NotificationService _notificationService = NotificationService();
// Constructor // Constructor
CommentViewModel(); CommentViewModel();
// Methods // Methods
addComment(String text, String idPost) async { addComment(String text, String idPost, User receiver) async {
try { try {
print(receiver.token);
await _commentService.createComment(text, idPost); await _commentService.createComment(text, idPost);
_notificationService.sendNotifyComment(receiver.token, text);
} catch (e) { } catch (e) {
print(e); print(e);
rethrow; rethrow;

Loading…
Cancel
Save