Merge with HISTORIC_CAPSULE_LDE 🔀
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
e3017fad2a
@ -1,257 +1,257 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:gradient_borders/box_borders/gradient_box_border.dart';
|
import 'package:gradient_borders/box_borders/gradient_box_border.dart';
|
||||||
import 'package:justmusic/components/profil_picture_component.dart';
|
import 'package:justmusic/components/profil_picture_component.dart';
|
||||||
import 'package:text_scroll/text_scroll.dart';
|
import 'package:text_scroll/text_scroll.dart';
|
||||||
import 'package:zoom_tap_animation/zoom_tap_animation.dart';
|
import 'package:zoom_tap_animation/zoom_tap_animation.dart';
|
||||||
|
|
||||||
import '../model/Post.dart';
|
import '../model/Post.dart';
|
||||||
|
|
||||||
class PostComponent extends StatefulWidget {
|
class PostComponent extends StatefulWidget {
|
||||||
final Function(Post)? callback;
|
final Function(Post)? callback;
|
||||||
final Post post;
|
final Post post;
|
||||||
final int index;
|
final int index;
|
||||||
|
|
||||||
PostComponent({Key? key, required this.callback, required this.post, required this.index}) : super(key: key);
|
PostComponent({Key? key, required this.callback, required this.post, required this.index}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PostComponent> createState() => _PostComponentState();
|
State<PostComponent> createState() => _PostComponentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PostComponentState extends State<PostComponent> with TickerProviderStateMixin {
|
class _PostComponentState extends State<PostComponent> with TickerProviderStateMixin {
|
||||||
bool choice = false;
|
bool choice = false;
|
||||||
DateTime today = DateTime.now();
|
DateTime today = DateTime.now();
|
||||||
|
|
||||||
void switchChoice() {
|
void switchChoice() {
|
||||||
setState(() {
|
setState(() {
|
||||||
choice = !choice;
|
choice = !choice;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<String> frenchMonths = [
|
final List<String> frenchMonths = [
|
||||||
'Janvier',
|
'Janvier',
|
||||||
'Février',
|
'Février',
|
||||||
'Mars',
|
'Mars',
|
||||||
'Avril',
|
'Avril',
|
||||||
'Mai',
|
'Mai',
|
||||||
'Juin',
|
'Juin',
|
||||||
'Juillet',
|
'Juillet',
|
||||||
'Août',
|
'Août',
|
||||||
'Septembre',
|
'Septembre',
|
||||||
'Octobre',
|
'Octobre',
|
||||||
'Novembre',
|
'Novembre',
|
||||||
'Décembre'
|
'Décembre'
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
print("post: ${widget.post.date.toString()}");
|
print("post: ${widget.post.date.toString()}");
|
||||||
print("ajrd: ${DateTime.now().toString()}");
|
print("ajrd: ${DateTime.now().toString()}");
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var mins = "0";
|
var mins = "0";
|
||||||
if (widget.post.date.minute < 10) {
|
if (widget.post.date.minute < 10) {
|
||||||
mins = "0${widget.post.date.minute}";
|
mins = "0${widget.post.date.minute}";
|
||||||
} else {
|
} else {
|
||||||
mins = widget.post.date.minute.toString();
|
mins = widget.post.date.minute.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: switchChoice,
|
onTap: switchChoice,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
ProfilPictureComponent(user: widget.post.user),
|
ProfilPictureComponent(user: widget.post.user),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 8,
|
flex: 8,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.post.user.pseudo,
|
widget.post.user.pseudo,
|
||||||
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w600),
|
style: GoogleFonts.plusJakartaSans(color: Colors.white, fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
widget.post.location.item2 != null
|
widget.post.location.item2 != null
|
||||||
? Text(
|
? Text(
|
||||||
"${widget.post.location.item1}, ${widget.post.location.item2}",
|
"${widget.post.location.item1}, ${widget.post.location.item2}",
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: Colors.white.withOpacity(0.4),
|
color: Colors.white.withOpacity(0.4),
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
fontSize: 13),
|
fontSize: 13),
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
"",
|
"",
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: Colors.white.withOpacity(0.4),
|
color: Colors.white.withOpacity(0.4),
|
||||||
fontWeight: FontWeight.w300,
|
fontWeight: FontWeight.w300,
|
||||||
fontSize: 13),
|
fontSize: 13),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DateTime(today.year, today.month, today.day).isAtSameMomentAs(
|
DateTime(today.year, today.month, today.day).isAtSameMomentAs(
|
||||||
DateTime(widget.post.date.year, widget.post.date.month, widget.post.date.day))
|
DateTime(widget.post.date.year, widget.post.date.month, widget.post.date.day))
|
||||||
? Text(
|
? Text(
|
||||||
"Aujourd'hui, ${widget.post.date.hour}:$mins",
|
"Aujourd'hui, ${widget.post.date.hour}:$mins",
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
|
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
'${widget.post.date.day} ${frenchMonths[widget.post.date.month - 1]}, ${widget.post.date.hour}:$mins',
|
'${widget.post.date.day} ${frenchMonths[widget.post.date.month - 1]}, ${widget.post.date.hour}:$mins',
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
|
color: Colors.white.withOpacity(0.4), fontWeight: FontWeight.w300, fontSize: 13),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ZoomTapAnimation(
|
ZoomTapAnimation(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.callback!(widget.post);
|
widget.callback!(widget.post);
|
||||||
},
|
},
|
||||||
enableLongTapRepeatEvent: false,
|
enableLongTapRepeatEvent: false,
|
||||||
longTapRepeatDuration: const Duration(milliseconds: 100),
|
longTapRepeatDuration: const Duration(milliseconds: 100),
|
||||||
begin: 1.0,
|
begin: 1.0,
|
||||||
end: 0.99,
|
end: 0.99,
|
||||||
beginDuration: const Duration(milliseconds: 70),
|
beginDuration: const Duration(milliseconds: 70),
|
||||||
endDuration: const Duration(milliseconds: 100),
|
endDuration: const Duration(milliseconds: 100),
|
||||||
beginCurve: Curves.decelerate,
|
beginCurve: Curves.decelerate,
|
||||||
endCurve: Curves.easeInOutSine,
|
endCurve: Curves.easeInOutSine,
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: 1 / 1,
|
aspectRatio: 1 / 1,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
// add border
|
// add border
|
||||||
border: const GradientBoxBorder(
|
border: const GradientBoxBorder(
|
||||||
gradient: LinearGradient(colors: [
|
gradient: LinearGradient(colors: [
|
||||||
Colors.transparent,
|
Colors.transparent,
|
||||||
Color(0xFF323232),
|
Color(0xFF323232),
|
||||||
], begin: Alignment.topCenter, end: Alignment.bottomCenter),
|
], begin: Alignment.topCenter, end: Alignment.bottomCenter),
|
||||||
width: 2.5,
|
width: 2.5,
|
||||||
),
|
),
|
||||||
// set border radius
|
// set border radius
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(18),
|
borderRadius: BorderRadius.circular(18),
|
||||||
// implement image
|
// implement image
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: FadeInImage.assetNetwork(
|
child: FadeInImage.assetNetwork(
|
||||||
image: widget.post.music.cover!,
|
image: widget.post.music.cover!,
|
||||||
fadeInDuration: const Duration(milliseconds: 100),
|
fadeInDuration: const Duration(milliseconds: 100),
|
||||||
placeholder: "assets/images/loadingPlaceholder.gif",
|
placeholder: "assets/images/loadingPlaceholder.gif",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Image(
|
Image(
|
||||||
image: AssetImage("assets/images/shadow_post.png"),
|
image: AssetImage("assets/images/shadow_post.png"),
|
||||||
opacity: AnimationController(vsync: this, value: 0.7),
|
opacity: AnimationController(vsync: this, value: 0.7),
|
||||||
fit: BoxFit.fitHeight,
|
fit: BoxFit.fitHeight,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
),
|
),
|
||||||
widget.post.description == null
|
widget.post.description == null
|
||||||
? Container()
|
? Container()
|
||||||
: Padding(
|
: Padding(
|
||||||
padding: EdgeInsets.all(15),
|
padding: EdgeInsets.all(15),
|
||||||
child: AutoSizeText(
|
child: AutoSizeText(
|
||||||
'“${widget.post.description}”',
|
'“${widget.post.description}”',
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 15.sp),
|
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 15.sp),
|
||||||
maxFontSize: 20,
|
maxFontSize: 20,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
widget.post.selfie != null
|
widget.post.selfie != null
|
||||||
? Positioned(
|
? Positioned(
|
||||||
top: 0,
|
top: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(12),
|
padding: EdgeInsets.all(12),
|
||||||
child: Container(
|
child: Container(
|
||||||
constraints: BoxConstraints(maxWidth: 140, maxHeight: 140),
|
constraints: BoxConstraints(maxWidth: 140, maxHeight: 140),
|
||||||
width: 90.sp,
|
width: 90.sp,
|
||||||
height: 90.sp,
|
height: 90.sp,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
// add border
|
// add border
|
||||||
border: Border.all(width: 3, color: Colors.white),
|
border: Border.all(width: 3, color: Colors.white),
|
||||||
// set border radius
|
// set border radius
|
||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(15),
|
||||||
),
|
),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(13),
|
borderRadius: BorderRadius.circular(13),
|
||||||
// implement image
|
// implement image
|
||||||
child: FadeInImage.assetNetwork(
|
child: FadeInImage.assetNetwork(
|
||||||
image: widget.post.selfie!,
|
image: widget.post.selfie!,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
fadeInDuration: const Duration(milliseconds: 100),
|
fadeInDuration: const Duration(milliseconds: 100),
|
||||||
placeholder: "assets/images/loadingPlaceholder.gif",
|
placeholder: "assets/images/loadingPlaceholder.gif",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
: Container(),
|
: Container(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
SizedBox(height: 15),
|
SizedBox(height: 15),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 8,
|
flex: 8,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(bottom: 2),
|
padding: EdgeInsets.only(bottom: 2),
|
||||||
child: TextScroll(
|
child: TextScroll(
|
||||||
widget.post.music.title!,
|
widget.post.music.title!,
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
height: 1, color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
|
height: 1, color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
|
||||||
mode: TextScrollMode.endless,
|
mode: TextScrollMode.endless,
|
||||||
velocity: Velocity(pixelsPerSecond: Offset(50, 20)),
|
velocity: Velocity(pixelsPerSecond: Offset(50, 20)),
|
||||||
pauseBetween: Duration(milliseconds: 500),
|
pauseBetween: Duration(milliseconds: 500),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
Container(width: 10),
|
Container(width: 10),
|
||||||
AutoSizeText(
|
AutoSizeText(
|
||||||
widget.post.music.date.toString(),
|
widget.post.music.date.toString(),
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
|
color: Colors.white, fontWeight: FontWeight.w600, fontSize: 26.h),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
maxFontSize: 20,
|
maxFontSize: 20,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
TextScroll(
|
TextScroll(
|
||||||
widget.post.music.artists.first.name!,
|
widget.post.music.artists.first.name!,
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
height: 1, color: Colors.white.withOpacity(0.5), fontWeight: FontWeight.w300, fontSize: 16.h),
|
height: 1, color: Colors.white.withOpacity(0.5), fontWeight: FontWeight.w300, fontSize: 16.h),
|
||||||
mode: TextScrollMode.endless,
|
mode: TextScrollMode.endless,
|
||||||
pauseBetween: Duration(milliseconds: 500),
|
pauseBetween: Duration(milliseconds: 500),
|
||||||
velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
|
velocity: Velocity(pixelsPerSecond: Offset(20, 0)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,418 +1,418 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/Material.dart';
|
import 'package:flutter/Material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:justmusic/model/Music.dart';
|
import 'package:justmusic/model/Music.dart';
|
||||||
|
|
||||||
import '../components/music_list_component.dart';
|
import '../components/music_list_component.dart';
|
||||||
import '../values/constants.dart';
|
import '../values/constants.dart';
|
||||||
import '../main.dart';
|
import '../main.dart';
|
||||||
|
|
||||||
class SearchSongScreen extends StatefulWidget {
|
class SearchSongScreen extends StatefulWidget {
|
||||||
final Function callback;
|
final Function callback;
|
||||||
const SearchSongScreen({Key? key, required this.callback}) : super(key: key);
|
const SearchSongScreen({Key? key, required this.callback}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SearchSongScreen> createState() => _SearchSongScreenState();
|
State<SearchSongScreen> createState() => _SearchSongScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SearchSongScreenState extends State<SearchSongScreen> {
|
class _SearchSongScreenState extends State<SearchSongScreen> {
|
||||||
final ScrollController _scrollController = ScrollController();
|
final ScrollController _scrollController = ScrollController();
|
||||||
final TextEditingController _textEditingController = TextEditingController();
|
final TextEditingController _textEditingController = TextEditingController();
|
||||||
PageController controller = PageController();
|
PageController controller = PageController();
|
||||||
bool isCollectionSelected = false;
|
bool isCollectionSelected = false;
|
||||||
|
|
||||||
int? playingIndex;
|
int? playingIndex;
|
||||||
|
|
||||||
Future<void> resetFullScreen() async {
|
Future<void> resetFullScreen() async {
|
||||||
await SystemChannels.platform.invokeMethod<void>(
|
await SystemChannels.platform.invokeMethod<void>(
|
||||||
'SystemChrome.restoreSystemUIOverlays',
|
'SystemChrome.restoreSystemUIOverlays',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
fetchTrendingMusic();
|
fetchTrendingMusic();
|
||||||
_scrollController.addListener(_scrollListener);
|
_scrollController.addListener(_scrollListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetchTrendingMusic() async {
|
Future<void> fetchTrendingMusic() async {
|
||||||
await MyApp.musicViewModel.getMusicsWithPlaylistId('37i9dQZF1DX1X23oiQRTB5').then((value) {
|
await MyApp.musicViewModel.getMusicsWithPlaylistId('37i9dQZF1DX1X23oiQRTB5').then((value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredData = value;
|
filteredData = value;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _scrollListener() async {
|
Future<void> _scrollListener() async {
|
||||||
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
|
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
|
||||||
filteredData.addAll(await MyApp.musicViewModel
|
filteredData.addAll(await MyApp.musicViewModel
|
||||||
.getMusicsWithName(_textEditingController.text, limit: 10, offset: filteredData.length));
|
.getMusicsWithName(_textEditingController.text, limit: 10, offset: filteredData.length));
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredData = filteredData;
|
filteredData = filteredData;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (_scrollController.offset >= _scrollController.position.maxScrollExtent &&
|
if (_scrollController.offset >= _scrollController.position.maxScrollExtent &&
|
||||||
!_scrollController.position.outOfRange) {
|
!_scrollController.position.outOfRange) {
|
||||||
setState(() {
|
setState(() {
|
||||||
//you can do anything here
|
//you can do anything here
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (_scrollController.offset <= _scrollController.position.minScrollExtent &&
|
if (_scrollController.offset <= _scrollController.position.minScrollExtent &&
|
||||||
!_scrollController.position.outOfRange) {
|
!_scrollController.position.outOfRange) {
|
||||||
setState(() {
|
setState(() {
|
||||||
Timer(Duration(milliseconds: 1), () => _scrollController.jumpTo(0));
|
Timer(Duration(milliseconds: 1), () => _scrollController.jumpTo(0));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Music> filteredData = [];
|
List<Music> filteredData = [];
|
||||||
|
|
||||||
void playMusic(int index) {
|
void playMusic(int index) {
|
||||||
if (playingIndex == index) {
|
if (playingIndex == index) {
|
||||||
setState(() {
|
setState(() {
|
||||||
playingIndex = null;
|
playingIndex = null;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
playingIndex = index;
|
playingIndex = index;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_changePage(int index) {
|
_changePage(int index) {
|
||||||
/*if (isCollectionSelected) {
|
/*if (isCollectionSelected) {
|
||||||
setState(() {
|
setState(() {
|
||||||
isCollectionSelected = !isCollectionSelected;
|
isCollectionSelected = !isCollectionSelected;
|
||||||
controller.animateTo(1, duration: Duration(milliseconds: 200), curve: Curves.easeOut);
|
controller.animateTo(1, duration: Duration(milliseconds: 200), curve: Curves.easeOut);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
isCollectionSelected = !isCollectionSelected;
|
isCollectionSelected = !isCollectionSelected;
|
||||||
controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeOut);
|
controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeOut);
|
||||||
});
|
});
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Music>> _fetchSavedSong() async {
|
Future<List<Music>> _fetchSavedSong() async {
|
||||||
return await MyApp.musicViewModel.getFavoriteMusicsByUserId(MyApp.userViewModel.userCurrent.id);
|
return await MyApp.musicViewModel.getFavoriteMusicsByUserId(MyApp.userViewModel.userCurrent.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
MyApp.audioPlayer.pause();
|
MyApp.audioPlayer.pause();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
double screenHeight = MediaQuery.of(context).size.height;
|
double screenHeight = MediaQuery.of(context).size.height;
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||||
if (!currentFocus.hasPrimaryFocus) {
|
if (!currentFocus.hasPrimaryFocus) {
|
||||||
currentFocus.unfocus();
|
currentFocus.unfocus();
|
||||||
resetFullScreen();
|
resetFullScreen();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: BackdropFilter(
|
child: BackdropFilter(
|
||||||
filter: ImageFilter.blur(
|
filter: ImageFilter.blur(
|
||||||
sigmaX: 60.0,
|
sigmaX: 60.0,
|
||||||
sigmaY: 60.0,
|
sigmaY: 60.0,
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: bgAppBar.withOpacity(0.5),
|
color: bgAppBar.withOpacity(0.5),
|
||||||
height: screenHeight - 50,
|
height: screenHeight - 50,
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Align(
|
Align(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 60,
|
width: 60,
|
||||||
height: 5,
|
height: 5,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Color(0xFF3A3A3A).withOpacity(0.6), borderRadius: BorderRadius.circular(20))),
|
color: Color(0xFF3A3A3A).withOpacity(0.6), borderRadius: BorderRadius.circular(20))),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 10,
|
height: 10,
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 10, left: 20, right: 20),
|
padding: const EdgeInsets.only(bottom: 10, left: 20, right: 20),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _textEditingController,
|
controller: _textEditingController,
|
||||||
keyboardAppearance: Brightness.dark,
|
keyboardAppearance: Brightness.dark,
|
||||||
onEditingComplete: resetFullScreen,
|
onEditingComplete: resetFullScreen,
|
||||||
onSubmitted: (value) async {
|
onSubmitted: (value) async {
|
||||||
if (_textEditingController.text.isEmpty) {
|
if (_textEditingController.text.isEmpty) {
|
||||||
fetchTrendingMusic();
|
fetchTrendingMusic();
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredData = [];
|
filteredData = [];
|
||||||
});
|
});
|
||||||
filteredData = await MyApp.musicViewModel.getMusicsWithNameOrArtistName(value);
|
filteredData = await MyApp.musicViewModel.getMusicsWithNameOrArtistName(value);
|
||||||
setState(() {
|
setState(() {
|
||||||
filteredData = filteredData;
|
filteredData = filteredData;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeIn);
|
controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.easeIn);
|
||||||
},
|
},
|
||||||
cursorColor: Colors.white,
|
cursorColor: Colors.white,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
style: GoogleFonts.plusJakartaSans(color: grayText),
|
style: GoogleFonts.plusJakartaSans(color: grayText),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
prefixIcon: const Icon(
|
prefixIcon: const Icon(
|
||||||
Icons.search,
|
Icons.search,
|
||||||
color: grayColor,
|
color: grayColor,
|
||||||
),
|
),
|
||||||
focusedBorder: const OutlineInputBorder(
|
focusedBorder: const OutlineInputBorder(
|
||||||
borderSide: BorderSide(width: 1, color: grayColor),
|
borderSide: BorderSide(width: 1, color: grayColor),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.only(top: 0, bottom: 0, left: defaultPadding, right: defaultPadding),
|
const EdgeInsets.only(top: 0, bottom: 0, left: defaultPadding, right: defaultPadding),
|
||||||
fillColor: searchBarColor,
|
fillColor: searchBarColor,
|
||||||
filled: true,
|
filled: true,
|
||||||
focusColor: grayText,
|
focusColor: grayText,
|
||||||
enabledBorder: const OutlineInputBorder(
|
enabledBorder: const OutlineInputBorder(
|
||||||
borderSide: BorderSide(width: 1, color: grayColor),
|
borderSide: BorderSide(width: 1, color: grayColor),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||||
hintText: 'Chercher un son',
|
hintText: 'Chercher un son',
|
||||||
hintStyle: GoogleFonts.plusJakartaSans(color: grayHint)),
|
hintStyle: GoogleFonts.plusJakartaSans(color: grayHint)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 10, bottom: 20),
|
padding: const EdgeInsets.only(top: 10, bottom: 20),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: _changePage(0),
|
onTap: _changePage(0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Recherche",
|
"Recherche",
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: isCollectionSelected ? Color(0xFF9A9A9A) : Colors.white,
|
color: isCollectionSelected ? Color(0xFF9A9A9A) : Colors.white,
|
||||||
fontWeight: isCollectionSelected ? FontWeight.w500 : FontWeight.w700),
|
fontWeight: isCollectionSelected ? FontWeight.w500 : FontWeight.w700),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: _changePage(1),
|
onTap: _changePage(1),
|
||||||
child: Text("Collection",
|
child: Text("Collection",
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: isCollectionSelected ? Colors.white : Color(0xFF9A9A9A),
|
color: isCollectionSelected ? Colors.white : Color(0xFF9A9A9A),
|
||||||
fontWeight: isCollectionSelected ? FontWeight.w700 : FontWeight.w500)),
|
fontWeight: isCollectionSelected ? FontWeight.w700 : FontWeight.w500)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: PageView(
|
child: PageView(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
physics: BouncingScrollPhysics(),
|
physics: BouncingScrollPhysics(),
|
||||||
onPageChanged: (index) {
|
onPageChanged: (index) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (index == 1) {
|
if (index == 1) {
|
||||||
isCollectionSelected = true;
|
isCollectionSelected = true;
|
||||||
} else {
|
} else {
|
||||||
isCollectionSelected = false;
|
isCollectionSelected = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
ScrollConfiguration(
|
ScrollConfiguration(
|
||||||
behavior: ScrollBehavior().copyWith(scrollbars: true),
|
behavior: ScrollBehavior().copyWith(scrollbars: true),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
|
physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemCount: filteredData.length,
|
itemCount: filteredData.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (playingIndex == index) {
|
if (playingIndex == index) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.callback(filteredData[index]);
|
widget.callback(filteredData[index]);
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
child: MusicListComponent(
|
child: MusicListComponent(
|
||||||
music: filteredData[index],
|
music: filteredData[index],
|
||||||
playing: true,
|
playing: true,
|
||||||
callback: playMusic,
|
callback: playMusic,
|
||||||
index: index,
|
index: index,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.callback(filteredData[index]);
|
widget.callback(filteredData[index]);
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
child: MusicListComponent(
|
child: MusicListComponent(
|
||||||
music: filteredData[index],
|
music: filteredData[index],
|
||||||
playing: false,
|
playing: false,
|
||||||
callback: playMusic,
|
callback: playMusic,
|
||||||
index: index,
|
index: index,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
ScrollConfiguration(
|
ScrollConfiguration(
|
||||||
behavior: ScrollBehavior().copyWith(scrollbars: true),
|
behavior: ScrollBehavior().copyWith(scrollbars: true),
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: _fetchSavedSong(),
|
future: _fetchSavedSong(),
|
||||||
builder: (BuildContext context, AsyncSnapshot<List<Music>> snapshot) {
|
builder: (BuildContext context, AsyncSnapshot<List<Music>> snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
if (snapshot.data?.length == 0) {
|
if (snapshot.data?.length == 0) {
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: double.infinity,
|
height: double.infinity,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Votre collection est vide.",
|
"Votre collection est vide.",
|
||||||
style: GoogleFonts.plusJakartaSans(
|
style: GoogleFonts.plusJakartaSans(
|
||||||
color: Colors.white, fontWeight: FontWeight.w800, fontSize: 18),
|
color: Colors.white, fontWeight: FontWeight.w800, fontSize: 18),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Image.asset(
|
Image.asset(
|
||||||
"assets/images/empty_collection.png",
|
"assets/images/empty_collection.png",
|
||||||
width: 300,
|
width: 300,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
|
physics: const BouncingScrollPhysics(decelerationRate: ScrollDecelerationRate.fast),
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemCount: snapshot.data?.length,
|
itemCount: snapshot.data?.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (playingIndex == index) {
|
if (playingIndex == index) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.callback((snapshot.data?[index])!);
|
widget.callback((snapshot.data?[index])!);
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) => CupertinoAlertDialog(
|
builder: (BuildContext context) => CupertinoAlertDialog(
|
||||||
title: const Text('Supprimer la musique'),
|
title: const Text('Supprimer la musique'),
|
||||||
content: Text(
|
content: Text(
|
||||||
'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'),
|
'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'),
|
||||||
actions: <CupertinoDialogAction>[
|
actions: <CupertinoDialogAction>[
|
||||||
CupertinoDialogAction(
|
CupertinoDialogAction(
|
||||||
/// This parameter indicates this action is the default,
|
/// This parameter indicates this action is the default,
|
||||||
/// and turns the action's text to bold text.
|
/// and turns the action's text to bold text.
|
||||||
isDefaultAction: true,
|
isDefaultAction: true,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: const Text('Annuler'),
|
child: const Text('Annuler'),
|
||||||
),
|
),
|
||||||
CupertinoDialogAction(
|
CupertinoDialogAction(
|
||||||
/// This parameter indicates the action would perform
|
/// This parameter indicates the action would perform
|
||||||
/// a destructive action such as deletion, and turns
|
/// a destructive action such as deletion, and turns
|
||||||
/// the action's text color to red.
|
/// the action's text color to red.
|
||||||
isDestructiveAction: true,
|
isDestructiveAction: true,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
await MyApp.musicViewModel
|
await MyApp.musicViewModel
|
||||||
.addOrDeleteFavoriteMusic((snapshot.data?[index])!.id);
|
.addOrDeleteFavoriteMusic((snapshot.data?[index])!.id);
|
||||||
MyApp.userViewModel.userCurrent.musics_likes
|
MyApp.userViewModel.userCurrent.musics_likes
|
||||||
.remove((snapshot.data?[index])!.id);
|
.remove((snapshot.data?[index])!.id);
|
||||||
|
|
||||||
MyApp.audioPlayer.release();
|
MyApp.audioPlayer.release();
|
||||||
setState(() {
|
setState(() {
|
||||||
playingIndex = null;
|
playingIndex = null;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: const Text('Supprimer'),
|
child: const Text('Supprimer'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
child: MusicListComponent(
|
child: MusicListComponent(
|
||||||
music: (snapshot.data?[index])!,
|
music: (snapshot.data?[index])!,
|
||||||
playing: true,
|
playing: true,
|
||||||
callback: playMusic,
|
callback: playMusic,
|
||||||
index: index,
|
index: index,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.callback((snapshot.data?[index])!);
|
widget.callback((snapshot.data?[index])!);
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) => CupertinoAlertDialog(
|
builder: (BuildContext context) => CupertinoAlertDialog(
|
||||||
title: const Text('Supprimer la musique'),
|
title: const Text('Supprimer la musique'),
|
||||||
content: Text(
|
content: Text(
|
||||||
'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'),
|
'Etes-vous sur de vouloir supprimer ${(snapshot.data?[index])!.title} de votre collection?'),
|
||||||
actions: <CupertinoDialogAction>[
|
actions: <CupertinoDialogAction>[
|
||||||
CupertinoDialogAction(
|
CupertinoDialogAction(
|
||||||
/// This parameter indicates this action is the default,
|
/// This parameter indicates this action is the default,
|
||||||
/// and turns the action's text to bold text.
|
/// and turns the action's text to bold text.
|
||||||
isDefaultAction: true,
|
isDefaultAction: true,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: const Text('Annuler'),
|
child: const Text('Annuler'),
|
||||||
),
|
),
|
||||||
CupertinoDialogAction(
|
CupertinoDialogAction(
|
||||||
/// This parameter indicates the action would perform
|
/// This parameter indicates the action would perform
|
||||||
/// a destructive action such as deletion, and turns
|
/// a destructive action such as deletion, and turns
|
||||||
/// the action's text color to red.
|
/// the action's text color to red.
|
||||||
isDestructiveAction: true,
|
isDestructiveAction: true,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
await MyApp.musicViewModel
|
await MyApp.musicViewModel
|
||||||
.addOrDeleteFavoriteMusic((snapshot.data?[index])!.id);
|
.addOrDeleteFavoriteMusic((snapshot.data?[index])!.id);
|
||||||
MyApp.userViewModel.userCurrent.musics_likes
|
MyApp.userViewModel.userCurrent.musics_likes
|
||||||
.remove((snapshot.data?[index])!.id);
|
.remove((snapshot.data?[index])!.id);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: const Text('Supprimer'),
|
child: const Text('Supprimer'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
child: MusicListComponent(
|
child: MusicListComponent(
|
||||||
music: (snapshot.data?[index])!,
|
music: (snapshot.data?[index])!,
|
||||||
playing: false,
|
playing: false,
|
||||||
callback: playMusic,
|
callback: playMusic,
|
||||||
index: index,
|
index: index,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return CupertinoActivityIndicator();
|
return CupertinoActivityIndicator();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in new issue