diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml
index 72fa842..db02f0e 100644
--- a/.idea/libraries/Dart_Packages.xml
+++ b/.idea/libraries/Dart_Packages.xml
@@ -37,6 +37,13 @@
+
+
+
+
+
+
+
@@ -359,6 +366,13 @@
+
+
+
+
+
+
+
@@ -597,6 +611,13 @@
+
+
+
+
+
+
+
@@ -639,6 +660,13 @@
+
+
+
+
+
+
+
@@ -772,6 +800,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -793,6 +842,13 @@
+
+
+
+
+
+
+
@@ -808,6 +864,7 @@
+
@@ -853,6 +910,7 @@
+
@@ -885,12 +943,14 @@
+
+
@@ -909,9 +969,13 @@
+
+
+
+
diff --git a/Sources/justMUSIC/assets/images/add.svg b/Sources/justMUSIC/assets/images/add.svg
new file mode 100644
index 0000000..9736b5e
--- /dev/null
+++ b/Sources/justMUSIC/assets/images/add.svg
@@ -0,0 +1,3 @@
+
diff --git a/Sources/justMUSIC/assets/images/chat.svg b/Sources/justMUSIC/assets/images/chat.svg
new file mode 100644
index 0000000..5174563
--- /dev/null
+++ b/Sources/justMUSIC/assets/images/chat.svg
@@ -0,0 +1,4 @@
+
diff --git a/Sources/justMUSIC/assets/images/heart.svg b/Sources/justMUSIC/assets/images/heart.svg
new file mode 100644
index 0000000..f673b81
--- /dev/null
+++ b/Sources/justMUSIC/assets/images/heart.svg
@@ -0,0 +1,3 @@
+
diff --git a/Sources/justMUSIC/assets/images/report.svg b/Sources/justMUSIC/assets/images/report.svg
new file mode 100644
index 0000000..02b113a
--- /dev/null
+++ b/Sources/justMUSIC/assets/images/report.svg
@@ -0,0 +1,5 @@
+
diff --git a/Sources/justMUSIC/assets/images/save.svg b/Sources/justMUSIC/assets/images/save.svg
new file mode 100644
index 0000000..e9169e8
--- /dev/null
+++ b/Sources/justMUSIC/assets/images/save.svg
@@ -0,0 +1,4 @@
+
diff --git a/Sources/justMUSIC/lib/components/button_play_component.dart b/Sources/justMUSIC/lib/components/button_play_component.dart
new file mode 100644
index 0000000..2b252de
--- /dev/null
+++ b/Sources/justMUSIC/lib/components/button_play_component.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/Material.dart';
+
+import '../main.dart';
+import '../model/Music.dart';
+
+class ButtonPlayComponent extends StatefulWidget {
+ final Music music;
+ const ButtonPlayComponent({super.key, required this.music});
+
+ @override
+ State createState() => _ButtonPlayComponentState();
+}
+
+class _ButtonPlayComponentState extends State {
+ bool isPlaying = false;
+
+ @override
+ void initState() {
+ MyApp.audioPlayer.onPlayerComplete.listen((event) {
+ setState(() {
+ isPlaying = false;
+ });
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ child: GestureDetector(
+ onTap: () {
+ if (isPlaying) {
+ widget.music.stopSong();
+ setState(() {
+ isPlaying = !isPlaying;
+ });
+ } else {
+ widget.music.playSong();
+ setState(() {
+ isPlaying = !isPlaying;
+ });
+ }
+ },
+ child: Icon(
+ isPlaying ? Icons.pause_circle : Icons.play_circle,
+ color: Colors.white,
+ size: 53,
+ ),
+ ));
+ }
+}
diff --git a/Sources/justMUSIC/lib/components/comment_component.dart b/Sources/justMUSIC/lib/components/comment_component.dart
index 641f2f1..2f86d14 100644
--- a/Sources/justMUSIC/lib/components/comment_component.dart
+++ b/Sources/justMUSIC/lib/components/comment_component.dart
@@ -11,54 +11,56 @@ class CommentComponent extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
width: double.infinity,
- decoration: BoxDecoration(
- color: bgComment, borderRadius: BorderRadius.circular(10)),
+ decoration: BoxDecoration(color: bgComment, borderRadius: BorderRadius.circular(20)),
padding: EdgeInsets.all(20),
- child: Column(
+ child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- ClipOval(
- child: SizedBox.fromSize(
- // Image radius
- child: Image(
- image: AssetImage("assets/images/exemple_profile.png"),
- width: 40,
- ),
- ),
- ),
- SizedBox(
- width: 10,
- ),
- Text(
- "Melina",
- style: GoogleFonts.plusJakartaSans(
- color: Colors.white, fontWeight: FontWeight.w600),
- ),
- Padding(
- padding: EdgeInsets.only(top: 6, left: 10),
- child: Text(
- "Il y a 2 min(s)",
- style: GoogleFonts.plusJakartaSans(
- color: Colors.white.withOpacity(0.6),
- fontWeight: FontWeight.w200,
- fontSize: 10),
- ),
+ ClipOval(
+ child: SizedBox.fromSize(
+ // Image radius
+ child: Image(
+ image: AssetImage("assets/images/exemple_profile.png"),
+ width: 40,
),
- ],
- ),
- SizedBox(
- height: 10,
- ),
- Text(
- "J’adore ce son auss je trouve qu’il a vraiment une plume de fou le rap c’est trop bien jknei rhozi ugzeor gzhjkev huz vhzbejlh zouebvfiyzv fi hzejkfb zjf ouzebfjzebihf b zuib fiuzebfihzbejfbzejkbf hzbfiébiu zegiu fzieu iuzy giuzeg iuzg eiu zg ",
- style: GoogleFonts.plusJakartaSans(
- color: Colors.white.withOpacity(0.4),
- fontWeight: FontWeight.w300,
- fontSize: 13),
+ ),
),
+ Expanded(
+ child: Column(
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ SizedBox(
+ width: 10,
+ ),
+ Text(
+ "Melina",
+ style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w600),
+ ),
+ Padding(
+ padding: EdgeInsets.only(top: 6, left: 10),
+ child: Text(
+ "Il y a 2 min(s)",
+ style: GoogleFonts.plusJakartaSans(
+ color: Colors.white.withOpacity(0.6), fontWeight: FontWeight.w400, fontSize: 10),
+ ),
+ ),
+ ],
+ ),
+ SizedBox(
+ height: 8,
+ ),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 10),
+ child: Text(
+ "J’adore ce son aussi, je trouve qu’il avait vraiment une plume de fou.",
+ style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w300, fontSize: 11),
+ ),
+ ),
+ ],
+ ),
+ )
],
),
);
diff --git a/Sources/justMUSIC/lib/components/play_button_component.dart b/Sources/justMUSIC/lib/components/play_button_component.dart
index 237881d..9f4b21d 100644
--- a/Sources/justMUSIC/lib/components/play_button_component.dart
+++ b/Sources/justMUSIC/lib/components/play_button_component.dart
@@ -1,4 +1,3 @@
-import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/Material.dart';
import 'package:flutter_animated_play_button/flutter_animated_play_button.dart';
import 'package:ionicons/ionicons.dart';
@@ -12,11 +11,7 @@ class PlayButtonComponent extends StatefulWidget {
final int index;
final bool playing;
const PlayButtonComponent(
- {Key? key,
- required this.music,
- required this.callback,
- required this.playing,
- required this.index})
+ {Key? key, required this.music, required this.callback, required this.playing, required this.index})
: super(key: key);
@override
@@ -24,8 +19,6 @@ class PlayButtonComponent extends StatefulWidget {
}
class _PlayButtonComponentState extends State {
- final player = AudioPlayer();
-
@override
void initState() {
MyApp.audioPlayer.onPlayerComplete.listen((event) {
diff --git a/Sources/justMUSIC/lib/components/post_component.dart b/Sources/justMUSIC/lib/components/post_component.dart
index 4d1de01..c6c0c13 100644
--- a/Sources/justMUSIC/lib/components/post_component.dart
+++ b/Sources/justMUSIC/lib/components/post_component.dart
@@ -259,7 +259,7 @@ class _PostComponentState extends State with TickerProviderStateM
),
widget.post.location.item2 != null
? Text(
- "${widget.post.location?.item1}, ${widget.post.location?.item2}",
+ "${widget.post.location.item1}, ${widget.post.location.item2}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4),
fontWeight: FontWeight.w300,
@@ -284,7 +284,7 @@ class _PostComponentState extends State with TickerProviderStateM
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}",
+ "hier, ${widget.post.date.hour}:${widget.post.date.minute}",
style: GoogleFonts.plusJakartaSans(
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
),
diff --git a/Sources/justMUSIC/lib/screens/detail_post_screen.dart b/Sources/justMUSIC/lib/screens/detail_post_screen.dart
new file mode 100644
index 0000000..700e061
--- /dev/null
+++ b/Sources/justMUSIC/lib/screens/detail_post_screen.dart
@@ -0,0 +1,532 @@
+import 'package:flutter/Material.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: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 '../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 {
+ Future resetFullScreen() async {
+ await SystemChannels.platform.invokeMethod(
+ 'SystemChrome.restoreSystemUIOverlays',
+ );
+ }
+
+ bool choice = false;
+ DateTime today = DateTime.now();
+
+ void switchChoice() {
+ setState(() {
+ choice = !choice;
+ });
+ }
+
+ @override
+ void dispose() {
+ MyApp.audioPlayer.release();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ print("post: ${widget.post.date.toString()}");
+ print("ajrd: ${DateTime.now().toString()}");
+ super.initState();
+ }
+
+ /*void test() {
+ return Column(
+ children: [
+ Align(
+ child: Container(
+ width: 60,
+ height: 5,
+ decoration: BoxDecoration(color: Colors.white.withOpacity(0.3), borderRadius: BorderRadius.circular(20))),
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ Expanded(
+ child: ClipRRect(
+ borderRadius: BorderRadius.only(topRight: Radius.circular(15), topLeft: Radius.circular(15)),
+ child: Padding(
+ padding: EdgeInsets.only(left: defaultPadding, right: defaultPadding),
+ child: SingleChildScrollView(
+ physics: BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
+ child: Wrap(
+ // to apply margin in the main axis of the wrap
+ runSpacing: 10,
+ children: [
+ Container(height: 5),
+ Align(
+ child: RichText(
+ text: TextSpan(
+ text: "3",
+ style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w600),
+ children: [
+ TextSpan(
+ text: " commentaires",
+ style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w300),
+ )
+ ])),
+ ),
+ SizedBox(height: 20),
+ CommentComponent(),
+ CommentComponent(),
+ CommentComponent(),
+ Container(height: 10),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ 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(
+ // Image radius
+ child: const Image(
+ image: AssetImage("assets/images/exemple_profile.png"),
+ width: 45,
+ ),
+ ),
+ ),
+ SizedBox(
+ width: 10,
+ ),
+ Expanded(
+ child: TextField(
+ keyboardAppearance: Brightness.dark,
+ 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)),
+ ),
+ )
+ ],
+ ),
+ ),
+ )),
+ ),
+ ],
+ );
+ }*/
+ 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,
+ 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,
+ ),
+ )),
+ 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,
+ ),
+ ),
+ ),
+ )
+ : 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),
+ 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), // Couleur de la bordure
+ width: 1.0, // Épaisseur de la bordure
+ ),
+ ),
+ ),
+ child: Column(
+ children: [
+ Padding(
+ padding: EdgeInsets.symmetric(vertical: 20),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ SvgPicture.asset("assets/images/heart.svg", semanticsLabel: 'Like Logo'),
+ 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'),
+ ],
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(15.0),
+ child: RichText(
+ text: TextSpan(
+ text: "3",
+ style: GoogleFonts.plusJakartaSans(
+ color: Colors.white, fontWeight: FontWeight.w800),
+ children: [
+ TextSpan(
+ text: " commentaires",
+ style: GoogleFonts.plusJakartaSans(
+ color: Colors.white, fontWeight: FontWeight.w400),
+ )
+ ])),
+ ),
+ Padding(
+ padding: EdgeInsets.fromLTRB(20, 0, 20, 20),
+ child: Wrap(
+ runSpacing: 13,
+ children: [
+ CommentComponent(),
+ CommentComponent(),
+ CommentComponent(),
+ ],
+ ),
+ )
+ ],
+ ),
+ ),
+ ],
+ ),
+ 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),
+ // implement 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(
+ // Image radius
+ child: Image.network(
+ MyApp.userViewModel.userCurrent.pp,
+ width: 45,
+ ),
+ ),
+ ),
+ SizedBox(
+ width: 10,
+ ),
+ Expanded(
+ child: TextField(
+ keyboardAppearance: Brightness.dark,
+ 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)),
+ ),
+ )
+ ],
+ ),
+ ),
+ )),
+ ),
+ ],
+ ),
+ ));
+ }
+}
+
+class MyBehavior extends ScrollBehavior {
+ @override
+ Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
+ return child;
+ }
+}
diff --git a/Sources/justMUSIC/lib/screens/feed_screen.dart b/Sources/justMUSIC/lib/screens/feed_screen.dart
index 7670d92..0324f71 100644
--- a/Sources/justMUSIC/lib/screens/feed_screen.dart
+++ b/Sources/justMUSIC/lib/screens/feed_screen.dart
@@ -1,14 +1,21 @@
+import 'dart:async';
+
+import 'package:another_flushbar/flushbar.dart';
import 'package:circular_reveal_animation/circular_reveal_animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:google_fonts/google_fonts.dart';
+import 'package:ionicons/ionicons.dart';
import 'package:justmusic/main.dart';
-import '../components/comment_component.dart';
+import 'package:lottie/lottie.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);
@@ -17,17 +24,21 @@ class FeedScreen extends StatefulWidget {
State createState() => _FeedScreenState();
}
-class _FeedScreenState extends State
- with SingleTickerProviderStateMixin {
+class _FeedScreenState extends State with SingleTickerProviderStateMixin {
late AnimationController animationController;
late Animation animation;
late List friendFeed;
+ Timer? timer;
+
late List discoveryFeed;
late List displayFeed;
+ final DateTime midnight = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day + 1);
+ bool isDismissed = true;
@override
void initState() {
super.initState();
+
MyApp.postViewModel.getPostsFriends();
friendFeed = MyApp.postViewModel.postsFriends;
MyApp.postViewModel.getBestPosts();
@@ -44,10 +55,90 @@ class _FeedScreenState extends State
animationController.forward();
}
- Future resetFullScreen() async {
- await SystemChannels.platform.invokeMethod(
- 'SystemChrome.restoreSystemUIOverlays',
- );
+ Future showCapsuleDot() async {
+ bool res = await MyApp.postViewModel.getAvailable();
+ if (isDismissed) {
+ if (res) {
+ setState(() {
+ isDismissed = !isDismissed;
+ });
+ Flushbar(
+ maxWidth: 210,
+ animationDuration: Duration(seconds: 1),
+ forwardAnimationCurve: Curves.easeOutCirc,
+ margin: EdgeInsets.fromLTRB(0, 0, 0, 0),
+ icon: Icon(
+ Ionicons.sparkles,
+ color: Colors.white,
+ size: 18,
+ ),
+ padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
+ messageText: Align(
+ alignment: Alignment.centerLeft,
+ child: Text(
+ "Capsule disponible",
+ style: GoogleFonts.plusJakartaSans(color: Colors.grey, fontSize: 15),
+ ),
+ ),
+ flushbarStyle: FlushbarStyle.FLOATING,
+ flushbarPosition: FlushbarPosition.BOTTOM,
+ textDirection: Directionality.of(context),
+ borderRadius: BorderRadius.circular(1000),
+ borderWidth: 1,
+ isDismissible: false,
+ borderColor: Colors.white.withOpacity(0.04),
+ duration: const Duration(minutes: 100),
+ leftBarIndicatorColor: Colors.transparent,
+ positionOffset: 20,
+ onTap: (_) {
+ Navigator.pop(context);
+ Navigator.pushNamed(context, '/post');
+ },
+ ).show(context).then((value) {
+ isDismissed = !isDismissed;
+ });
+ } else {
+ setState(() {
+ isDismissed = !isDismissed;
+ });
+ Flushbar(
+ maxWidth: 155,
+ animationDuration: Duration(seconds: 1),
+ isDismissible: false,
+ forwardAnimationCurve: Curves.easeOutCirc,
+ margin: EdgeInsets.fromLTRB(0, 0, 0, 0),
+ icon: Lottie.asset(
+ 'assets/animations/LottieHourGlass.json',
+ width: 26,
+ fit: BoxFit.fill,
+ ),
+ padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
+ messageText: Align(
+ alignment: Alignment.centerLeft,
+ child: CountdownTimer(
+ endTime: midnight.millisecondsSinceEpoch - 2 * 60 * 60 * 1000,
+ textStyle: GoogleFonts.plusJakartaSans(color: Colors.grey, fontSize: 15),
+ ),
+ ),
+ flushbarStyle: FlushbarStyle.FLOATING,
+ flushbarPosition: FlushbarPosition.BOTTOM,
+ textDirection: Directionality.of(context),
+ borderRadius: BorderRadius.circular(1000),
+ borderWidth: 1,
+ borderColor: Colors.white.withOpacity(0.04),
+ duration: const Duration(minutes: 100),
+ leftBarIndicatorColor: Colors.transparent,
+ positionOffset: 20,
+ onTap: (_) {},
+ ).show(context).then((value) {
+ {
+ setState(() {
+ isDismissed = !isDismissed;
+ });
+ }
+ });
+ }
+ }
}
Future _refresh() async {
@@ -87,171 +178,18 @@ class _FeedScreenState extends State
isScrollControlled: true,
context: context,
shape: const RoundedRectangleBorder(
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(20), topRight: Radius.circular(20))),
+ borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))),
builder: ((BuildContext context) {
- return GestureDetector(
- onTap: () {
- FocusScopeNode currentFocus = FocusScope.of(context);
- if (!currentFocus.hasPrimaryFocus) {
- currentFocus.unfocus();
- resetFullScreen();
- }
- },
- child: Container(
- height: 720.h,
- margin: const EdgeInsets.only(top: 10),
- child: Column(
- children: [
- Align(
- child: Container(
- width: 60,
- height: 5,
- decoration: BoxDecoration(
- color: Colors.white.withOpacity(0.3),
- borderRadius: BorderRadius.circular(20))),
- ),
- const SizedBox(
- height: 20,
- ),
- Expanded(
- child: ClipRRect(
- borderRadius: BorderRadius.only(
- topRight: Radius.circular(15),
- topLeft: Radius.circular(15)),
- child: Padding(
- padding: EdgeInsets.only(
- left: defaultPadding, right: defaultPadding),
- child: SingleChildScrollView(
- physics: BouncingScrollPhysics(
- decelerationRate: ScrollDecelerationRate.fast),
- child: Wrap(
- // to apply margin in the main axis of the wrap
- runSpacing: 10,
- children: [
- PostComponent(
- callback: null,
- post: displayFeed[index],
- index: index,
- ),
- Container(height: 5),
- displayFeed[index].description == null
- ? Container()
- : Padding(
- padding: const EdgeInsets.only(bottom: 20),
- child: Text(
- '${displayFeed[index].description ?? ""}',
- style: GoogleFonts.plusJakartaSans(
- color: Colors.white,
- fontWeight: FontWeight.w200)),
- ),
- Align(
- child: RichText(
- text: TextSpan(
- text: "3",
- style: GoogleFonts.plusJakartaSans(
- color: Colors.white,
- fontWeight: FontWeight.w600),
- children: [
- TextSpan(
- text: " commentaires",
- style: GoogleFonts.plusJakartaSans(
- color: Colors.white,
- fontWeight: FontWeight.w300),
- )
- ])),
- ),
- SizedBox(height: 20),
- CommentComponent(),
- CommentComponent(),
- CommentComponent(),
- Container(height: 10),
- ],
- ),
- ),
- ),
- ),
- ),
- 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(
- // Image radius
- child: const Image(
- image: AssetImage(
- "assets/images/exemple_profile.png"),
- width: 45,
- ),
- ),
- ),
- SizedBox(
- width: 10,
- ),
- Expanded(
- child: TextField(
- keyboardAppearance: Brightness.dark,
- 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)),
- ),
- )
- ],
- ),
- ),
- )),
- ),
- ],
- ),
- ),
- );
+ return ClipRRect(
+ borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
+ child: DetailPostScreen(post: displayFeed[index]));
}),
);
}
@override
Widget build(BuildContext context) {
+ showCapsuleDot();
return Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: bgColor,
@@ -265,21 +203,16 @@ class _FeedScreenState extends State
Container(
decoration: const BoxDecoration(
image: DecorationImage(
- image: AssetImage("assets/images/empty_bg.png"),
- fit: BoxFit.cover,
- opacity: 0.3),
+ image: AssetImage("assets/images/empty_bg.png"), fit: BoxFit.cover, opacity: 0.3),
),
child: Padding(
- padding:
- EdgeInsets.only(top: 140.h, left: defaultPadding),
+ 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))
+ color: Colors.white, fontSize: 23, fontWeight: FontWeight.w800))
],
),
),
@@ -292,14 +225,8 @@ class _FeedScreenState extends State
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
- stops: [
- 0.3,
- 1
- ],
- colors: [
- bgColor.withOpacity(0.9),
- bgColor.withOpacity(0)
- ])),
+ stops: [0.3, 1],
+ colors: [bgColor.withOpacity(0.9), bgColor.withOpacity(0)])),
),
),
),
@@ -325,26 +252,21 @@ class _FeedScreenState extends State
centerOffset: Offset(30.w, -100),
child: Container(
constraints: BoxConstraints(maxWidth: 600),
- padding: EdgeInsets.fromLTRB(
- defaultPadding, 100.h, defaultPadding, 0),
+ padding: EdgeInsets.fromLTRB(defaultPadding, 100.h, defaultPadding, 0),
child: RefreshIndicator(
displacement: 20,
triggerMode: RefreshIndicatorTriggerMode.onEdge,
onRefresh: _refresh,
child: ListView.builder(
- physics: const BouncingScrollPhysics(
- decelerationRate:
- ScrollDecelerationRate.fast),
+ physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
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),
+ child:
+ PostComponent(callback: openDetailPost, post: displayFeed[index], index: index),
);
},
),
@@ -359,14 +281,8 @@ class _FeedScreenState extends State
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
- stops: [
- 0.3,
- 1
- ],
- colors: [
- bgColor.withOpacity(0.9),
- bgColor.withOpacity(0)
- ])),
+ stops: [0.3, 1],
+ colors: [bgColor.withOpacity(0.9), bgColor.withOpacity(0)])),
),
),
),
diff --git a/Sources/justMUSIC/pubspec.lock b/Sources/justMUSIC/pubspec.lock
index b0be0a1..a63a241 100644
--- a/Sources/justMUSIC/pubspec.lock
+++ b/Sources/justMUSIC/pubspec.lock
@@ -41,6 +41,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.7"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
async:
dependency: transitive
description:
@@ -406,6 +414,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
+ flutter_svg:
+ dependency: "direct main"
+ description:
+ name: flutter_svg
+ sha256: "8c5d68a82add3ca76d792f058b186a0599414f279f00ece4830b9b231b570338"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.7"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -672,6 +688,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.3"
+ path_parsing:
+ dependency: transitive
+ description:
+ name: path_parsing
+ sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.1"
path_provider:
dependency: transitive
description:
@@ -720,6 +744,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.7"
+ petitparser:
+ dependency: transitive
+ description:
+ name: petitparser
+ sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.4.0"
pinch_zoom:
dependency: "direct main"
description:
@@ -869,6 +901,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.7"
+ vector_graphics:
+ dependency: transitive
+ description:
+ name: vector_graphics
+ sha256: "670f6e07aca990b4a2bcdc08a784193c4ccdd1932620244c3a86bb72a0eac67f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.7"
+ vector_graphics_codec:
+ dependency: transitive
+ description:
+ name: vector_graphics_codec
+ sha256: "7451721781d967db9933b63f5733b1c4533022c0ba373a01bdd79d1a5457f69f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.7"
+ vector_graphics_compiler:
+ dependency: transitive
+ description:
+ name: vector_graphics_compiler
+ sha256: "80a13c613c8bde758b1464a1755a7b3a8f2b6cec61fbf0f5a53c94c30f03ba2e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.7"
vector_math:
dependency: transitive
description:
@@ -893,6 +949,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
+ xml:
+ dependency: transitive
+ description:
+ name: xml
+ sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.3.0"
zoom_tap_animation:
dependency: "direct main"
description:
diff --git a/Sources/justMUSIC/pubspec.yaml b/Sources/justMUSIC/pubspec.yaml
index f3ad4f0..bc11957 100644
--- a/Sources/justMUSIC/pubspec.yaml
+++ b/Sources/justMUSIC/pubspec.yaml
@@ -70,6 +70,7 @@ dependencies:
lottie: ^2.5.0
custom_refresh_indicator: ^2.2.1
animations: ^2.0.7
+ flutter_svg: ^2.0.7
dev_dependencies:
flutter_test: