diff --git a/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml b/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml index 519a56e..5fefc0b 100644 --- a/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml +++ b/Sources/justMUSIC/android/app/src/main/AndroidManifest.xml @@ -3,8 +3,7 @@ package="com.example.justmusic"> + android:icon="@mipmap/ic_launcher"> createState() => _PostComponentState(); -} - -class _PostComponentState extends State with TickerProviderStateMixin { - bool choice = false; - DateTime today = DateTime.now(); - - void switchChoice() { - setState(() { - choice = !choice; - }); - } - - @override - void initState() { - print("post: ${widget.post.date.toString()}"); - print("ajrd: ${DateTime.now().toString()}"); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: switchChoice, - child: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - if (widget.callback == null) { - return SizedBox( - width: double.infinity, - child: Column( - 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( - "${widget.post.date.day}/${widget.post.date.month}/${widget.post.date.year}-${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: () { - 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 - borderRadius: BorderRadius.circular(20), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(18), - // implement image - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Image( - image: NetworkImage(choice ? widget.post.selfie! : widget.post.music.cover!), - fit: BoxFit.cover, - width: double.infinity, - ), - 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( - choice ? widget.post.music.cover! : widget.post.selfie!), - fit: BoxFit.cover, - ), - ), - ), - )) - : Container(), - ], - ), - ), - ), - )), - SizedBox(height: 15), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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.w300, fontSize: 16.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.withOpacity(0.5), fontWeight: FontWeight.w300, fontSize: 16.h), - textAlign: TextAlign.end, - maxFontSize: 20, - ), - ], - ), - ], - )); - } - - return SizedBox( - width: double.infinity, - child: Column( - 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.index); - }, - 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: 60, - 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)), - )), - ], - ), - ) - ], - )); - }, - ), - ); - } -} +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: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; + }); + } + + @override + void initState() { + print("post: ${widget.post.date.toString()}"); + print("ajrd: ${DateTime.now().toString()}"); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: switchChoice, + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + if (widget.callback == null) { + return SizedBox( + width: double.infinity, + child: Column( + 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( + "${widget.post.date.day}/${widget.post.date.month}/${widget.post.date.year}-${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: () { + 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 + borderRadius: BorderRadius.circular(20), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(18), + // implement image + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Image( + image: NetworkImage(choice ? widget.post.selfie! : widget.post.music.cover!), + fit: BoxFit.cover, + width: double.infinity, + ), + 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( + choice ? widget.post.music.cover! : widget.post.selfie!), + fit: BoxFit.cover, + ), + ), + ), + )) + : Container(), + ], + ), + ), + ), + )), + SizedBox(height: 15), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + 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( + 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.w300, fontSize: 16.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.withOpacity(0.5), fontWeight: FontWeight.w300, fontSize: 16.h), + textAlign: TextAlign.end, + maxFontSize: 20, + ), + ], + ), + ], + )); + } + + return SizedBox( + width: double.infinity, + child: Column( + 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)), + )), + ], + ), + ) + ], + )); + }, + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/components/top_nav_bar_component.dart b/Sources/justMUSIC/lib/components/top_nav_bar_component.dart index 950d0ee..39deb0d 100644 --- a/Sources/justMUSIC/lib/components/top_nav_bar_component.dart +++ b/Sources/justMUSIC/lib/components/top_nav_bar_component.dart @@ -15,17 +15,15 @@ import '../values/constants.dart'; class TopNavBarComponent extends StatefulWidget { final Function(bool) callback; - - const TopNavBarComponent({Key? key, required this.callback}) - : super(key: key); + final bool choice; + const TopNavBarComponent({Key? key, required this.callback, required this.choice}) : super(key: key); @override State createState() => _TopNavBarComponentState(); } -class _TopNavBarComponentState extends State - with TickerProviderStateMixin { - bool choice = true; +class _TopNavBarComponentState extends State with TickerProviderStateMixin { + late bool choice; bool isDismissed = true; @@ -140,6 +138,7 @@ class _TopNavBarComponentState extends State @override Widget build(BuildContext context) { + choice = widget.choice; return Padding( padding: const EdgeInsets.only(top: defaultPadding), child: Container( diff --git a/Sources/justMUSIC/lib/screens/detail_post_screen.dart b/Sources/justMUSIC/lib/screens/detail_post_screen.dart index 140e42d..0f1b875 100644 --- a/Sources/justMUSIC/lib/screens/detail_post_screen.dart +++ b/Sources/justMUSIC/lib/screens/detail_post_screen.dart @@ -1,19 +1,14 @@ import 'dart:async'; - import 'package:flutter/Material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.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 '../main.dart'; import '../model/Post.dart'; import '../model/Comment.dart'; @@ -57,255 +52,99 @@ class _DetailPostScreenState extends State { @override void initState() { - print("post: ${widget.post.date.toString()}"); - print("ajrd: ${DateTime.now().toString()}"); - myFocusNode = FocusNode(); - var keyboardVisibilityController = KeyboardVisibilityController(); - print( - 'Keyboard visibility direct query: ${keyboardVisibilityController.isVisible}'); - super.initState(); - - keyboardSubscription = - keyboardVisibilityController.onChange.listen((bool visible) { - if (!visible) { - myFocusNode.unfocus(); - } - }); + myFocusNode = FocusNode(); } final ScrollController _scrollController = ScrollController(); @override Widget build(BuildContext context) { - 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, + return 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: FadeInImage.assetNetwork( + placeholder: "assets/images/loadingPlaceholder.gif", + image: choice ? widget.post.selfie! : widget.post.music.cover!, width: double.infinity, - child: FadeInImage.assetNetwork( - placeholder: - "assets/images/loadingPlaceholder.gif", - image: choice - ? widget.post.selfie! - : widget.post.music.cover!, - width: double.infinity, - fit: BoxFit.cover, - ), + fit: BoxFit.cover, ), ), - Column( - children: [ - Container( - height: 200, - margin: EdgeInsets.only(top: 230), - width: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [Colors.transparent, bgModal], - stops: [0, 0.8], - ), + ), + Column( + children: [ + Container( + height: 200, + margin: EdgeInsets.only(top: 230), + width: double.infinity, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Colors.transparent, bgModal], + stops: [0, 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: Image( - image: NetworkImage( - widget.post.user.pp), - width: 45, - ), + ), + 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: Image( + image: NetworkImage(widget.post.user.pp), + width: 45, ), ), - ) - : 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}:${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( - 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), + ) + : 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( - widget.post.music.artists - .first.name!, - style: GoogleFonts - .plusJakartaSans( + choice ? widget.post.user.pseudo : widget.post.music.title!, + style: GoogleFonts.plusJakartaSans( height: 1, color: Colors.white, - fontWeight: - FontWeight.w500, - fontSize: 17, + fontWeight: FontWeight.w800, + fontSize: 22, ), mode: TextScrollMode .endless, @@ -316,316 +155,335 @@ class _DetailPostScreenState extends State { 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.symmetric(vertical: 20), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, - children: [ - SvgPicture.asset( - "assets/images/heart.svg", - semanticsLabel: 'Like Logo'), - GestureDetector( - onTap: () { - myFocusNode.requestFocus(); - }, - 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'), - 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) { - print("test:"); - 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( - color: Colors.white, - fontWeight: - FontWeight.w800, + ), + 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, ), - children: [ - TextSpan( - text: snapshot - .data! - .length > - 1 - ? " commentaires" - : " commentaire", - style: GoogleFonts - .plusJakartaSans( - color: Colors - .white, - fontWeight: - FontWeight - .w400, + ) + ? 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( + 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, ), ) - : Container(), - 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]); - }, + : Text( + "", + style: GoogleFonts.plusJakartaSans( + color: Colors.white.withOpacity(0.4), + fontWeight: FontWeight.w300, + fontSize: 13, ), ) - : Container(), - ], - ); - } else { - return Container( - child: Center( - child: - CupertinoActivityIndicator(), - ), - ); - } - }, + : 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.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), + ), + 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, + ), ), - 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( + 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.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SvgPicture.asset("assets/images/heart.svg", semanticsLabel: 'Like Logo'), + GestureDetector( + onTap: () { + myFocusNode.requestFocus(); + }, + 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'), + 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) { + print("test:"); + 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( + color: Colors.white, + 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 + ? 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(), - ], - ), + ), + ) + : 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), - ), + ), + 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: Image.network( - MyApp.userViewModel.userCurrent.pp, - width: 45, - ), + ], + ), + ), + 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: Image.network( + MyApp.userViewModel.userCurrent.pp, + width: 45, ), ), - 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); - } - 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, - 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), + ), + 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); + } + 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, + 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), ), ), - ], - ), + ), + ], ), ), ), ), - ], - ), + ), + ], ), ); } diff --git a/Sources/justMUSIC/lib/screens/feed_screen.dart b/Sources/justMUSIC/lib/screens/feed_screen.dart index ff77931..83c9d95 100644 --- a/Sources/justMUSIC/lib/screens/feed_screen.dart +++ b/Sources/justMUSIC/lib/screens/feed_screen.dart @@ -1,273 +1,277 @@ -import 'dart:async'; -import 'package:circular_reveal_animation/circular_reveal_animation.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/main.dart'; -import 'package:justmusic/main.dart'; -import 'package:tuple/tuple.dart'; -import '../components/post_component.dart'; -import '../components/top_nav_bar_component.dart'; -import '../model/Post.dart'; -import '../values/constants.dart'; -import 'detail_post_screen.dart'; - -class FeedScreen extends StatefulWidget { - const FeedScreen({Key? key}) : super(key: key); - - @override - State createState() => _FeedScreenState(); -} - -class _FeedScreenState extends State - with SingleTickerProviderStateMixin { - late AnimationController animationController; - late Animation animation; - late List friendFeed; - Timer? timer; - - late List discoveryFeed; - late List displayFeed; - bool isDismissed = true; - bool choiceFeed = false; - - @override - void initState() { - super.initState(); - friendFeed = MyApp.postViewModel.postsFriends; - discoveryFeed = MyApp.postViewModel.bestPosts; - animationController = AnimationController( - vsync: this, - duration: Duration(milliseconds: 400), - ); - animation = CurvedAnimation( - parent: animationController, - curve: Curves.easeInOutSine, - ); - animationController.forward(); - } - - Future _refresh() async { - if (choiceFeed) { - await MyApp.postViewModel.getBestPosts(); - setState(() {}); - } else { - await MyApp.postViewModel.getPostsFriends(); - setState(() {}); - } - } - - void changeFeed(bool choice) { - // Mettez ici le code pour l'action que vous souhaitez effectuer avec le paramètre - if (choice) { - setState(() { - animationController.reset(); - displayFeed = MyApp.postViewModel.postsFriends.reversed.toList(); - animationController.forward(); - choiceFeed = false; - }); - } else { - setState(() { - animationController.reset(); - displayFeed = MyApp.postViewModel.bestPosts.reversed.toList(); - animationController.forward(); - choiceFeed = true; - }); - } - } - - void openDetailPost(int index) { - showModalBottomSheet( - backgroundColor: bgModal, - elevation: 1, - constraints: const BoxConstraints( - maxWidth: 600, - ), - isScrollControlled: true, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), topRight: Radius.circular(20))), - builder: ((BuildContext context) { - return ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), topRight: Radius.circular(20)), - child: DetailPostScreen(post: displayFeed[index])); - }), - ); - } - - _fetchData() async { - friendFeed = await MyApp.postViewModel.getPostsFriends(); - discoveryFeed = await MyApp.postViewModel.getBestPosts(); - return Tuple2(friendFeed, displayFeed); - } - - @override - Widget build(BuildContext context) { - if (choiceFeed) { - displayFeed = MyApp.postViewModel.postsFriends.reversed.toList(); - } else { - displayFeed = MyApp.postViewModel.bestPosts.reversed.toList(); - } - _fetchData(); - - return Scaffold( - resizeToAvoidBottomInset: true, - backgroundColor: bgColor, - extendBodyBehindAppBar: true, - body: displayFeed.isEmpty - ? Container( - width: double.infinity, - child: Stack( - fit: StackFit.expand, - children: [ - Container( - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/images/empty_bg.png"), - fit: BoxFit.cover, - opacity: 0.3), - ), - child: Padding( - padding: - EdgeInsets.only(top: 140.h, left: defaultPadding), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Suis tes amis pour voir leurs capsules", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontSize: 23, - fontWeight: FontWeight.w800)) - ], - ), - ), - ), - Align( - alignment: Alignment.topCenter, - child: IgnorePointer( - child: Container( - height: 240.h, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topRight, - stops: [ - 0.3, - 1 - ], - colors: [ - bgColor.withOpacity(0.9), - bgColor.withOpacity(0) - ])), - ), - ), - ), - Align( - alignment: Alignment.topCenter, - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 800), - child: TopNavBarComponent(callback: changeFeed), - ), - ), - ], - ), - ) - : Container( - width: double.infinity, - height: double.infinity, - child: Stack( - fit: StackFit.expand, - children: [ - Expanded( - child: Align( - alignment: Alignment.topCenter, - child: CircularRevealAnimation( - animation: animation, - centerOffset: Offset(30.w, -100), - child: Expanded( - child: Container( - height: double.infinity, - constraints: BoxConstraints(maxWidth: 600), - padding: EdgeInsets.fromLTRB( - defaultPadding, 100.h, defaultPadding, 0), - child: Expanded( - child: FutureBuilder( - future: _fetchData(), - builder: (BuildContext context, - AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return RefreshIndicator( - displacement: 20, - triggerMode: - RefreshIndicatorTriggerMode - .onEdge, - onRefresh: _refresh, - child: Expanded( - child: ListView.builder( - physics: - const AlwaysScrollableScrollPhysics(), - clipBehavior: Clip.none, - shrinkWrap: true, - itemCount: displayFeed.length, - itemBuilder: - (BuildContext context, - int index) { - return Padding( - padding: - const EdgeInsets.only( - bottom: 40), - child: PostComponent( - callback: openDetailPost, - post: displayFeed[index], - index: index), - ); - }, - ), - ), - ); - } else { - return Center( - child: CupertinoActivityIndicator(), - ); - } - }, - ), - )), - ), - ), - ), - ), - Align( - alignment: Alignment.topCenter, - child: IgnorePointer( - child: Container( - height: 240.h, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topRight, - stops: [ - 0.3, - 1 - ], - colors: [ - bgColor.withOpacity(0.9), - bgColor.withOpacity(0) - ])), - ), - ), - ), - Align( - alignment: Alignment.topCenter, - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 800), - child: TopNavBarComponent(callback: changeFeed), - ), - ), - ], - ), - )); - } -} +import 'dart:async'; +import 'package:circular_reveal_animation/circular_reveal_animation.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/main.dart'; +import 'package:tuple/tuple.dart'; +import '../components/post_component.dart'; +import '../components/top_nav_bar_component.dart'; +import '../model/Post.dart'; +import '../values/constants.dart'; +import 'detail_post_screen.dart'; + +class FeedScreen extends StatefulWidget { + const FeedScreen({Key? key}) : super(key: key); + + @override + State createState() => _FeedScreenState(); +} + +class _FeedScreenState extends State with SingleTickerProviderStateMixin { + late AnimationController animationController; + late Animation animation; + late List friendFeed; + Timer? timer; + + late List discoveryFeed; + late Tuple2, List> displayFeed; + bool isDismissed = true; + bool choiceFeed = true; + PageController controller = PageController(); + + @override + void initState() { + super.initState(); + friendFeed = MyApp.postViewModel.postsFriends; + discoveryFeed = MyApp.postViewModel.bestPosts; + + animationController = AnimationController( + vsync: this, + duration: Duration(milliseconds: 400), + ); + animation = CurvedAnimation( + parent: animationController, + curve: Curves.easeInOutSine, + ); + animationController.forward(); + _fetchData().then((tuple) { + friendFeed = tuple.item2; + displayFeed = tuple.item1; + setState(() {}); + }); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + Future _refresh() async { + Tuple2, List> tuple = await _fetchData(); + displayFeed = Tuple2(tuple.item1, tuple.item2); + setState(() {}); + } + + void changeFeed(bool choice) { + setState(() { + if (choice) { + controller.nextPage(duration: Duration(milliseconds: 300), curve: Curves.linear); + } else { + controller.previousPage(duration: Duration(milliseconds: 300), curve: Curves.linear); + } + }); + } + + void openDetailPost(Post post) { + showModalBottomSheet( + backgroundColor: bgModal, + elevation: 1, + constraints: const BoxConstraints( + maxWidth: 600, + ), + isScrollControlled: true, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))), + builder: ((BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)), + child: DetailPostScreen(post: post)); + }), + ); + } + + _fetchData() async { + friendFeed = await MyApp.postViewModel.getPostsFriends(); + discoveryFeed = await MyApp.postViewModel.getBestPosts(); + return Tuple2(friendFeed, discoveryFeed); + } + + switchTopBar(int index) { + if (index == 0) { + setState(() { + choiceFeed = true; + }); + } else { + setState(() { + choiceFeed = false; + }); + } + } + + @override + Widget build(BuildContext context) { + displayFeed = + Tuple2(MyApp.postViewModel.postsFriends.reversed.toList(), MyApp.postViewModel.bestPosts.reversed.toList()); + bool empty = + (choiceFeed == true && displayFeed.item1.isEmpty) || (choiceFeed == false && displayFeed.item2.isEmpty); + return Scaffold( + resizeToAvoidBottomInset: true, + backgroundColor: bgColor, + extendBodyBehindAppBar: true, + body: Container( + width: double.infinity, + height: double.infinity, + child: Stack( + fit: StackFit.expand, + children: [ + AnimatedOpacity( + opacity: empty ? 1 : 0, + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + child: Container( + decoration: const BoxDecoration( + image: + DecorationImage(image: AssetImage("assets/images/empty_bg.png"), fit: BoxFit.cover, opacity: 0.3), + ), + child: Padding( + padding: EdgeInsets.only(top: 140.h, left: defaultPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Suis tes amis pour voir leurs capsules", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontSize: 23, fontWeight: FontWeight.w800)) + ], + ), + ), + ), + ), + PageView( + onPageChanged: (value) { + switchTopBar(value); + }, + controller: controller, + scrollBehavior: const ScrollBehavior().copyWith(overscroll: false), + physics: AlwaysScrollableScrollPhysics(), + scrollDirection: Axis.horizontal, + children: [ + Align( + alignment: Alignment.topCenter, + child: CircularRevealAnimation( + animation: animation, + centerOffset: Offset(30.w, -100), + child: Container( + height: double.infinity, + constraints: BoxConstraints(maxWidth: 600), + padding: EdgeInsets.fromLTRB(defaultPadding, 100.h, defaultPadding, 0), + child: RefreshIndicator( + displacement: 20, + triggerMode: RefreshIndicatorTriggerMode.onEdge, + onRefresh: _refresh, + child: ListView.builder( + physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), + clipBehavior: Clip.none, + shrinkWrap: false, + itemCount: displayFeed.item1.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: const EdgeInsets.only(bottom: 40), + child: + PostComponent(callback: openDetailPost, post: displayFeed.item1[index], index: index), + ); + }, + ), + ), + ), + ), + ), + Align( + alignment: Alignment.topCenter, + child: CircularRevealAnimation( + animation: animation, + centerOffset: Offset(30.w, -100), + child: Container( + height: double.infinity, + constraints: BoxConstraints(maxWidth: 600), + padding: EdgeInsets.fromLTRB(defaultPadding, 100.h, defaultPadding, 0), + child: RefreshIndicator( + displacement: 20, + triggerMode: RefreshIndicatorTriggerMode.onEdge, + onRefresh: _refresh, + child: ListView.builder( + physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), + clipBehavior: Clip.none, + shrinkWrap: false, + itemCount: displayFeed.item2.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: const EdgeInsets.only(bottom: 40), + child: + PostComponent(callback: openDetailPost, post: displayFeed.item2[index], index: index), + ); + }, + ), + ), + ), + ), + ), + ], + ), + Align( + alignment: Alignment.topCenter, + child: IgnorePointer( + child: Container( + height: 240.h, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topRight, + stops: [0.3, 1], + colors: [bgColor.withOpacity(0.9), bgColor.withOpacity(0)])), + ), + ), + ), + Align( + alignment: Alignment.topCenter, + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 800), + child: TopNavBarComponent(callback: changeFeed, choice: choiceFeed), + ), + ), + ], + ), + ), + ); + } +} + +class NoEdgeEffectScrollPhysics extends ScrollPhysics { + const NoEdgeEffectScrollPhysics({ScrollPhysics? parent}) : super(parent: parent); + + @override + NoEdgeEffectScrollPhysics applyTo(ScrollPhysics? ancestor) { + return NoEdgeEffectScrollPhysics(parent: buildParent(ancestor)); + } + + @override + double applyBoundaryConditions(ScrollMetrics position, double value) { + // Supprimez l'effet de bord (effet de vague) + return 0.0; + } + + @override + double applyPhysicsToUserOffset(ScrollMetrics position, double offset) { + // Supprimez la rétroaction haptique + return offset; + } + + @override + Simulation? createBallisticSimulation(ScrollMetrics position, double velocity) { + // Désactivez l'overscroll + return super.createBallisticSimulation(position, 0.0); + } +}