diff --git a/Sources/justMUSIC/lib/components/historic_component.dart b/Sources/justMUSIC/lib/components/historic_component.dart index 7d0e758..db18e71 100644 --- a/Sources/justMUSIC/lib/components/historic_component.dart +++ b/Sources/justMUSIC/lib/components/historic_component.dart @@ -1,8 +1,16 @@ import 'package:flutter/Material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/main.dart'; +import 'package:justmusic/values/constants.dart'; +import 'package:tuple/tuple.dart'; + +import '../model/Music.dart'; class HistoricComponent extends StatefulWidget { final int month; - const HistoricComponent({super.key, required this.month}); + final int year; + const HistoricComponent({super.key, required this.month, required this.year}); @override State createState() => _HistoricComponentState(); @@ -17,27 +25,72 @@ class _HistoricComponentState extends State { return DateTime(year, month + 1, 0).day; } + getHistoric() {} + @override Widget build(BuildContext context) { - return Wrap( - spacing: 14, - runSpacing: 14, - children: List.generate(getNumberOfDaysInMonth(DateTime.now().year, widget.month), (index) { - // Generate widgets - return LimitedBox( - maxWidth: MediaQuery.of(context).size.width - 40 / 5, - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - Color(0xFF1E1E1E).withOpacity(0.7), - Color(0xFF1E1E1E).withOpacity(0), - ], begin: Alignment.topCenter, end: Alignment.bottomCenter), - borderRadius: BorderRadius.circular(3)), - height: 60, - width: 60, - ), - ); - }), - ); + return FutureBuilder( + future: MyApp.musicViewModel + .getHistoryCapsulesMonthWhitIdUser(MyApp.userViewModel.userCurrent.id, widget.month, widget.year), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Wrap( + spacing: 14, + runSpacing: 14, + children: List.generate(getNumberOfDaysInMonth(widget.year, widget.month), (index) { + Tuple2? checkCapsule; + if (snapshot.data != null) { + for (var element in snapshot.data!) { + if (element.item1 == index + 1) { + checkCapsule = element; + } + } + } + + if ((widget.year > DateTime.now().year || widget.month > DateTime.now().month) || + (widget.year == DateTime.now().year && + widget.month == DateTime.now().month && + index > DateTime.now().day)) { + return Container( + decoration: BoxDecoration( + gradient: LinearGradient(colors: [ + Color(0xFF1E1E1E).withOpacity(0.7), + Color(0xFF1E1E1E).withOpacity(0), + ], begin: Alignment.topCenter, end: Alignment.bottomCenter), + borderRadius: BorderRadius.circular(5)), + height: 60, + width: 60, + ); + } + if (checkCapsule != null) { + return Container( + decoration: BoxDecoration( + image: DecorationImage(image: NetworkImage((checkCapsule.item2.cover)!)), + borderRadius: BorderRadius.circular(5)), + height: 60, + width: 60, + ); + } else { + return Container( + color: bgColor, + height: 60, + width: 60, + child: Center( + child: Text( + (index + 1).toString(), + style: + GoogleFonts.plusJakartaSans(color: Colors.white, fontSize: 22, fontWeight: FontWeight.w800), + ), + ), + ); + } + + // Generate widgets + }), + ); + } else { + return CupertinoActivityIndicator(); + } + }); } } diff --git a/Sources/justMUSIC/lib/components/post_component.dart b/Sources/justMUSIC/lib/components/post_component.dart index d46f458..e80649d 100644 --- a/Sources/justMUSIC/lib/components/post_component.dart +++ b/Sources/justMUSIC/lib/components/post_component.dart @@ -1,257 +1,257 @@ -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:google_fonts/google_fonts.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:zoom_tap_animation/zoom_tap_animation.dart'; - -import '../model/Post.dart'; - -class PostComponent extends StatefulWidget { - final Function(Post)? callback; - final Post post; - final int index; - - PostComponent({Key? key, required this.callback, required this.post, required this.index}) : super(key: key); - - @override - State createState() => _PostComponentState(); -} - -class _PostComponentState extends State with TickerProviderStateMixin { - bool choice = false; - DateTime today = DateTime.now(); - - void switchChoice() { - setState(() { - choice = !choice; - }); - } - - final List frenchMonths = [ - 'Janvier', - 'Février', - 'Mars', - 'Avril', - 'Mai', - 'Juin', - 'Juillet', - 'Août', - 'Septembre', - 'Octobre', - 'Novembre', - 'Décembre' - ]; - - @override - void initState() { - print("post: ${widget.post.date.toString()}"); - print("ajrd: ${DateTime.now().toString()}"); - super.initState(); - } - - @override - Widget build(BuildContext context) { - var mins = "0"; - if (widget.post.date.minute < 10) { - mins = "0${widget.post.date.minute}"; - } else { - mins = widget.post.date.minute.toString(); - } - - return GestureDetector( - onTap: switchChoice, - child: SizedBox( - width: double.infinity, - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - ProfilPictureComponent(user: widget.post.user), - 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}:$mins", - style: GoogleFonts.plusJakartaSans( - color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13), - ) - : Text( - '${widget.post.date.day} ${frenchMonths[widget.post.date.month - 1]}, ${widget.post.date.hour}:$mins', - 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: [ - SizedBox( - width: double.infinity, - child: FadeInImage.assetNetwork( - image: widget.post.music.cover!, - fadeInDuration: const Duration(milliseconds: 100), - placeholder: "assets/images/loadingPlaceholder.gif", - ), - ), - 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: FadeInImage.assetNetwork( - image: widget.post.selfie!, - fit: BoxFit.cover, - fadeInDuration: const Duration(milliseconds: 100), - placeholder: "assets/images/loadingPlaceholder.gif", - ), - ), - ), - )) - : Container(), - ], - ), - ), - ), - )), - SizedBox(height: 15), - 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, - ), - ], - ), - 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)), - ), - ], - ), - ], - ))); - } -} +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:google_fonts/google_fonts.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:zoom_tap_animation/zoom_tap_animation.dart'; + +import '../model/Post.dart'; + +class PostComponent extends StatefulWidget { + final Function(Post)? callback; + final Post post; + final int index; + + PostComponent({Key? key, required this.callback, required this.post, required this.index}) : super(key: key); + + @override + State createState() => _PostComponentState(); +} + +class _PostComponentState extends State with TickerProviderStateMixin { + bool choice = false; + DateTime today = DateTime.now(); + + void switchChoice() { + setState(() { + choice = !choice; + }); + } + + final List frenchMonths = [ + 'Janvier', + 'Février', + 'Mars', + 'Avril', + 'Mai', + 'Juin', + 'Juillet', + 'Août', + 'Septembre', + 'Octobre', + 'Novembre', + 'Décembre' + ]; + + @override + void initState() { + print("post: ${widget.post.date.toString()}"); + print("ajrd: ${DateTime.now().toString()}"); + super.initState(); + } + + @override + Widget build(BuildContext context) { + var mins = "0"; + if (widget.post.date.minute < 10) { + mins = "0${widget.post.date.minute}"; + } else { + mins = widget.post.date.minute.toString(); + } + + return GestureDetector( + onTap: switchChoice, + child: SizedBox( + width: double.infinity, + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ProfilPictureComponent(user: widget.post.user), + 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}:$mins", + style: GoogleFonts.plusJakartaSans( + color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13), + ) + : Text( + '${widget.post.date.day} ${frenchMonths[widget.post.date.month - 1]}, ${widget.post.date.hour}:$mins', + 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: [ + SizedBox( + width: double.infinity, + child: FadeInImage.assetNetwork( + image: widget.post.music.cover!, + fadeInDuration: const Duration(milliseconds: 100), + placeholder: "assets/images/loadingPlaceholder.gif", + ), + ), + 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: FadeInImage.assetNetwork( + image: widget.post.selfie!, + fit: BoxFit.cover, + fadeInDuration: const Duration(milliseconds: 100), + placeholder: "assets/images/loadingPlaceholder.gif", + ), + ), + ), + )) + : Container(), + ], + ), + ), + ), + )), + SizedBox(height: 15), + 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, + ), + ], + ), + 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)), + ), + ], + ), + ], + ))); + } +} diff --git a/Sources/justMUSIC/lib/main.dart b/Sources/justMUSIC/lib/main.dart index cf342bd..a371898 100644 --- a/Sources/justMUSIC/lib/main.dart +++ b/Sources/justMUSIC/lib/main.dart @@ -26,6 +26,9 @@ import 'package:justmusic/view_model/UserViewModel.dart'; import 'package:justmusic/model/User.dart' as userJustMusic; import 'firebase_options.dart'; import 'package:timezone/data/latest.dart' as tz; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:intl/date_symbol_data_local.dart'; Future main() async { tz.initializeTimeZones(); @@ -35,6 +38,7 @@ Future main() async { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); + await initializeDateFormatting('fr_FR', null); await FirebaseMessaging.instance.requestPermission(sound: true); runApp(const MyApp()); } diff --git a/Sources/justMUSIC/lib/screens/capsule_historic_screen.dart b/Sources/justMUSIC/lib/screens/capsule_historic_screen.dart index d6fe2c7..f1f7646 100644 --- a/Sources/justMUSIC/lib/screens/capsule_historic_screen.dart +++ b/Sources/justMUSIC/lib/screens/capsule_historic_screen.dart @@ -3,6 +3,7 @@ import 'package:google_fonts/google_fonts.dart'; import '../components/historic_component.dart'; import '../values/constants.dart'; +import 'package:intl/intl.dart'; class CapsuleHistoricScreen extends StatefulWidget { const CapsuleHistoricScreen({super.key}); @@ -12,6 +13,20 @@ class CapsuleHistoricScreen extends StatefulWidget { } class _CapsuleHistoricScreenState extends State { + DateTime date = DateTime.now(); + + _reduceMonth() { + setState(() { + date = DateTime(date.year, date.month - 1, date.day); + }); + } + + _addMonth() { + setState(() { + date = DateTime(date.year, date.month + 1, date.day); + }); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -60,30 +75,73 @@ class _CapsuleHistoricScreenState extends State { padding: const EdgeInsets.symmetric(horizontal: settingPadding), child: Column( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( - padding: EdgeInsets.only(top: 30, bottom: 40), - child: SizedBox( - width: double.infinity, - child: Stack( - alignment: Alignment.center, + padding: const EdgeInsets.only(top: 80, left: 60, right: 60), + child: Align( + alignment: Alignment.center, + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Container( - padding: EdgeInsets.symmetric(horizontal: 15), - constraints: BoxConstraints(maxWidth: 600), - child: Column( - children: [ - HistoricComponent( - month: DateTime.now().month, - ), - ], + GestureDetector( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + height: 30, + width: 30, + child: Image( + image: AssetImage("assets/images/return_icon.png"), + height: 8, + ), + ), + onTap: _reduceMonth, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: Text( + '${DateFormat.MMMM('fr_FR').format(date)[0].toUpperCase()}${DateFormat.MMMM('fr_FR').format(date).substring(1)} ${date.year}', + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontWeight: FontWeight.w600, fontSize: 16), ), + ), + GestureDetector( + onTap: _addMonth, + child: Transform( + alignment: Alignment.center, + transform: Matrix4.rotationY(3.14159265), + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + height: 30, + width: 30, + child: Image( + image: AssetImage("assets/images/return_icon.png"), + height: 8, + ), + )), ) ], ), ), ), + Padding( + padding: EdgeInsets.only(top: 30, bottom: 40), + child: SizedBox( + width: double.infinity, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 15), + constraints: BoxConstraints(maxWidth: 600), + child: Column( + children: [ + HistoricComponent( + month: date.month, + year: date.year, + ), + ], + ), + )), + ), ], ), ), diff --git a/Sources/justMUSIC/lib/screens/detail_post_screen.dart b/Sources/justMUSIC/lib/screens/detail_post_screen.dart index 28c73ea..b05fa16 100644 --- a/Sources/justMUSIC/lib/screens/detail_post_screen.dart +++ b/Sources/justMUSIC/lib/screens/detail_post_screen.dart @@ -1,672 +1,672 @@ -import 'dart:async'; -import 'package:flutter/Material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:pinch_zoom/pinch_zoom.dart'; -import 'package:text_scroll/text_scroll.dart'; -import 'package:zoom_tap_animation/zoom_tap_animation.dart'; -import '../components/button_play_component.dart'; -import '../components/comment_component.dart'; -import '../components/profil_picture_component.dart'; -import '../main.dart'; -import '../model/Post.dart'; -import '../model/Comment.dart'; -import '../values/constants.dart'; - -class DetailPostScreen extends StatefulWidget { - final Post post; - - const DetailPostScreen({super.key, required this.post}); - - @override - State createState() => _DetailPostScreenState(); -} - -class _DetailPostScreenState extends State { - TextEditingController _textController = TextEditingController(); - late FocusNode myFocusNode; - late StreamSubscription keyboardSubscription; - - Future resetFullScreen() async { - await SystemChannels.platform.invokeMethod( - 'SystemChrome.restoreSystemUIOverlays', - ); - } - - bool choice = false; - DateTime today = DateTime.now(); - - void switchChoice() { - setState(() { - choice = !choice; - }); - } - - bool isSaved() { - return MyApp.userViewModel.userCurrent.musics_likes.contains(widget.post.music.id); - } - - bool isLiked() { - return widget.post.likes.contains(MyApp.userViewModel.userCurrent.id); - } - - @override - void dispose() { - MyApp.audioPlayer.release(); - myFocusNode.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - myFocusNode = FocusNode(); - } - - final ScrollController _scrollController = ScrollController(); - - @override - Widget build(BuildContext context) { - var mins = "0"; - if (widget.post.date.minute < 10) { - mins = "0${widget.post.date.minute}"; - } else { - mins = widget.post.date.minute.toString(); - } - return GestureDetector( - onTap: () { - FocusScopeNode currentFocus = FocusScope.of(context); - if (!currentFocus.hasPrimaryFocus) { - currentFocus.unfocus(); - resetFullScreen(); - } - }, - child: Container( - height: 760.h, - child: Column( - children: [ - Expanded( - child: Stack( - children: [ - ScrollConfiguration( - behavior: MyBehavior(), - child: SingleChildScrollView( - controller: _scrollController, - physics: AlwaysScrollableScrollPhysics(), - child: Stack( - clipBehavior: Clip.hardEdge, - children: [ - Align( - alignment: Alignment.topCenter, - child: Container( - height: 400, - width: double.infinity, - child: PinchZoom( - resetDuration: const Duration(milliseconds: 400), - maxScale: 2.5, - child: FadeInImage.assetNetwork( - placeholder: "assets/images/loadingPlaceholder.gif", - image: choice ? widget.post.selfie! : widget.post.music.cover!, - width: double.infinity, - fit: BoxFit.cover, - )), - ), - ), - Column( - children: [ - Container( - height: 200, - margin: EdgeInsets.only(top: 230), - width: double.infinity, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Colors.transparent, - bgModal.withOpacity(0.5), - bgModal.withOpacity(0.75), - bgModal - ], - stops: [0, 0.2, 0.4, 0.8], - ), - ), - child: Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 10), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.only(right: 10), - child: choice - ? Padding( - padding: const EdgeInsets.all(4), - child: ClipOval( - child: SizedBox.fromSize( - // Image radius - child: ProfilPictureComponent(user: widget.post.user), - ), - ), - ) - : widget.post.music.previewUrl != null - ? ButtonPlayComponent(music: widget.post.music) - : Container(), - ), - Flexible( - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - 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, - pauseBetween: Duration(milliseconds: 500), - velocity: Velocity(pixelsPerSecond: Offset(20, 0)), - ), - ), - ), - Padding( - 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}:$mins", - style: GoogleFonts.plusJakartaSans( - height: 1, - color: Colors.white, - fontWeight: FontWeight.w900, - fontSize: 18, - ), - ) - : Text( - "hier, ${widget.post.date.hour}:$mins", - style: GoogleFonts.plusJakartaSans( - height: 1, - color: Colors.white, - fontWeight: FontWeight.w900, - fontSize: 18, - ), - ) - : Text( - widget.post.music.date.toString(), - style: GoogleFonts.plusJakartaSans( - height: 1, - color: Colors.white, - fontWeight: FontWeight.w900, - 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( - "", - 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, - ), - ), - ), - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 30, bottom: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - children: [ - GestureDetector( - onTap: () async { - var bool = await MyApp.postViewModel - .addOrDeleteFavoritePost(widget.post.id); - print("testttt"); - if (!bool) { - widget.post.likes.add(MyApp.userViewModel.userCurrent.id); - - setState(() {}); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text("Vous avez liké cette capsule", - style: TextStyle(fontWeight: FontWeight.bold)), - backgroundColor: primaryColor, - closeIconColor: Colors.white, - ), - ); - } else { - widget.post.likes.remove(MyApp.userViewModel.userCurrent.id); - setState(() {}); - - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text("Vous avez supprimé votre like", - style: TextStyle(fontWeight: FontWeight.bold)), - backgroundColor: Colors.red, - closeIconColor: Colors.white, - ), - ); - } - }, - child: SvgPicture.asset( - "assets/images/heart.svg", - semanticsLabel: 'Like Logo', - color: isLiked() ? primaryColor : Colors.white, - ), - ), - Container( - padding: EdgeInsets.only(top: 8), - height: 30, - child: FutureBuilder>( - future: MyApp.postViewModel.getLikesByPostId(widget.post.id), - builder: - (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.hasData) { - return Text(snapshot.data!.length.toString(), - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w800, - )); - } else { - return Container( - child: Center( - child: CupertinoActivityIndicator(), - ), - ); - } - }, - ), - ) - ], - ), - Column( - children: [ - GestureDetector( - onTap: () { - myFocusNode.requestFocus(); - }, - child: SvgPicture.asset("assets/images/chat.svg", - semanticsLabel: 'Chat Logo'), - ), - Container( - padding: EdgeInsets.only(top: 8), - height: 30, - child: FutureBuilder>( - future: MyApp.commentViewModel.getCommentsByPostId(widget.post.id), - builder: - (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.hasData) { - return Text(snapshot.data!.length.toString(), - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w800, - )); - } else { - return Container( - child: Center( - child: CupertinoActivityIndicator(), - ), - ); - } - }, - ), - ) - ], - ), - SvgPicture.asset("assets/images/add.svg", - semanticsLabel: 'Add playlist Logo'), - GestureDetector( - onTap: () async { - var bool = await MyApp.musicViewModel - .addOrDeleteFavoriteMusic(widget.post.music.id); - !bool - ? ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: RichText( - textAlign: TextAlign.center, - maxLines: 1, - overflow: TextOverflow.ellipsis, - text: TextSpan( - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w400, - fontSize: 15, - ), - children: [ - TextSpan( - text: "${widget.post.music.title}", - style: TextStyle(fontWeight: FontWeight.bold)), - TextSpan(text: " ajouté à votre collection"), - ], - ), - ), - backgroundColor: primaryColor, - closeIconColor: Colors.white, - ), - ) - : ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: RichText( - textAlign: TextAlign.center, - maxLines: 1, - overflow: TextOverflow.ellipsis, - text: TextSpan( - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontWeight: FontWeight.w400, - fontSize: 15, - ), - children: [ - TextSpan( - text: "${widget.post.music.title}", - style: TextStyle(fontWeight: FontWeight.bold)), - TextSpan(text: " retiré de votre collection"), - ], - ), - ), - backgroundColor: Colors.red, - closeIconColor: Colors.white, - ), - ); - setState(() {}); - }, - child: SvgPicture.asset( - "assets/images/save.svg", - semanticsLabel: 'Save Logo', - color: isSaved() ? primaryColor : Colors.white, - )), - SvgPicture.asset("assets/images/report.svg", semanticsLabel: 'Report Logo'), - ], - ), - ), - FutureBuilder>( - future: MyApp.commentViewModel.getCommentsByPostId(widget.post.id), - builder: (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.hasData) { - return Column( - children: [ - snapshot.data!.length > 0 - ? Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), - child: ListView.builder( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: snapshot.data?.length, - itemBuilder: (BuildContext context, int index) { - return CommentComponent(comment: snapshot.data![index]); - }, - ), - ) - : Container(), - ], - ); - } else { - return Container( - child: Center( - child: CupertinoActivityIndicator(), - ), - ); - } - }, - ), - ], - ), - ), - ], - ), - widget.post.selfie != null - ? Align( - alignment: Alignment.topRight, - child: ZoomTapAnimation( - onTap: () { - if (widget.post.selfie != null) { - switchChoice(); - } - }, - enableLongTapRepeatEvent: false, - longTapRepeatDuration: const Duration(milliseconds: 100), - begin: 1.0, - end: 0.96, - beginDuration: const Duration(milliseconds: 70), - endDuration: const Duration(milliseconds: 100), - beginCurve: Curves.decelerate, - endCurve: Curves.easeInOutSine, - child: Container( - margin: EdgeInsets.all(20), - width: 120, - height: 120, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - border: Border.all(width: 4, color: Colors.white), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(15), - // implementer l'image - child: Image( - image: - NetworkImage(choice ? widget.post.music.cover! : widget.post.selfie!), - fit: BoxFit.cover, - ), - ), - ), - ), - ) - : Container(), - ], - ), - ), - ), - Align( - alignment: Alignment.topCenter, - child: Container( - height: 50, - width: double.infinity, - color: Colors.transparent, - child: Align( - alignment: Alignment.topCenter, - 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( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( - children: [ - ClipOval( - child: SizedBox.fromSize( - // Rayon de l'image - child: FadeInImage.assetNetwork( - image: MyApp.userViewModel.userCurrent.pp, - width: 45, - height: 45, - fit: BoxFit.cover, - fadeInDuration: const Duration(milliseconds: 100), - placeholder: "assets/images/loadingPlaceholder.gif", - ), - ), - ), - SizedBox(width: 10), - Expanded( - child: TextField( - keyboardAppearance: Brightness.dark, - controller: _textController, - 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), - ), - ), - ), - ], - ), - ), - ), - ), - ), - ], - ), - )); - } -} - -class MyBehavior extends ScrollBehavior { - @override - Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) { - return child; - } -} +import 'dart:async'; +import 'package:flutter/Material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:pinch_zoom/pinch_zoom.dart'; +import 'package:text_scroll/text_scroll.dart'; +import 'package:zoom_tap_animation/zoom_tap_animation.dart'; +import '../components/button_play_component.dart'; +import '../components/comment_component.dart'; +import '../components/profil_picture_component.dart'; +import '../main.dart'; +import '../model/Post.dart'; +import '../model/Comment.dart'; +import '../values/constants.dart'; + +class DetailPostScreen extends StatefulWidget { + final Post post; + + const DetailPostScreen({super.key, required this.post}); + + @override + State createState() => _DetailPostScreenState(); +} + +class _DetailPostScreenState extends State { + TextEditingController _textController = TextEditingController(); + late FocusNode myFocusNode; + late StreamSubscription keyboardSubscription; + + Future resetFullScreen() async { + await SystemChannels.platform.invokeMethod( + 'SystemChrome.restoreSystemUIOverlays', + ); + } + + bool choice = false; + DateTime today = DateTime.now(); + + void switchChoice() { + setState(() { + choice = !choice; + }); + } + + bool isSaved() { + return MyApp.userViewModel.userCurrent.musics_likes.contains(widget.post.music.id); + } + + bool isLiked() { + return widget.post.likes.contains(MyApp.userViewModel.userCurrent.id); + } + + @override + void dispose() { + MyApp.audioPlayer.release(); + myFocusNode.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + myFocusNode = FocusNode(); + } + + final ScrollController _scrollController = ScrollController(); + + @override + Widget build(BuildContext context) { + var mins = "0"; + if (widget.post.date.minute < 10) { + mins = "0${widget.post.date.minute}"; + } else { + mins = widget.post.date.minute.toString(); + } + return GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + resetFullScreen(); + } + }, + child: Container( + height: 760.h, + child: Column( + children: [ + Expanded( + child: Stack( + children: [ + ScrollConfiguration( + behavior: MyBehavior(), + child: SingleChildScrollView( + controller: _scrollController, + physics: AlwaysScrollableScrollPhysics(), + child: Stack( + clipBehavior: Clip.hardEdge, + children: [ + Align( + alignment: Alignment.topCenter, + child: Container( + height: 400, + width: double.infinity, + child: PinchZoom( + resetDuration: const Duration(milliseconds: 400), + maxScale: 2.5, + child: FadeInImage.assetNetwork( + placeholder: "assets/images/loadingPlaceholder.gif", + image: choice ? widget.post.selfie! : widget.post.music.cover!, + width: double.infinity, + fit: BoxFit.cover, + )), + ), + ), + Column( + children: [ + Container( + height: 200, + margin: EdgeInsets.only(top: 230), + width: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + bgModal.withOpacity(0.5), + bgModal.withOpacity(0.75), + bgModal + ], + stops: [0, 0.2, 0.4, 0.8], + ), + ), + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(right: 10), + child: choice + ? Padding( + padding: const EdgeInsets.all(4), + child: ClipOval( + child: SizedBox.fromSize( + // Image radius + child: ProfilPictureComponent(user: widget.post.user), + ), + ), + ) + : widget.post.music.previewUrl != null + ? ButtonPlayComponent(music: widget.post.music) + : Container(), + ), + Flexible( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + 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, + pauseBetween: Duration(milliseconds: 500), + velocity: Velocity(pixelsPerSecond: Offset(20, 0)), + ), + ), + ), + Padding( + 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}:$mins", + style: GoogleFonts.plusJakartaSans( + height: 1, + color: Colors.white, + fontWeight: FontWeight.w900, + fontSize: 18, + ), + ) + : Text( + "hier, ${widget.post.date.hour}:$mins", + style: GoogleFonts.plusJakartaSans( + height: 1, + color: Colors.white, + fontWeight: FontWeight.w900, + fontSize: 18, + ), + ) + : Text( + widget.post.music.date.toString(), + style: GoogleFonts.plusJakartaSans( + height: 1, + color: Colors.white, + fontWeight: FontWeight.w900, + 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( + "", + 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, + ), + ), + ), + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 30, bottom: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + GestureDetector( + onTap: () async { + var bool = await MyApp.postViewModel + .addOrDeleteFavoritePost(widget.post.id); + print("testttt"); + if (!bool) { + widget.post.likes.add(MyApp.userViewModel.userCurrent.id); + + setState(() {}); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("Vous avez liké cette capsule", + style: TextStyle(fontWeight: FontWeight.bold)), + backgroundColor: primaryColor, + closeIconColor: Colors.white, + ), + ); + } else { + widget.post.likes.remove(MyApp.userViewModel.userCurrent.id); + setState(() {}); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("Vous avez supprimé votre like", + style: TextStyle(fontWeight: FontWeight.bold)), + backgroundColor: Colors.red, + closeIconColor: Colors.white, + ), + ); + } + }, + child: SvgPicture.asset( + "assets/images/heart.svg", + semanticsLabel: 'Like Logo', + color: isLiked() ? primaryColor : Colors.white, + ), + ), + Container( + padding: EdgeInsets.only(top: 8), + height: 30, + child: FutureBuilder>( + future: MyApp.postViewModel.getLikesByPostId(widget.post.id), + builder: + (BuildContext context, AsyncSnapshot> snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!.length.toString(), + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w800, + )); + } else { + return Container( + child: Center( + child: CupertinoActivityIndicator(), + ), + ); + } + }, + ), + ) + ], + ), + Column( + children: [ + GestureDetector( + onTap: () { + myFocusNode.requestFocus(); + }, + child: SvgPicture.asset("assets/images/chat.svg", + semanticsLabel: 'Chat Logo'), + ), + Container( + padding: EdgeInsets.only(top: 8), + height: 30, + child: FutureBuilder>( + future: MyApp.commentViewModel.getCommentsByPostId(widget.post.id), + builder: + (BuildContext context, AsyncSnapshot> snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!.length.toString(), + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w800, + )); + } else { + return Container( + child: Center( + child: CupertinoActivityIndicator(), + ), + ); + } + }, + ), + ) + ], + ), + SvgPicture.asset("assets/images/add.svg", + semanticsLabel: 'Add playlist Logo'), + GestureDetector( + onTap: () async { + var bool = await MyApp.musicViewModel + .addOrDeleteFavoriteMusic(widget.post.music.id); + !bool + ? ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: RichText( + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + text: TextSpan( + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 15, + ), + children: [ + TextSpan( + text: "${widget.post.music.title}", + style: TextStyle(fontWeight: FontWeight.bold)), + TextSpan(text: " ajouté à votre collection"), + ], + ), + ), + backgroundColor: primaryColor, + closeIconColor: Colors.white, + ), + ) + : ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: RichText( + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + text: TextSpan( + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 15, + ), + children: [ + TextSpan( + text: "${widget.post.music.title}", + style: TextStyle(fontWeight: FontWeight.bold)), + TextSpan(text: " retiré de votre collection"), + ], + ), + ), + backgroundColor: Colors.red, + closeIconColor: Colors.white, + ), + ); + setState(() {}); + }, + child: SvgPicture.asset( + "assets/images/save.svg", + semanticsLabel: 'Save Logo', + color: isSaved() ? primaryColor : Colors.white, + )), + SvgPicture.asset("assets/images/report.svg", semanticsLabel: 'Report Logo'), + ], + ), + ), + FutureBuilder>( + future: MyApp.commentViewModel.getCommentsByPostId(widget.post.id), + builder: (BuildContext context, AsyncSnapshot> snapshot) { + if (snapshot.hasData) { + return Column( + children: [ + snapshot.data!.length > 0 + ? Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), + child: ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: snapshot.data?.length, + itemBuilder: (BuildContext context, int index) { + return CommentComponent(comment: snapshot.data![index]); + }, + ), + ) + : Container(), + ], + ); + } else { + return Container( + child: Center( + child: CupertinoActivityIndicator(), + ), + ); + } + }, + ), + ], + ), + ), + ], + ), + widget.post.selfie != null + ? Align( + alignment: Alignment.topRight, + child: ZoomTapAnimation( + onTap: () { + if (widget.post.selfie != null) { + switchChoice(); + } + }, + enableLongTapRepeatEvent: false, + longTapRepeatDuration: const Duration(milliseconds: 100), + begin: 1.0, + end: 0.96, + beginDuration: const Duration(milliseconds: 70), + endDuration: const Duration(milliseconds: 100), + beginCurve: Curves.decelerate, + endCurve: Curves.easeInOutSine, + child: Container( + margin: EdgeInsets.all(20), + width: 120, + height: 120, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + border: Border.all(width: 4, color: Colors.white), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(15), + // implementer l'image + child: Image( + image: + NetworkImage(choice ? widget.post.music.cover! : widget.post.selfie!), + fit: BoxFit.cover, + ), + ), + ), + ), + ) + : Container(), + ], + ), + ), + ), + Align( + alignment: Alignment.topCenter, + child: Container( + height: 50, + width: double.infinity, + color: Colors.transparent, + child: Align( + alignment: Alignment.topCenter, + 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( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + children: [ + ClipOval( + child: SizedBox.fromSize( + // Rayon de l'image + child: FadeInImage.assetNetwork( + image: MyApp.userViewModel.userCurrent.pp, + width: 45, + height: 45, + fit: BoxFit.cover, + fadeInDuration: const Duration(milliseconds: 100), + placeholder: "assets/images/loadingPlaceholder.gif", + ), + ), + ), + SizedBox(width: 10), + Expanded( + child: TextField( + keyboardAppearance: Brightness.dark, + controller: _textController, + 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), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + )); + } +} + +class MyBehavior extends ScrollBehavior { + @override + Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) { + return child; + } +} diff --git a/Sources/justMUSIC/lib/screens/search_song_screen.dart b/Sources/justMUSIC/lib/screens/search_song_screen.dart index aac095b..7b2136e 100644 --- a/Sources/justMUSIC/lib/screens/search_song_screen.dart +++ b/Sources/justMUSIC/lib/screens/search_song_screen.dart @@ -1,418 +1,418 @@ -import 'dart:async'; -import 'dart:ui'; - -import 'package:flutter/Material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/services.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/model/Music.dart'; - -import '../components/music_list_component.dart'; -import '../values/constants.dart'; -import '../main.dart'; - -class SearchSongScreen extends StatefulWidget { - final Function callback; - const SearchSongScreen({Key? key, required this.callback}) : super(key: key); - - @override - State createState() => _SearchSongScreenState(); -} - -class _SearchSongScreenState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textEditingController = TextEditingController(); - PageController controller = PageController(); - bool isCollectionSelected = false; - - int? playingIndex; - - Future resetFullScreen() async { - await SystemChannels.platform.invokeMethod( - 'SystemChrome.restoreSystemUIOverlays', - ); - } - - @override - void initState() { - super.initState(); - fetchTrendingMusic(); - _scrollController.addListener(_scrollListener); - } - - Future fetchTrendingMusic() async { - await MyApp.musicViewModel.getMusicsWithPlaylistId('37i9dQZF1DX1X23oiQRTB5').then((value) { - setState(() { - filteredData = value; - }); - }); - } - - Future _scrollListener() async { - if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { - filteredData.addAll(await MyApp.musicViewModel - .getMusicsWithName(_textEditingController.text, limit: 10, offset: filteredData.length)); - setState(() { - filteredData = filteredData; - }); - } - if (_scrollController.offset >= _scrollController.position.maxScrollExtent && - !_scrollController.position.outOfRange) { - setState(() { - //you can do anything here - }); - } - if (_scrollController.offset <= _scrollController.position.minScrollExtent && - !_scrollController.position.outOfRange) { - setState(() { - Timer(Duration(milliseconds: 1), () => _scrollController.jumpTo(0)); - }); - } - } - - List filteredData = []; - - void playMusic(int index) { - if (playingIndex == index) { - setState(() { - playingIndex = null; - }); - } else { - setState(() { - playingIndex = index; - }); - } - } - - _changePage(int index) { - /*if (isCollectionSelected) { - setState(() { - isCollectionSelected = !isCollectionSelected; - controller.animateTo(1, duration: Duration(milliseconds: 200), curve: Curves.easeOut); - }); - } else { - setState(() { - isCollectionSelected = !isCollectionSelected; - controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeOut); - }); - }*/ - } - - Future> _fetchSavedSong() async { - return await MyApp.musicViewModel.getFavoriteMusicsByUserId(MyApp.userViewModel.userCurrent.id); - } - - @override - void dispose() { - MyApp.audioPlayer.pause(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - double screenHeight = MediaQuery.of(context).size.height; - return GestureDetector( - onTap: () { - FocusScopeNode currentFocus = FocusScope.of(context); - if (!currentFocus.hasPrimaryFocus) { - currentFocus.unfocus(); - resetFullScreen(); - } - }, - child: BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 60.0, - sigmaY: 60.0, - ), - child: Container( - color: bgAppBar.withOpacity(0.5), - height: screenHeight - 50, - padding: const EdgeInsets.only(top: 10), - child: Column( - children: [ - Align( - child: Container( - width: 60, - height: 5, - decoration: BoxDecoration( - color: Color(0xFF3A3A3A).withOpacity(0.6), borderRadius: BorderRadius.circular(20))), - ), - const SizedBox( - height: 10, - ), - Padding( - padding: const EdgeInsets.only(bottom: 10, left: 20, right: 20), - child: SizedBox( - height: 40, - child: TextField( - controller: _textEditingController, - keyboardAppearance: Brightness.dark, - onEditingComplete: resetFullScreen, - onSubmitted: (value) async { - if (_textEditingController.text.isEmpty) { - fetchTrendingMusic(); - } else { - setState(() { - filteredData = []; - }); - filteredData = await MyApp.musicViewModel.getMusicsWithNameOrArtistName(value); - setState(() { - filteredData = filteredData; - }); - } - controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeIn); - }, - cursorColor: Colors.white, - keyboardType: TextInputType.text, - style: GoogleFonts.plusJakartaSans(color: grayText), - decoration: InputDecoration( - prefixIcon: const Icon( - Icons.search, - color: grayColor, - ), - focusedBorder: const OutlineInputBorder( - borderSide: BorderSide(width: 1, color: grayColor), - borderRadius: BorderRadius.all(Radius.circular(10))), - contentPadding: - const EdgeInsets.only(top: 0, bottom: 0, left: defaultPadding, right: defaultPadding), - fillColor: searchBarColor, - filled: true, - focusColor: grayText, - enabledBorder: const OutlineInputBorder( - borderSide: BorderSide(width: 1, color: grayColor), - borderRadius: BorderRadius.all(Radius.circular(10))), - hintText: 'Chercher un son', - hintStyle: GoogleFonts.plusJakartaSans(color: grayHint)), - ), - ), - ), - Padding( - padding: const EdgeInsets.only(top: 10, bottom: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: _changePage(0), - child: Text( - "Recherche", - style: GoogleFonts.plusJakartaSans( - color: isCollectionSelected ? Color(0xFF9A9A9A) : Colors.white, - fontWeight: isCollectionSelected ? FontWeight.w500 : FontWeight.w700), - ), - ), - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: _changePage(1), - child: Text("Collection", - style: GoogleFonts.plusJakartaSans( - color: isCollectionSelected ? Colors.white : Color(0xFF9A9A9A), - fontWeight: isCollectionSelected ? FontWeight.w700 : FontWeight.w500)), - ), - ], - ), - ), - Flexible( - child: PageView( - controller: controller, - physics: BouncingScrollPhysics(), - onPageChanged: (index) { - setState(() { - if (index == 1) { - isCollectionSelected = true; - } else { - isCollectionSelected = false; - } - }); - }, - children: [ - ScrollConfiguration( - behavior: ScrollBehavior().copyWith(scrollbars: true), - child: ListView.builder( - physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast), - controller: _scrollController, - itemCount: filteredData.length, - itemBuilder: (context, index) { - if (playingIndex == index) { - return InkWell( - onTap: () { - widget.callback(filteredData[index]); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: MusicListComponent( - music: filteredData[index], - playing: true, - callback: playMusic, - index: index, - ), - )); - } - return InkWell( - onTap: () { - widget.callback(filteredData[index]); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: MusicListComponent( - music: filteredData[index], - playing: false, - callback: playMusic, - index: index, - ), - )); - }), - ), - ScrollConfiguration( - behavior: ScrollBehavior().copyWith(scrollbars: true), - child: FutureBuilder( - future: _fetchSavedSong(), - builder: (BuildContext context, AsyncSnapshot> snapshot) { - if (snapshot.hasData) { - if (snapshot.data?.length == 0) { - return Container( - width: double.infinity, - height: double.infinity, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - "Votre collection est vide.", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, fontWeight: FontWeight.w800, fontSize: 18), - ), - ), - Image.asset( - "assets/images/empty_collection.png", - width: 300, - ) - ], - ), - ); - } else { - return ListView.builder( - physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast), - controller: _scrollController, - itemCount: snapshot.data?.length, - itemBuilder: (context, index) { - if (playingIndex == index) { - return InkWell( - onTap: () { - widget.callback((snapshot.data?[index])!); - }, - onLongPress: () { - showCupertinoModalPopup( - context: context, - builder: (BuildContext context) => CupertinoAlertDialog( - title: const Text('Supprimer la musique'), - content: Text( - 'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'), - actions: [ - CupertinoDialogAction( - /// This parameter indicates this action is the default, - /// and turns the action's text to bold text. - isDefaultAction: true, - onPressed: () { - Navigator.pop(context); - }, - child: const Text('Annuler'), - ), - CupertinoDialogAction( - /// This parameter indicates the action would perform - /// a destructive action such as deletion, and turns - /// the action's text color to red. - isDestructiveAction: true, - onPressed: () async { - Navigator.pop(context); - await MyApp.musicViewModel - .addOrDeleteFavoriteMusic((snapshot.data?[index])!.id); - MyApp.userViewModel.userCurrent.musics_likes - .remove((snapshot.data?[index])!.id); - - MyApp.audioPlayer.release(); - setState(() { - playingIndex = null; - }); - }, - child: const Text('Supprimer'), - ), - ], - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: MusicListComponent( - music: (snapshot.data?[index])!, - playing: true, - callback: playMusic, - index: index, - ), - )); - } - return InkWell( - onTap: () { - widget.callback((snapshot.data?[index])!); - }, - onLongPress: () { - showCupertinoModalPopup( - context: context, - builder: (BuildContext context) => CupertinoAlertDialog( - title: const Text('Supprimer la musique'), - content: Text( - 'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'), - actions: [ - CupertinoDialogAction( - /// This parameter indicates this action is the default, - /// and turns the action's text to bold text. - isDefaultAction: true, - onPressed: () { - Navigator.pop(context); - }, - child: const Text('Annuler'), - ), - CupertinoDialogAction( - /// This parameter indicates the action would perform - /// a destructive action such as deletion, and turns - /// the action's text color to red. - isDestructiveAction: true, - onPressed: () async { - Navigator.pop(context); - await MyApp.musicViewModel - .addOrDeleteFavoriteMusic((snapshot.data?[index])!.id); - MyApp.userViewModel.userCurrent.musics_likes - .remove((snapshot.data?[index])!.id); - setState(() {}); - }, - child: const Text('Supprimer'), - ), - ], - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: MusicListComponent( - music: (snapshot.data?[index])!, - playing: false, - callback: playMusic, - index: index, - ), - )); - }); - } - } else { - return CupertinoActivityIndicator(); - } - }, - ), - ) - ], - )) - ], - ), - ), - )); - } -} +import 'dart:async'; +import 'dart:ui'; + +import 'package:flutter/Material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/model/Music.dart'; + +import '../components/music_list_component.dart'; +import '../values/constants.dart'; +import '../main.dart'; + +class SearchSongScreen extends StatefulWidget { + final Function callback; + const SearchSongScreen({Key? key, required this.callback}) : super(key: key); + + @override + State createState() => _SearchSongScreenState(); +} + +class _SearchSongScreenState extends State { + final ScrollController _scrollController = ScrollController(); + final TextEditingController _textEditingController = TextEditingController(); + PageController controller = PageController(); + bool isCollectionSelected = false; + + int? playingIndex; + + Future resetFullScreen() async { + await SystemChannels.platform.invokeMethod( + 'SystemChrome.restoreSystemUIOverlays', + ); + } + + @override + void initState() { + super.initState(); + fetchTrendingMusic(); + _scrollController.addListener(_scrollListener); + } + + Future fetchTrendingMusic() async { + await MyApp.musicViewModel.getMusicsWithPlaylistId('37i9dQZF1DX1X23oiQRTB5').then((value) { + setState(() { + filteredData = value; + }); + }); + } + + Future _scrollListener() async { + if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { + filteredData.addAll(await MyApp.musicViewModel + .getMusicsWithName(_textEditingController.text, limit: 10, offset: filteredData.length)); + setState(() { + filteredData = filteredData; + }); + } + if (_scrollController.offset >= _scrollController.position.maxScrollExtent && + !_scrollController.position.outOfRange) { + setState(() { + //you can do anything here + }); + } + if (_scrollController.offset <= _scrollController.position.minScrollExtent && + !_scrollController.position.outOfRange) { + setState(() { + Timer(Duration(milliseconds: 1), () => _scrollController.jumpTo(0)); + }); + } + } + + List filteredData = []; + + void playMusic(int index) { + if (playingIndex == index) { + setState(() { + playingIndex = null; + }); + } else { + setState(() { + playingIndex = index; + }); + } + } + + _changePage(int index) { + /*if (isCollectionSelected) { + setState(() { + isCollectionSelected = !isCollectionSelected; + controller.animateTo(1, duration: Duration(milliseconds: 200), curve: Curves.easeOut); + }); + } else { + setState(() { + isCollectionSelected = !isCollectionSelected; + controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeOut); + }); + }*/ + } + + Future> _fetchSavedSong() async { + return await MyApp.musicViewModel.getFavoriteMusicsByUserId(MyApp.userViewModel.userCurrent.id); + } + + @override + void dispose() { + MyApp.audioPlayer.pause(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + double screenHeight = MediaQuery.of(context).size.height; + return GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + resetFullScreen(); + } + }, + child: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 60.0, + sigmaY: 60.0, + ), + child: Container( + color: bgAppBar.withOpacity(0.5), + height: screenHeight - 50, + padding: const EdgeInsets.only(top: 10), + child: Column( + children: [ + Align( + child: Container( + width: 60, + height: 5, + decoration: BoxDecoration( + color: Color(0xFF3A3A3A).withOpacity(0.6), borderRadius: BorderRadius.circular(20))), + ), + const SizedBox( + height: 10, + ), + Padding( + padding: const EdgeInsets.only(bottom: 10, left: 20, right: 20), + child: SizedBox( + height: 40, + child: TextField( + controller: _textEditingController, + keyboardAppearance: Brightness.dark, + onEditingComplete: resetFullScreen, + onSubmitted: (value) async { + if (_textEditingController.text.isEmpty) { + fetchTrendingMusic(); + } else { + setState(() { + filteredData = []; + }); + filteredData = await MyApp.musicViewModel.getMusicsWithNameOrArtistName(value); + setState(() { + filteredData = filteredData; + }); + } + controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeIn); + }, + cursorColor: Colors.white, + keyboardType: TextInputType.text, + style: GoogleFonts.plusJakartaSans(color: grayText), + decoration: InputDecoration( + prefixIcon: const Icon( + Icons.search, + color: grayColor, + ), + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide(width: 1, color: grayColor), + borderRadius: BorderRadius.all(Radius.circular(10))), + contentPadding: + const EdgeInsets.only(top: 0, bottom: 0, left: defaultPadding, right: defaultPadding), + fillColor: searchBarColor, + filled: true, + focusColor: grayText, + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide(width: 1, color: grayColor), + borderRadius: BorderRadius.all(Radius.circular(10))), + hintText: 'Chercher un son', + hintStyle: GoogleFonts.plusJakartaSans(color: grayHint)), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 10, bottom: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: _changePage(0), + child: Text( + "Recherche", + style: GoogleFonts.plusJakartaSans( + color: isCollectionSelected ? Color(0xFF9A9A9A) : Colors.white, + fontWeight: isCollectionSelected ? FontWeight.w500 : FontWeight.w700), + ), + ), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: _changePage(1), + child: Text("Collection", + style: GoogleFonts.plusJakartaSans( + color: isCollectionSelected ? Colors.white : Color(0xFF9A9A9A), + fontWeight: isCollectionSelected ? FontWeight.w700 : FontWeight.w500)), + ), + ], + ), + ), + Flexible( + child: PageView( + controller: controller, + physics: BouncingScrollPhysics(), + onPageChanged: (index) { + setState(() { + if (index == 1) { + isCollectionSelected = true; + } else { + isCollectionSelected = false; + } + }); + }, + children: [ + ScrollConfiguration( + behavior: ScrollBehavior().copyWith(scrollbars: true), + child: ListView.builder( + physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast), + controller: _scrollController, + itemCount: filteredData.length, + itemBuilder: (context, index) { + if (playingIndex == index) { + return InkWell( + onTap: () { + widget.callback(filteredData[index]); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: MusicListComponent( + music: filteredData[index], + playing: true, + callback: playMusic, + index: index, + ), + )); + } + return InkWell( + onTap: () { + widget.callback(filteredData[index]); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: MusicListComponent( + music: filteredData[index], + playing: false, + callback: playMusic, + index: index, + ), + )); + }), + ), + ScrollConfiguration( + behavior: ScrollBehavior().copyWith(scrollbars: true), + child: FutureBuilder( + future: _fetchSavedSong(), + builder: (BuildContext context, AsyncSnapshot> snapshot) { + if (snapshot.hasData) { + if (snapshot.data?.length == 0) { + return Container( + width: double.infinity, + height: double.infinity, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "Votre collection est vide.", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontWeight: FontWeight.w800, fontSize: 18), + ), + ), + Image.asset( + "assets/images/empty_collection.png", + width: 300, + ) + ], + ), + ); + } else { + return ListView.builder( + physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast), + controller: _scrollController, + itemCount: snapshot.data?.length, + itemBuilder: (context, index) { + if (playingIndex == index) { + return InkWell( + onTap: () { + widget.callback((snapshot.data?[index])!); + }, + onLongPress: () { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) => CupertinoAlertDialog( + title: const Text('Supprimer la musique'), + content: Text( + 'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'), + actions: [ + CupertinoDialogAction( + /// This parameter indicates this action is the default, + /// and turns the action's text to bold text. + isDefaultAction: true, + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Annuler'), + ), + CupertinoDialogAction( + /// This parameter indicates the action would perform + /// a destructive action such as deletion, and turns + /// the action's text color to red. + isDestructiveAction: true, + onPressed: () async { + Navigator.pop(context); + await MyApp.musicViewModel + .addOrDeleteFavoriteMusic((snapshot.data?[index])!.id); + MyApp.userViewModel.userCurrent.musics_likes + .remove((snapshot.data?[index])!.id); + + MyApp.audioPlayer.release(); + setState(() { + playingIndex = null; + }); + }, + child: const Text('Supprimer'), + ), + ], + ), + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: MusicListComponent( + music: (snapshot.data?[index])!, + playing: true, + callback: playMusic, + index: index, + ), + )); + } + return InkWell( + onTap: () { + widget.callback((snapshot.data?[index])!); + }, + onLongPress: () { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) => CupertinoAlertDialog( + title: const Text('Supprimer la musique'), + content: Text( + 'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'), + actions: [ + CupertinoDialogAction( + /// This parameter indicates this action is the default, + /// and turns the action's text to bold text. + isDefaultAction: true, + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Annuler'), + ), + CupertinoDialogAction( + /// This parameter indicates the action would perform + /// a destructive action such as deletion, and turns + /// the action's text color to red. + isDestructiveAction: true, + onPressed: () async { + Navigator.pop(context); + await MyApp.musicViewModel + .addOrDeleteFavoriteMusic((snapshot.data?[index])!.id); + MyApp.userViewModel.userCurrent.musics_likes + .remove((snapshot.data?[index])!.id); + setState(() {}); + }, + child: const Text('Supprimer'), + ), + ], + ), + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: MusicListComponent( + music: (snapshot.data?[index])!, + playing: false, + callback: playMusic, + index: index, + ), + )); + }); + } + } else { + return CupertinoActivityIndicator(); + } + }, + ), + ) + ], + )) + ], + ), + ), + )); + } +} diff --git a/Sources/justMUSIC/lib/services/MusicService.dart b/Sources/justMUSIC/lib/services/MusicService.dart index 307177e..d1fd832 100644 --- a/Sources/justMUSIC/lib/services/MusicService.dart +++ b/Sources/justMUSIC/lib/services/MusicService.dart @@ -33,9 +33,8 @@ class MusicService { } } - Future>> getHistoryCapsulesMonthWhitIdUser( - String idUser, int month, int year) async { - List> capsules = []; + Future>> getHistoryCapsulesMonthWhitIdUser(String idUser, int month, int year) async { + List> capsules = []; var querySnapshot = await FirebaseFirestore.instance .collection('posts') @@ -46,8 +45,7 @@ class MusicService { .get(); for (var document in querySnapshot.docs) { - capsules.add(Tuple2(document.data()['date'].toDate().day.toString(), - document.data()['idMusic'])); + capsules.add(Tuple2(document.data()['date'].toDate().day, document.data()['song_id'])); } return capsules; diff --git a/Sources/justMUSIC/lib/view_model/MusicViewModel.dart b/Sources/justMUSIC/lib/view_model/MusicViewModel.dart index 78c0f8b..3695244 100644 --- a/Sources/justMUSIC/lib/view_model/MusicViewModel.dart +++ b/Sources/justMUSIC/lib/view_model/MusicViewModel.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:justmusic/view_model/TokenSpotify.dart'; import 'package:http/http.dart' as http; +import 'package:tuple/tuple.dart'; import '../main.dart'; import '../model/Artist.dart'; import '../model/Music.dart'; @@ -231,4 +232,23 @@ class MusicViewModel { rethrow; } } + + Future>> getHistoryCapsulesMonthWhitIdUser(String idUser, int month, int year) async { + try { + List> capsules = []; + var capsulesData = await _musicService.getHistoryCapsulesMonthWhitIdUser(idUser, month, year); + + var musics = await getMusicsWithIds(capsulesData.map((capsule) => capsule.item2).toList()); + + for (var capsule in capsulesData) { + var music = musics.firstWhere((music) => music.id == capsule.item2); + print(capsule.item1); + capsules.add(Tuple2(capsule.item1, music)); + } + return capsules; + } catch (e) { + print(e); + rethrow; + } + } }