diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index bb10470..9a7932e 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -1,3 +1,4 @@ +<<<<<<< HEAD @@ -529,4 +530,545 @@ +======= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>>>>>>> master \ No newline at end of file diff --git a/Sources/justMUSIC/.gitignore b/Sources/justMUSIC/.gitignore index 24476c5..7995c36 100644 --- a/Sources/justMUSIC/.gitignore +++ b/Sources/justMUSIC/.gitignore @@ -30,6 +30,7 @@ migrate_working_dir/ .packages .pub-cache/ .pub/ +.lib/values/keys.dart /build/ # Symbolication related diff --git a/Sources/justMUSIC/android/app/src/debug/AndroidManifest.xml b/Sources/justMUSIC/android/app/src/debug/AndroidManifest.xml index 8ffe024..04c234b 100644 --- a/Sources/justMUSIC/android/app/src/debug/AndroidManifest.xml +++ b/Sources/justMUSIC/android/app/src/debug/AndroidManifest.xml @@ -1,7 +1,9 @@ - - - - + + + + + diff --git a/Sources/justMUSIC/android/build.gradle b/Sources/justMUSIC/android/build.gradle index 791e37b..c0f45cf 100644 --- a/Sources/justMUSIC/android/build.gradle +++ b/Sources/justMUSIC/android/build.gradle @@ -1,19 +1,15 @@ buildscript { - ext.kotlin_version = '1.7.10' + ext.kotlin_version = '1.9.0' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' + classpath 'com.android.tools.build:gradle:7.1.2' classpath 'com.google.gms:google-services:4.3.15' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } - - - - } allprojects { @@ -34,4 +30,3 @@ subprojects { tasks.register("clean", Delete) { delete rootProject.buildDir } - diff --git a/Sources/justMUSIC/assets/images/rocket_button.png b/Sources/justMUSIC/assets/images/rocket_button.png new file mode 100644 index 0000000..2b27406 Binary files /dev/null and b/Sources/justMUSIC/assets/images/rocket_button.png differ diff --git a/Sources/justMUSIC/lib/components/buttonPostComponent.dart b/Sources/justMUSIC/lib/components/buttonPostComponent.dart new file mode 100644 index 0000000..28c4587 --- /dev/null +++ b/Sources/justMUSIC/lib/components/buttonPostComponent.dart @@ -0,0 +1,146 @@ +import 'package:flutter/Material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:ionicons/ionicons.dart'; +import 'package:tuple/tuple.dart'; + +import '../values/constants.dart'; + +class PhotoPostComponent extends StatelessWidget { + final bool empty; + const PhotoPostComponent({Key? key, required this.empty}) : super(key: key); + + @override + Widget build(BuildContext context) { + return empty + ? Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: postbutton, borderRadius: BorderRadius.circular(8)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Icon( + Ionicons.camera, + size: 15, + color: Colors.white, + ), + SizedBox( + width: 10, + ), + Expanded( + child: Text( + 'Prendre un selfie', + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontSize: 12), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ) + ]), + )) + : Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: fillButton, borderRadius: BorderRadius.circular(8)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Text( + "Selfie enregistré", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontSize: 12), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ), + SizedBox( + width: 10, + ), + Icon( + Icons.close, + size: 12, + color: Colors.white, + ), + ]), + )); + } +} + +class LocationPostComponent extends StatelessWidget { + final bool empty; + final Tuple2? location; + const LocationPostComponent( + {Key? key, required this.empty, required this.location}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return empty + ? Container( + width: double.infinity, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: postbutton, borderRadius: BorderRadius.circular(8)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Icon( + Icons.location_on, + size: 15, + color: Colors.white, + ), + SizedBox( + width: 10, + ), + Expanded( + child: Text( + 'Ajouter un lieu', + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontSize: 12), + overflow: TextOverflow.ellipsis, + ), + ) + ])), + ) + : Container( + width: double.infinity, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: fillButton, borderRadius: BorderRadius.circular(8)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Text( + '${location?.item1}, ${location?.item2}', + style: GoogleFonts.plusJakartaSans( + color: Colors.white, fontSize: 12), + overflow: TextOverflow.ellipsis, + ), + ), + SizedBox( + width: 10, + ), + Icon( + Icons.close, + size: 12, + color: Colors.white, + ), + ]), + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/components/city_list_component.dart b/Sources/justMUSIC/lib/components/city_list_component.dart new file mode 100644 index 0000000..59a2100 --- /dev/null +++ b/Sources/justMUSIC/lib/components/city_list_component.dart @@ -0,0 +1,45 @@ +import 'package:flutter/Material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/values/constants.dart'; +import 'package:tuple/tuple.dart'; + +class CityListComponent extends StatelessWidget { + final Tuple2 location; + const CityListComponent({Key? key, required this.location}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + child: RichText( + overflow: TextOverflow.ellipsis, + maxLines: 1, + text: TextSpan(children: [ + TextSpan( + text: location.item2 + ", ", + style: GoogleFonts.plusJakartaSans( + color: grayText, + fontWeight: FontWeight.w400, + fontSize: 17), + ), + TextSpan( + text: location.item1, + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 17), + ), + ])), + ), + ], + ), + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/components/editable_post_component.dart b/Sources/justMUSIC/lib/components/editable_post_component.dart index 7cf202f..7bc2714 100644 --- a/Sources/justMUSIC/lib/components/editable_post_component.dart +++ b/Sources/justMUSIC/lib/components/editable_post_component.dart @@ -1,113 +1,377 @@ -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:justmusic/values/constants.dart'; - -class EditablePostComponent extends StatefulWidget { - const EditablePostComponent({Key? key}) : super(key: key); - - @override - State createState() => _EditablePostComponentState(); -} - -class _EditablePostComponentState extends State { - @override - Widget build(BuildContext context) { - return ClipRRect( - borderRadius: BorderRadius.circular(25), - child: Container( - constraints: BoxConstraints(maxWidth: 400), - width: double.infinity, - color: warningBttnColor, - child: Column( - children: [ - AspectRatio( - aspectRatio: 1 / 1, - child: Container( - decoration: BoxDecoration( - // add border - border: Border.all(width: 3.0, color: grayColor), - // set border radius - borderRadius: BorderRadius.circular(20), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(18), - // implement image - child: const Image( - image: AssetImage("assets/images/exemple_cover.png"), - fit: BoxFit.cover, - width: double.infinity, - ), - ), - ), - ), - Padding( - padding: EdgeInsets.fromLTRB(15, 25, 15, 25), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - AutoSizeText( - "France, Lyon", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, fontSize: 13.sp), - maxFontSize: 20, - ), - Image( - image: AssetImage("assets/images/camera_icon.png"), - width: 30, - ), - AutoSizeText( - "10 Juil. 2023", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, fontSize: 13.sp), - maxFontSize: 20, - ), - ], - ), - ), - Padding( - padding: EdgeInsets.fromLTRB(15, 0, 10, 25), - child: SizedBox( - width: double.infinity, - child: TextFormField( - keyboardAppearance: Brightness.dark, - minLines: 1, - cursorColor: primaryColor, - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontSize: 13, - fontWeight: FontWeight.w300), - maxLines: 4, - maxLength: 120, - decoration: InputDecoration( - counterStyle: GoogleFonts.plusJakartaSans( - color: grayText, fontSize: 9), - focusedBorder: const OutlineInputBorder( - borderSide: - BorderSide(width: 0, color: Colors.transparent), - borderRadius: - BorderRadius.all(Radius.circular(10))), - contentPadding: - const EdgeInsets.only(top: 0, bottom: 0, left: 0), - fillColor: Colors.transparent, - filled: true, - focusColor: Colors.transparent, - enabledBorder: const OutlineInputBorder( - borderSide: - BorderSide(width: 0, color: Colors.transparent), - borderRadius: - BorderRadius.all(Radius.circular(10))), - hintText: 'Description...', - hintStyle: GoogleFonts.plusJakartaSans( - color: grayText, - fontSize: 13, - fontWeight: FontWeight.w300), - ), - ), - )), - ], - ), - )); - } -} +import 'dart:io'; + +import 'package:animated_appear/animated_appear.dart'; +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:circular_reveal_animation/circular_reveal_animation.dart'; +import 'package:flutter/Material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:insta_image_viewer/insta_image_viewer.dart'; +import 'package:justmusic/values/constants.dart'; +import 'package:text_scroll/text_scroll.dart'; +import 'package:tuple/tuple.dart'; + +import '../model/Music.dart'; +import '../screens/search_location_screen.dart'; +import 'buttonPostComponent.dart'; + +class EditablePostComponent extends StatefulWidget { + final Music? music; + const EditablePostComponent({Key? key, this.music}) : super(key: key); + + @override + State createState() => _EditablePostComponentState(); +} + +class _EditablePostComponentState extends State + with TickerProviderStateMixin { + final ImagePicker picker = ImagePicker(); + late Animation animation; + late AnimationController animationController; + late AnimationController _controller; + File? image; + Tuple2? selectedCity; + + @override + void initState() { + _controller = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 400), + ); + animationController = AnimationController( + vsync: this, + duration: Duration(milliseconds: 400), + ); + animation = CurvedAnimation( + parent: animationController, + curve: Curves.easeInOutSine, + ); + animationController.forward(); + super.initState(); + } + + Future pickImage(ImageSource source) async { + try { + final image = await ImagePicker().pickImage(source: source); + if (image == null) return; + final imageTemp = File(image.path); + setState(() { + this.image = imageTemp; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + void _selectLocation(Tuple2 location) { + Navigator.pop(context); + setState(() { + selectedCity = location; + }); + } + + void searchLocation() { + showModalBottomSheet( + transitionAnimationController: _controller, + barrierColor: Colors.black.withOpacity(0.7), + backgroundColor: Colors.transparent, + 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: ((context) { + return ClipRRect( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), topRight: Radius.circular(20)), + child: SearchCityScreen(callback: _selectLocation)); + }), + ); + } + + @override + Widget build(BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.circular(25), + child: Container( + constraints: BoxConstraints(maxWidth: 400, minHeight: 500), + width: double.infinity, + color: warningBttnColor, + child: Column( + children: [ + CircularRevealAnimation( + animation: animation, + centerOffset: Offset(30.w, -100), + child: Stack( + children: [ + AspectRatio( + aspectRatio: 1 / 1, + child: Container( + decoration: BoxDecoration( + // add border + border: Border.all(width: 3.0, color: grayColor), + // set border radius + borderRadius: BorderRadius.circular(20), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(18), + // implement image + child: widget.music == null + ? Container( + color: grayColor, + width: double.infinity, + ) + : Image( + image: + NetworkImage(widget.music?.cover ?? ""), + fit: BoxFit.cover, + width: double.infinity, + ), + ), + ), + ), + image != null + ? Positioned( + top: 10, + right: 10, + child: AnimatedAppear( + delay: Duration(milliseconds: 500), + duration: Duration(milliseconds: 400), + child: Container( + width: 110, + height: 110, + decoration: BoxDecoration( + image: DecorationImage( + image: FileImage(image!), + fit: BoxFit.cover, + ), + color: grayColor, + borderRadius: BorderRadius.circular(20), + border: Border.all( + style: BorderStyle.solid, + color: Colors.white, + width: 4)), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: InstaImageViewer( + backgroundIsTransparent: true, + child: Image( + image: FileImage(image!), + fit: BoxFit.cover, + ), + ), + ), + ), + )) + : Container() + ], + )), + widget.music != null + ? Padding( + padding: const EdgeInsets.all(10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + flex: 8, + child: TextScroll( + (widget.music?.title)!, + 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, + ), + ), + ), + Flexible( + flex: 6, + child: Padding( + padding: EdgeInsets.only(bottom: 2), + child: TextScroll( + (widget.music?.artists[0].name)!, + 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( + "2013", + style: GoogleFonts.plusJakartaSans( + color: Colors.white.withOpacity(0.5), + fontWeight: FontWeight.w300, + fontSize: 16.h), + textAlign: TextAlign.end, + maxFontSize: 20, + ), + ], + ), + ) + : Container(), + Container( + padding: EdgeInsets.fromLTRB(15, 15, 15, 25), + width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 5, + child: GestureDetector( + onTap: () { + manageImage(); + }, + child: PhotoPostComponent( + empty: image == null, + ), + ), + ), + SizedBox( + width: 15, + ), + Expanded( + flex: 5, + child: GestureDetector( + onTap: () { + manageLocation(); + }, + child: LocationPostComponent( + empty: selectedCity == null, + location: selectedCity, + ), + ), + ), + ], + ), + ), + Padding( + padding: EdgeInsets.fromLTRB(15, 0, 10, 25), + child: SizedBox( + width: double.infinity, + child: TextFormField( + keyboardAppearance: Brightness.dark, + minLines: 1, + cursorColor: primaryColor, + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.w300), + maxLines: 4, + maxLength: 120, + decoration: InputDecoration( + counterStyle: GoogleFonts.plusJakartaSans( + color: grayText, fontSize: 9), + focusedBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent), + borderRadius: + BorderRadius.all(Radius.circular(10))), + contentPadding: + const EdgeInsets.only(top: 0, bottom: 0, left: 0), + fillColor: Colors.transparent, + filled: true, + focusColor: Colors.transparent, + enabledBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 0, color: Colors.transparent), + borderRadius: + BorderRadius.all(Radius.circular(10))), + hintText: 'Description...', + hintStyle: GoogleFonts.plusJakartaSans( + color: grayText, + fontSize: 13, + fontWeight: FontWeight.w300), + ), + ), + )), + ], + ), + )); + } + + void manageImage() { + if (image != null) { + setState(() { + image = null; + }); + } else { + _showActionSheet(context); + } + } + + void manageLocation() { + if (selectedCity != null) { + setState(() { + selectedCity = null; + }); + } else { + searchLocation(); + } + } + + void _showActionSheet(BuildContext context) { + showCupertinoModalPopup( + context: context, + barrierColor: Colors.black.withOpacity(0.5), + builder: (BuildContext context) => Container( + color: Colors.black, + child: CupertinoActionSheet( + title: Text( + 'Ajouter une photo', + style: GoogleFonts.plusJakartaSans(fontWeight: FontWeight.bold), + ), + actions: [ + CupertinoActionSheetAction( + onPressed: () { + pickImage(ImageSource.gallery); + Navigator.pop(context); + }, + child: const Text('Galerie'), + ), + CupertinoActionSheetAction( + onPressed: () { + pickImage(ImageSource.camera); + Navigator.pop(context); + }, + child: const Text('Prendre un selfie'), + ), + ], + cancelButton: CupertinoActionSheetAction( + isDestructiveAction: true, + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Annuler'), + ), + ), + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/components/music_list_component.dart b/Sources/justMUSIC/lib/components/music_list_component.dart index 4d8976d..93c5c42 100644 --- a/Sources/justMUSIC/lib/components/music_list_component.dart +++ b/Sources/justMUSIC/lib/components/music_list_component.dart @@ -1,100 +1,113 @@ -import 'package:flutter/Material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/components/play_button_component.dart'; -import 'package:text_scroll/text_scroll.dart'; -import '../model/Music.dart'; - -class MusicListComponent extends StatelessWidget { - final Music music; - const MusicListComponent({ - Key? key, - required this.music, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.only(bottom: 14), - child: Row( - children: [ - LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - if (music.cover != null) { - return ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5)), - child: music.cover != null - ? FadeInImage.assetNetwork( - height: 60, - width: 60, - fit: BoxFit.cover, - placeholder: "assets/images/loadingPlaceholder.gif", - image: music.cover!) - : Container( - height: 60, - width: 60, - color: Colors.grey, - ), - ); - } else { - return Image( - image: AssetImage("assets/images/exemple_cover.png"), - height: 60, - width: 60, - ); - } - }), - const SizedBox( - width: 10, - ), - Expanded( - flex: 10, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - children: [ - Flexible( - flex: 8, - child: ScrollConfiguration( - behavior: - ScrollBehavior().copyWith(scrollbars: false), - child: TextScroll( - music.title ?? "Unknown", - style: GoogleFonts.plusJakartaSans( - fontSize: 16, - color: Colors.white, - fontWeight: FontWeight.w700), - mode: TextScrollMode.endless, - pauseBetween: Duration(milliseconds: 2500), - velocity: Velocity(pixelsPerSecond: Offset(30, 0)), - intervalSpaces: 10, - ), - )), - Icon( - Icons.explicit, - color: Colors.grey.withOpacity(0.7), - size: 17, - ), - ], - ), - ScrollConfiguration( - behavior: ScrollBehavior().copyWith(scrollbars: false), - child: Text( - music.artists.first.name ?? "Unknown", - overflow: TextOverflow.ellipsis, - style: GoogleFonts.plusJakartaSans( - color: Colors.grey, fontWeight: FontWeight.w400), - )) - ], - ), - ), - Spacer(), - PlayButtonComponent( - urlPreview: music.previewUrl, - ) - ], - ), - ); - } -} +import 'package:flutter/Material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/components/play_button_component.dart'; +import 'package:text_scroll/text_scroll.dart'; +import '../model/Music.dart'; + +class MusicListComponent extends StatelessWidget { + final Music music; + final bool playing; + final int index; + final Function(int) callback; + MusicListComponent({ + Key? key, + required this.music, + required this.playing, + required this.callback, + required this.index, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.only(bottom: 14), + child: Row( + children: [ + LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + if (music.cover != null) { + return ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5)), + child: music.cover != null + ? FadeInImage.assetNetwork( + height: 60, + width: 60, + fit: BoxFit.cover, + placeholder: "assets/images/loadingPlaceholder.gif", + image: music.cover!) + : Container( + height: 60, + width: 60, + color: Colors.grey, + ), + ); + } else { + return Image( + image: AssetImage("assets/images/exemple_cover.png"), + height: 60, + width: 60, + ); + } + }), + const SizedBox( + width: 10, + ), + Expanded( + flex: 10, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Flexible( + flex: 8, + child: ScrollConfiguration( + behavior: + ScrollBehavior().copyWith(scrollbars: false), + child: TextScroll( + music.title ?? "Unknown", + style: GoogleFonts.plusJakartaSans( + fontSize: 16, + color: Colors.white, + fontWeight: FontWeight.w700), + mode: TextScrollMode.endless, + pauseBetween: Duration(milliseconds: 2500), + velocity: Velocity(pixelsPerSecond: Offset(30, 0)), + intervalSpaces: 10, + ), + )), + music.explicit + ? Icon( + Icons.explicit, + color: Colors.grey.withOpacity(0.7), + size: 17, + ) + : Container(), + ], + ), + ScrollConfiguration( + behavior: ScrollBehavior().copyWith(scrollbars: false), + child: Text( + music.artists.first.name ?? "Unknown", + overflow: TextOverflow.ellipsis, + style: GoogleFonts.plusJakartaSans( + color: Colors.grey, fontWeight: FontWeight.w400), + )) + ], + ), + ), + Spacer(), + music.previewUrl != null + ? PlayButtonComponent( + music: music, + callback: callback, + playing: playing, + index: index, + ) + : Container() + ], + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/components/play_button_component.dart b/Sources/justMUSIC/lib/components/play_button_component.dart index 52f764e..237881d 100644 --- a/Sources/justMUSIC/lib/components/play_button_component.dart +++ b/Sources/justMUSIC/lib/components/play_button_component.dart @@ -1,72 +1,72 @@ -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'; - -class PlayButtonComponent extends StatefulWidget { - final String? urlPreview; - const PlayButtonComponent({Key? key, required this.urlPreview}) - : super(key: key); - - @override - State createState() => _PlayButtonComponentState(); -} - -class _PlayButtonComponentState extends State { - bool isPlaying = true; - final player = AudioPlayer(); - void switchStatePlaying() { - setState(() { - isPlaying = !isPlaying; - }); - stopSong(); - } - - @override - void initState() { - player.onPlayerComplete.listen((event) { - switchStatePlaying(); - }); - super.initState(); - } - - @override - Widget build(BuildContext context) { - if (!isPlaying) { - playSong(); - } else {} - return isPlaying - ? GestureDetector( - onTap: switchStatePlaying, - child: Container( - width: 30, - height: 30, - child: Icon( - Ionicons.play_circle_outline, - color: Colors.grey.withOpacity(0.3), - size: 30, - )), - ) - : GestureDetector( - onTap: switchStatePlaying, - child: Container( - width: 30, - height: 30, - child: AnimatedPlayButton( - stopped: false, - color: Colors.grey.withOpacity(0.3), - onPressed: () {}, - ), - )); - } - - Future playSong() async { - if (widget.urlPreview != null) { - await player.play(UrlSource(widget.urlPreview ?? "")); - } - } - - Future stopSong() async { - await player.stop(); - } -} +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'; + +import '../main.dart'; +import '../model/Music.dart'; + +class PlayButtonComponent extends StatefulWidget { + final Music music; + final Function callback; + final int index; + final bool playing; + const PlayButtonComponent( + {Key? key, + required this.music, + required this.callback, + required this.playing, + required this.index}) + : super(key: key); + + @override + State createState() => _PlayButtonComponentState(); +} + +class _PlayButtonComponentState extends State { + final player = AudioPlayer(); + + @override + void initState() { + MyApp.audioPlayer.onPlayerComplete.listen((event) { + widget.callback(widget.index); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return !widget.playing + ? GestureDetector( + onTap: () { + widget.music.playSong(); + widget.callback(widget.index); + }, + child: Container( + width: 30, + height: 30, + child: Icon( + Ionicons.play_circle_outline, + color: Colors.grey.withOpacity(0.3), + size: 30, + )), + ) + : GestureDetector( + onTap: () { + widget.music.stopSong(); + + widget.callback(widget.index); + }, + child: Container( + width: 30, + height: 30, + child: AnimatedPlayButton( + stopped: false, + color: Colors.grey.withOpacity(0.3), + onPressed: () { + print("cc"); + }, + ), + )); + } +} diff --git a/Sources/justMUSIC/lib/components/post_button_component.dart b/Sources/justMUSIC/lib/components/post_button_component.dart index eff93b2..93f75d9 100644 --- a/Sources/justMUSIC/lib/components/post_button_component.dart +++ b/Sources/justMUSIC/lib/components/post_button_component.dart @@ -1,32 +1,149 @@ +import 'dart:ui'; + import 'package:flutter/Material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -class PostButtonComponent extends StatelessWidget { - const PostButtonComponent({Key? key}) : super(key: key); +class PostButtonComponent extends StatefulWidget { + final bool empty; + const PostButtonComponent({Key? key, required this.empty}) : super(key: key); + + @override + State createState() => _PostButtonComponentState(); +} + +class _PostButtonComponentState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + animationBehavior: AnimationBehavior.normal, + vsync: this, + duration: Duration(milliseconds: 1500), + ); + + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + _controller.reverse(); + } else if (status == AnimationStatus.dismissed) { + _controller.forward(); + } + }); + + _controller.forward(); + } @override Widget build(BuildContext context) { + if (widget.empty) { + return Container( + constraints: BoxConstraints(maxWidth: 400), + decoration: BoxDecoration( + gradient: LinearGradient(colors: [ + Color(0xFF141414), + Color(0xFF272727), + Color(0xFF141414) + ]), + borderRadius: BorderRadius.circular(10000)), + padding: EdgeInsets.symmetric(vertical: 25), + width: double.infinity, + child: Align( + child: Text( + "Publier la capsule", + style: GoogleFonts.plusJakartaSans( + color: Color(0xFF474747), + fontWeight: FontWeight.w800, + fontStyle: FontStyle.italic, + fontSize: 24), + ), + ), + ); + } return Container( - constraints: BoxConstraints(maxWidth: 400), - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - Color(0xFF141414), - Color(0xFF272727), - Color(0xFF141414) - ]), - borderRadius: BorderRadius.circular(10000)), - padding: EdgeInsets.symmetric(vertical: 25), width: double.infinity, - child: Align( - child: Text( - "Publier la capsule", - style: GoogleFonts.plusJakartaSans( - color: Color(0xFF474747), - fontWeight: FontWeight.w800, - fontStyle: FontStyle.italic, - fontSize: 24), - ), + height: 90, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + color: Colors.transparent, borderRadius: BorderRadius.circular(1000)), + child: Stack( + children: [ + AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Transform.translate( + offset: Offset( + _controller.value * (MediaQuery.of(context).size.width - 200), + 0, + ), + child: child, + ); + }, + child: Container( + width: 120, + height: 80, + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: LinearGradient(colors: [ + Color(0xFF9E78FF).withOpacity(0.0), + Color(0xFFFDFDFF), + Color(0xFFFFFFFF), + Color(0xFF9E78FF).withOpacity(0.0) + ], stops: const [ + 0, + 0.4, + 0.5, + 1 + ]), + ), + ), + ), + BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 10.0, + sigmaY: 10.0, + ), + child: Opacity( + opacity: 0.9, + child: Container( + constraints: BoxConstraints(maxWidth: 400), + decoration: BoxDecoration( + gradient: LinearGradient(colors: [ + Color(0xFF633AF4), + Color(0xFF9367FF), + Color(0xFF633AF4) + ]), + border: Border.all(width: 5, color: Color(0xFF1C1C1C)), + borderRadius: BorderRadius.circular(10000)), + padding: EdgeInsets.symmetric(vertical: 25), + width: double.infinity, + child: Padding( + padding: EdgeInsets.only(left: 100), + child: Text( + "Publier la capsule", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontWeight: FontWeight.w700, + fontStyle: FontStyle.italic, + fontSize: 22), + ), + ), + ), + )), + ClipOval( + child: Positioned( + left: -15, + child: Padding( + padding: const EdgeInsets.only(left: 5, top: 5), + child: Image( + image: AssetImage("assets/images/rocket_button.png"), + height: 65, + ), + ), + ), + ) + ], ), ); } diff --git a/Sources/justMUSIC/lib/main.dart b/Sources/justMUSIC/lib/main.dart index 191ec0d..fd68156 100644 --- a/Sources/justMUSIC/lib/main.dart +++ b/Sources/justMUSIC/lib/main.dart @@ -1,4 +1,6 @@ +import 'package:audioplayers/audioplayers.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -11,7 +13,7 @@ import 'package:justmusic/screens/registration_screen.dart'; import 'package:justmusic/screens/welcome_screen.dart'; import 'package:justmusic/view_model/MusicViewModel.dart'; import 'package:justmusic/view_model/UserViewModel.dart'; -import 'package:firebase_core/firebase_core.dart'; + import 'firebase_options.dart'; Future main() async { @@ -23,10 +25,10 @@ Future main() async { } class MyApp extends StatelessWidget { - // ugly as fuck static FirebaseFirestore db = FirebaseFirestore.instance; static UserViewModel userViewModel = UserViewModel(); static MusicViewModel musicViewModel = MusicViewModel(); + static AudioPlayer audioPlayer = AudioPlayer(); const MyApp({super.key}); @@ -36,6 +38,7 @@ class MyApp extends StatelessWidget { SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); Paint.enableDithering = true; return ScreenUtilInit( + useInheritedMediaQuery: true, builder: (context, child) { return MaterialApp( routes: { diff --git a/Sources/justMUSIC/lib/model/Music.dart b/Sources/justMUSIC/lib/model/Music.dart index 26103d4..ed9d9f4 100644 --- a/Sources/justMUSIC/lib/model/Music.dart +++ b/Sources/justMUSIC/lib/model/Music.dart @@ -1,61 +1,74 @@ -import 'Artist.dart'; - -class Music { - final String _id; - String? _title; - String? _cover; - String? _previewUrl; - DateTime? _date; - double? _duration; - bool _explicit = false; - List _artists; - - // Constructor - Music(this._id, this._title, this._cover, this._previewUrl, this._date, - this._duration, this._explicit, this._artists); - - //Getters and setters - String? get id => _id; - - String? get title => _title; - - set title(String? value) { - _title = value; - } - - String? get cover => _cover; - - set cover(String? value) { - _cover = value; - } - - String? get previewUrl => _previewUrl; - - set previewUrl(String? value) { - _previewUrl = value; - } - - DateTime? get date => _date; - - set date(DateTime? value) { - _date = value; - } - - double? get duration => _duration; - - set duration(double? value) { - _duration = value; - } - - bool get explicit => _explicit; - - set explicit(bool value) { - _explicit = value; - } - - List get artists => _artists; - - set artists(List value) { - _artists = value; - } -} +import 'package:audioplayers/audioplayers.dart'; + +import 'Artist.dart'; +import '../main.dart'; + +class Music { + final String _id; + String? _title; + String? _cover; + String? _previewUrl; + int? _date; + double? _duration; + bool _explicit = false; + List _artists; + + // Constructor + Music(this._id, this._title, this._cover, this._previewUrl, this._date, + this._duration, this._explicit, this._artists); + + //Getters and setters + String? get id => _id; + + String? get title => _title; + + set title(String? value) { + _title = value; + } + + String? get cover => _cover; + + set cover(String? value) { + _cover = value; + } + + String? get previewUrl => _previewUrl; + + set previewUrl(String? value) { + _previewUrl = value; + } + + int? get date => _date; + + set date(int? value) { + _date = value; + } + + double? get duration => _duration; + + set duration(double? value) { + _duration = value; + } + + bool get explicit => _explicit; + + set explicit(bool value) { + _explicit = value; + } + + List get artists => _artists; + + set artists(List value) { + _artists = value; + } + + Future playSong() async { + if (previewUrl != null) { + await MyApp.audioPlayer.play(UrlSource(previewUrl!)); + } + } + + Future stopSong() async { + await MyApp.audioPlayer.stop(); + } +} diff --git a/Sources/justMUSIC/lib/screens/feed_screen.dart b/Sources/justMUSIC/lib/screens/feed_screen.dart index 95b696a..97c42e2 100644 --- a/Sources/justMUSIC/lib/screens/feed_screen.dart +++ b/Sources/justMUSIC/lib/screens/feed_screen.dart @@ -1,297 +1,301 @@ -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 '../components/comment_component.dart'; -import '../components/post_component.dart'; -import '../components/top_nav_bar_component.dart'; -import '../values/constants.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; - late List discoveryFeed; - late List displayFeed; - - @override - void initState() { - super.initState(); - friendFeed = [ - PostComponent( - callback: openDetailPost, - ), - PostComponent( - callback: openDetailPost, - ), - PostComponent( - callback: openDetailPost, - ), - ]; - discoveryFeed = [ - PostComponent(callback: openDetailPost), - ]; - displayFeed = friendFeed; - animationController = AnimationController( - vsync: this, - duration: Duration(milliseconds: 400), - ); - animation = CurvedAnimation( - parent: animationController, - curve: Curves.easeInOutSine, - ); - animationController.forward(); - } - - Future resetFullScreen() async { - await SystemChannels.platform.invokeMethod( - 'SystemChrome.restoreSystemUIOverlays', - ); - } - - 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 = friendFeed; - animationController.forward(); - }); - } else { - setState(() { - animationController.reset(); - displayFeed = discoveryFeed; - animationController.forward(); - }); - } - } - - void openDetailPost() { - 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: ((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( - child: Wrap( - // to apply margin in the main axis of the wrap - runSpacing: 10, - children: [ - PostComponent( - callback: null, - ), - Container(height: 10), - 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)), - ), - ) - ], - ), - ), - )), - ), - ], - ), - ), - ); - }), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomInset: true, - backgroundColor: bgColor, - body: Stack( - children: [ - CircularRevealAnimation( - animation: animation, - centerOffset: Offset(30.w, -100), - child: SingleChildScrollView( - child: SizedBox( - width: double.infinity, - child: Align( - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 600), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: defaultPadding), - child: Container( - width: double.infinity, - child: Padding( - padding: EdgeInsets.only(top: 100.h), - child: SingleChildScrollView( - child: Wrap( - runSpacing: 60, - children: displayFeed, - ), - )), - ), - ), - ), - )), - ), - ), - 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 '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 '../components/comment_component.dart'; +import '../components/post_component.dart'; +import '../components/top_nav_bar_component.dart'; +import '../values/constants.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; + late List discoveryFeed; + late List displayFeed; + + @override + void initState() { + super.initState(); + friendFeed = [ + PostComponent( + callback: openDetailPost, + ), + PostComponent( + callback: openDetailPost, + ), + PostComponent( + callback: openDetailPost, + ), + ]; + discoveryFeed = [ + PostComponent(callback: openDetailPost), + ]; + displayFeed = friendFeed; + animationController = AnimationController( + vsync: this, + duration: Duration(milliseconds: 400), + ); + animation = CurvedAnimation( + parent: animationController, + curve: Curves.easeInOutSine, + ); + animationController.forward(); + } + + Future resetFullScreen() async { + await SystemChannels.platform.invokeMethod( + 'SystemChrome.restoreSystemUIOverlays', + ); + } + + 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 = friendFeed; + animationController.forward(); + }); + } else { + setState(() { + animationController.reset(); + displayFeed = discoveryFeed; + animationController.forward(); + }); + } + } + + void openDetailPost() { + 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 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, + ), + Container(height: 10), + 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)), + ), + ) + ], + ), + ), + )), + ), + ], + ), + ), + ); + }), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: true, + backgroundColor: bgColor, + body: Stack( + children: [ + CircularRevealAnimation( + animation: animation, + centerOffset: Offset(30.w, -100), + child: SingleChildScrollView( + physics: const BouncingScrollPhysics( + decelerationRate: ScrollDecelerationRate.fast), + child: SizedBox( + width: double.infinity, + child: Align( + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 600), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: defaultPadding), + child: Container( + width: double.infinity, + child: Padding( + padding: EdgeInsets.only(top: 100.h), + child: SingleChildScrollView( + child: Wrap( + runSpacing: 60, + children: displayFeed, + ), + )), + ), + ), + ), + )), + ), + ), + 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), + ), + ), + ], + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/screens/post_screen.dart b/Sources/justMUSIC/lib/screens/post_screen.dart index 574eac8..65cc130 100644 --- a/Sources/justMUSIC/lib/screens/post_screen.dart +++ b/Sources/justMUSIC/lib/screens/post_screen.dart @@ -1,126 +1,125 @@ -import 'dart:ui'; -import 'package:flutter/Material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:justmusic/components/back_button.dart'; -import 'package:justmusic/screens/search_song_screen.dart'; -import '../components/editable_post_component.dart'; -import '../components/post_button_component.dart'; -import '../values/constants.dart'; - -class PostScreen extends StatefulWidget { - const PostScreen({Key? key}) : super(key: key); - - @override - State createState() => _PostScreenState(); -} - -class _PostScreenState extends State - with SingleTickerProviderStateMixin { - final scrollController = ScrollController(); - late AnimationController _controller; - late Animation _animation; - - @override - void initState() { - _controller = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 400), - ); - - _animation = Tween(begin: 0.0, end: 400.0).animate( - CurvedAnimation( - parent: _controller, - curve: Curves.easeOut, - ), - ); - super.initState(); - } - - void openDetailPost() { - showModalBottomSheet( - transitionAnimationController: _controller, - barrierColor: Colors.black.withOpacity(0.7), - backgroundColor: Colors.transparent, - 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: ((context) { - return const ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), topRight: Radius.circular(20)), - child: SearchSongScreen()); - }), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomInset: true, - backgroundColor: bgColor, - extendBodyBehindAppBar: true, - appBar: PreferredSize( - preferredSize: Size(double.infinity, 80), - child: SafeArea( - child: Padding( - padding: const EdgeInsets.only( - left: defaultPadding, - right: defaultPadding, - top: defaultPadding), - child: Row( - children: [BackButtonComponent()], - ), - ), - ), - ), - body: Container( - padding: - const EdgeInsets.only(left: defaultPadding, right: defaultPadding), - width: double.infinity, - height: double.infinity, - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/images/background_justMusic.png"), - fit: BoxFit.cover, - ), - ), - child: Stack( - alignment: Alignment.topCenter, - children: [ - ScrollConfiguration( - behavior: ScrollBehavior().copyWith(scrollbars: false), - child: SingleChildScrollView( - controller: scrollController, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SizedBox( - height: 100.h, - ), - GestureDetector( - onTap: openDetailPost, - child: EditablePostComponent(), - ), - SizedBox( - height: 40.h, - ), - PostButtonComponent(), - SizedBox( - height: 40.h, - ), - ], - ), - ), - ), - ], - ), - ), - ); - } -} +import 'dart:ui'; +import 'package:flutter/Material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:justmusic/components/back_button.dart'; +import 'package:justmusic/screens/search_song_screen.dart'; +import 'package:tuple/tuple.dart'; +import '../components/editable_post_component.dart'; +import '../components/post_button_component.dart'; +import '../model/Music.dart'; +import '../values/constants.dart'; + +class PostScreen extends StatefulWidget { + const PostScreen({Key? key}) : super(key: key); + + @override + State createState() => _PostScreenState(); +} + +class _PostScreenState extends State + with SingleTickerProviderStateMixin { + final scrollController = ScrollController(); + late AnimationController _controller; + + Music? selectedMusic; + Tuple2? selectedCity; + + @override + void initState() { + _controller = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 400), + ); + + super.initState(); + } + + void _selectMusic(Music music) { + Navigator.pop(context); + setState(() { + selectedMusic = music; + }); + } + + void openSearchSong() { + showModalBottomSheet( + transitionAnimationController: _controller, + barrierColor: Colors.black.withOpacity(0.7), + backgroundColor: Colors.transparent, + 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: ((context) { + return ClipRRect( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), topRight: Radius.circular(20)), + child: SearchSongScreen(callback: _selectMusic)); + }), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: true, + backgroundColor: bgColor, + extendBodyBehindAppBar: true, + appBar: const PreferredSize( + preferredSize: Size(double.infinity, 80), + child: SafeArea( + child: Padding( + padding: EdgeInsets.only( + left: defaultPadding, + right: defaultPadding, + top: defaultPadding), + child: Row( + children: [BackButtonComponent()], + ), + ), + ), + ), + body: Container( + padding: + const EdgeInsets.only(left: defaultPadding, right: defaultPadding), + width: double.infinity, + height: double.infinity, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/background_justMusic.png"), + fit: BoxFit.cover, + ), + ), + child: ScrollConfiguration( + behavior: ScrollBehavior().copyWith(scrollbars: false), + child: SingleChildScrollView( + controller: scrollController, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + SizedBox( + height: 100.h, + ), + GestureDetector( + onTap: openSearchSong, + child: EditablePostComponent(music: selectedMusic)), + SizedBox( + height: 40.h, + ), + PostButtonComponent(empty: selectedMusic == null), + SizedBox( + height: 40.h, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/screens/profile_screen.dart b/Sources/justMUSIC/lib/screens/profile_screen.dart index a362d35..eead70d 100644 --- a/Sources/justMUSIC/lib/screens/profile_screen.dart +++ b/Sources/justMUSIC/lib/screens/profile_screen.dart @@ -1,146 +1,148 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/values/icons.dart'; -import '../components/profile_component.dart'; -import '../components/setting_part_component.dart'; -import '../main.dart'; -import '../values/constants.dart'; - -class ProfileScreen extends StatefulWidget { - const ProfileScreen({Key? key}) : super(key: key); - - @override - State createState() => _ProfileScreenState(); -} - -class _ProfileScreenState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: PreferredSize( - preferredSize: Size(double.infinity, 58), - child: Container( - height: double.infinity, - color: bgAppBar, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: defaultPadding), - child: Stack( - alignment: Alignment.centerLeft, - children: [ - GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: Container( - height: 15, - width: 15, - child: Image( - image: AssetImage("assets/images/return_icon.png"), - height: 8, - ), - )), - Align( - child: Text( - "Profile", - style: GoogleFonts.plusJakartaSans( - color: Colors.white, - fontSize: 14, - fontWeight: FontWeight.bold), - ), - ) - ], - ), - ), - ), - ), - body: Container( - width: double.infinity, - height: double.infinity, - color: bgColor, - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: settingPadding), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.only(top: 68.h, bottom: 40), - child: - ProfileComponent(user: MyApp.userViewModel.userCurrent), - ), - Padding( - padding: - const EdgeInsets.only(bottom: 12, left: defaultPadding), - child: Text( - "Compte", - style: GoogleFonts.plusJakartaSans( - color: grayText, - fontWeight: FontWeight.w800, - fontSize: 16), - ), - ), - ClipRRect( - borderRadius: BorderRadius.circular(8), - child: Column( - children: const [ - SettingPartComponent( - icon: JustMusicIcon.profile, - label: 'Compte', - ), - SettingPartComponent( - icon: JustMusicIcon.history, - label: 'Historiques des capsules', - ), - SettingPartComponent( - icon: JustMusicIcon.spotify, - label: 'Lier un compte Spotify', - ), - SettingPartComponent( - icon: JustMusicIcon.trash, - label: 'Supprimer mon compte', - ), - SettingPartComponent( - icon: JustMusicIcon.cross, - label: 'Déconnexion', - important: true, - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only( - bottom: 12, left: defaultPadding, top: 40), - child: Text( - "Préférences", - style: GoogleFonts.plusJakartaSans( - color: grayText, - fontWeight: FontWeight.w800, - fontSize: 16), - ), - ), - ClipRRect( - borderRadius: BorderRadius.circular(8), - child: Column( - children: const [ - SettingPartComponent( - icon: JustMusicIcon.theme, - label: 'Thême de l\'application', - ), - SettingPartComponent( - icon: JustMusicIcon.notification, - label: 'Notifications', - ), - ], - ), - ) - ], - ), - ), - ), - ), - ); - } -} +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/values/icons.dart'; +import '../components/profile_component.dart'; +import '../components/setting_part_component.dart'; +import '../main.dart'; +import '../values/constants.dart'; + +class ProfileScreen extends StatefulWidget { + const ProfileScreen({Key? key}) : super(key: key); + + @override + State createState() => _ProfileScreenState(); +} + +class _ProfileScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PreferredSize( + preferredSize: Size(double.infinity, 58), + child: Container( + height: double.infinity, + color: bgAppBar, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: defaultPadding), + child: Stack( + alignment: Alignment.centerLeft, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + height: 15, + width: 15, + child: Image( + image: AssetImage("assets/images/return_icon.png"), + height: 8, + ), + )), + Align( + child: Text( + "Profile", + style: GoogleFonts.plusJakartaSans( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.bold), + ), + ) + ], + ), + ), + ), + ), + body: Container( + width: double.infinity, + height: double.infinity, + color: bgColor, + child: SingleChildScrollView( + physics: const BouncingScrollPhysics( + decelerationRate: ScrollDecelerationRate.fast), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: settingPadding), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 68.h, bottom: 40), + child: + ProfileComponent(user: MyApp.userViewModel.userCurrent), + ), + Padding( + padding: + const EdgeInsets.only(bottom: 12, left: defaultPadding), + child: Text( + "Compte", + style: GoogleFonts.plusJakartaSans( + color: grayText, + fontWeight: FontWeight.w800, + fontSize: 16), + ), + ), + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Column( + children: const [ + SettingPartComponent( + icon: JustMusicIcon.profile, + label: 'Compte', + ), + SettingPartComponent( + icon: JustMusicIcon.history, + label: 'Historiques des capsules', + ), + SettingPartComponent( + icon: JustMusicIcon.spotify, + label: 'Lier un compte Spotify', + ), + SettingPartComponent( + icon: JustMusicIcon.trash, + label: 'Supprimer mon compte', + ), + SettingPartComponent( + icon: JustMusicIcon.cross, + label: 'Déconnexion', + important: true, + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only( + bottom: 12, left: defaultPadding, top: 40), + child: Text( + "Préférences", + style: GoogleFonts.plusJakartaSans( + color: grayText, + fontWeight: FontWeight.w800, + fontSize: 16), + ), + ), + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Column( + children: const [ + SettingPartComponent( + icon: JustMusicIcon.theme, + label: 'Thême de l\'application', + ), + SettingPartComponent( + icon: JustMusicIcon.notification, + label: 'Notifications', + ), + ], + ), + ) + ], + ), + ), + ), + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/screens/search_location_screen.dart b/Sources/justMUSIC/lib/screens/search_location_screen.dart new file mode 100644 index 0000000..82d8261 --- /dev/null +++ b/Sources/justMUSIC/lib/screens/search_location_screen.dart @@ -0,0 +1,89 @@ +import 'dart:ui'; + +import 'package:flutter/Material.dart'; +import 'package:flutter/cupertino.dart'; + +import '../components/city_list_component.dart'; +import '../services/GeoApi.dart'; +import '../values/constants.dart'; + +class SearchCityScreen extends StatefulWidget { + final Function callback; + const SearchCityScreen({Key? key, required this.callback}) : super(key: key); + + @override + State createState() => _SearchCityScreenState(); +} + +class _SearchCityScreenState extends State { + final ScrollController _scrollController = ScrollController(); + final GeoApi api = GeoApi(); + + @override + Widget build(BuildContext context) { + double screenHeight = MediaQuery.of(context).size.height; + return BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 60.0, + sigmaY: 60.0, + ), + child: Container( + color: bgAppBar.withOpacity(0.5), + height: screenHeight - 50, + padding: const EdgeInsets.only(top: 10), + child: Column( + children: [ + Align( + child: Container( + width: 60, + height: 5, + decoration: BoxDecoration( + color: Color(0xFF3A3A3A).withOpacity(0.6), + borderRadius: BorderRadius.circular(20))), + ), + const SizedBox( + height: 10, + ), + Flexible( + child: ScrollConfiguration( + behavior: ScrollBehavior().copyWith(scrollbars: true), + child: FutureBuilder( + future: api.getNearbyCities(), + builder: + (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return ListView.builder( + physics: const BouncingScrollPhysics( + decelerationRate: ScrollDecelerationRate.fast), + controller: _scrollController, + itemCount: snapshot.data.length, + itemBuilder: (context, index) { + return InkWell( + onTap: () { + widget.callback(snapshot.data[index]); + }, + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20), + child: CityListComponent( + location: snapshot.data[index], + ), + )); + }); + } else { + return Center( + child: CupertinoActivityIndicator( + radius: 15, + color: grayColor, + ), + ); + } + }, + ), + )) + ], + ), + ), + ); + } +} diff --git a/Sources/justMUSIC/lib/screens/search_song_screen.dart b/Sources/justMUSIC/lib/screens/search_song_screen.dart index 84b51ba..ae104a6 100644 --- a/Sources/justMUSIC/lib/screens/search_song_screen.dart +++ b/Sources/justMUSIC/lib/screens/search_song_screen.dart @@ -1,169 +1,212 @@ -import 'dart:async'; -import 'dart:ui'; - -import 'package:flutter/Material.dart'; -import 'package:flutter/services.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:justmusic/model/Music.dart'; - -import '../components/music_list_component.dart'; -import '../values/constants.dart'; -import '../main.dart'; - -class SearchSongScreen extends StatefulWidget { - const SearchSongScreen({Key? key}) : super(key: key); - - @override - State createState() => _SearchSongScreenState(); -} - -class _SearchSongScreenState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textEditingController = TextEditingController(); - - Future resetFullScreen() async { - await SystemChannels.platform.invokeMethod( - 'SystemChrome.restoreSystemUIOverlays', - ); - } - - @override - void initState() { - super.initState(); - _scrollController.addListener(_scrollListener); - } - - Future _scrollListener() async { - if (_scrollController.position.pixels == - _scrollController.position.maxScrollExtent) { - filteredData.addAll(await MyApp.musicViewModel.getMusicsWithName( - _textEditingController.text, - limit: 10, - offset: filteredData.length)); - setState(() { - filteredData = filteredData; - }); - } - if (_scrollController.offset >= - _scrollController.position.maxScrollExtent && - !_scrollController.position.outOfRange) { - setState(() { - //you can do anything here - }); - } - if (_scrollController.offset <= - _scrollController.position.minScrollExtent && - !_scrollController.position.outOfRange) { - setState(() { - Timer(Duration(milliseconds: 1), () => _scrollController.jumpTo(0)); - }); - } - } - - List filteredData = []; - - @override - Widget build(BuildContext context) { - double screenHeight = MediaQuery.of(context).size.height; - return GestureDetector( - onTap: () { - FocusScopeNode currentFocus = FocusScope.of(context); - if (!currentFocus.hasPrimaryFocus) { - currentFocus.unfocus(); - resetFullScreen(); - } - }, - child: BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 60.0, - sigmaY: 60.0, - ), - child: Container( - color: bgAppBar.withOpacity(0.5), - height: screenHeight - 50, - padding: const EdgeInsets.only(top: 10), - child: Column( - children: [ - Align( - child: Container( - width: 60, - height: 5, - decoration: BoxDecoration( - color: Color(0xFF3A3A3A).withOpacity(0.6), - borderRadius: BorderRadius.circular(20))), - ), - const SizedBox( - height: 10, - ), - Padding( - padding: - const EdgeInsets.only(bottom: 10, left: 20, right: 20), - child: SizedBox( - height: 40, - child: TextField( - controller: _textEditingController, - keyboardAppearance: Brightness.dark, - onEditingComplete: resetFullScreen, - onChanged: (value) async { - if (_textEditingController.text.isEmpty) { - } else if (value == " ") { - print("popular"); - } else { - filteredData = await MyApp.musicViewModel - .getMusicsWithName(value); - setState(() { - filteredData = filteredData; - }); - } - }, - cursorColor: Colors.white, - keyboardType: TextInputType.text, - style: GoogleFonts.plusJakartaSans(color: grayText), - decoration: InputDecoration( - prefixIcon: const Icon( - Icons.search, - color: grayColor, - ), - focusedBorder: const OutlineInputBorder( - borderSide: - BorderSide(width: 1, color: grayColor), - borderRadius: - BorderRadius.all(Radius.circular(10))), - contentPadding: const EdgeInsets.only( - top: 0, - bottom: 0, - left: defaultPadding, - right: defaultPadding), - fillColor: searchBarColor, - filled: true, - focusColor: grayText, - enabledBorder: const OutlineInputBorder( - borderSide: - BorderSide(width: 1, color: grayColor), - borderRadius: - BorderRadius.all(Radius.circular(10))), - hintText: 'Chercher un son', - hintStyle: - GoogleFonts.plusJakartaSans(color: grayColor)), - ), - ), - ), - Flexible( - child: ScrollConfiguration( - behavior: ScrollBehavior().copyWith(scrollbars: true), - child: ListView.builder( - controller: _scrollController, - itemCount: filteredData.length, - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: MusicListComponent(music: filteredData[index]), - ); - }), - )) - ], - ), - ), - )); - } -} +import 'dart:async'; +import 'dart:ui'; + +import 'package:flutter/Material.dart'; +import 'package:flutter/services.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:justmusic/model/Music.dart'; + +import '../components/music_list_component.dart'; +import '../values/constants.dart'; +import '../main.dart'; + +class SearchSongScreen extends StatefulWidget { + final Function callback; + const SearchSongScreen({Key? key, required this.callback}) : super(key: key); + + @override + State createState() => _SearchSongScreenState(); +} + +class _SearchSongScreenState extends State { + final ScrollController _scrollController = ScrollController(); + final TextEditingController _textEditingController = TextEditingController(); + int? playingIndex; + + Future resetFullScreen() async { + await SystemChannels.platform.invokeMethod( + 'SystemChrome.restoreSystemUIOverlays', + ); + } + + @override + void initState() { + super.initState(); + _scrollController.addListener(_scrollListener); + } + + Future _scrollListener() async { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + filteredData.addAll(await MyApp.musicViewModel.getMusicsWithName( + _textEditingController.text, + limit: 10, + offset: filteredData.length)); + setState(() { + filteredData = filteredData; + }); + } + if (_scrollController.offset >= + _scrollController.position.maxScrollExtent && + !_scrollController.position.outOfRange) { + setState(() { + //you can do anything here + }); + } + if (_scrollController.offset <= + _scrollController.position.minScrollExtent && + !_scrollController.position.outOfRange) { + setState(() { + Timer(Duration(milliseconds: 1), () => _scrollController.jumpTo(0)); + }); + } + } + + List filteredData = []; + + void playMusic(int index) { + if (playingIndex == index) { + setState(() { + playingIndex = null; + }); + } else { + setState(() { + playingIndex = index; + }); + } + } + + @override + Widget build(BuildContext context) { + double screenHeight = MediaQuery.of(context).size.height; + return GestureDetector( + onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + resetFullScreen(); + } + }, + child: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 60.0, + sigmaY: 60.0, + ), + child: Container( + color: bgAppBar.withOpacity(0.5), + height: screenHeight - 50, + padding: const EdgeInsets.only(top: 10), + child: Column( + children: [ + Align( + child: Container( + width: 60, + height: 5, + decoration: BoxDecoration( + color: Color(0xFF3A3A3A).withOpacity(0.6), + borderRadius: BorderRadius.circular(20))), + ), + const SizedBox( + height: 10, + ), + Padding( + padding: + const EdgeInsets.only(bottom: 10, left: 20, right: 20), + child: SizedBox( + height: 40, + child: TextField( + autofocus: true, + controller: _textEditingController, + keyboardAppearance: Brightness.dark, + onEditingComplete: resetFullScreen, + onSubmitted: (value) async { + if (_textEditingController.text.isEmpty) { + } else if (value == " ") { + print("popular"); + } else { + filteredData = await MyApp.musicViewModel + .getMusicsWithName(value); + setState(() { + filteredData = filteredData; + }); + } + }, + cursorColor: Colors.white, + keyboardType: TextInputType.text, + style: GoogleFonts.plusJakartaSans(color: grayText), + decoration: InputDecoration( + prefixIcon: const Icon( + Icons.search, + color: grayColor, + ), + focusedBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 1, color: grayColor), + borderRadius: + BorderRadius.all(Radius.circular(10))), + contentPadding: const EdgeInsets.only( + top: 0, + bottom: 0, + left: defaultPadding, + right: defaultPadding), + fillColor: searchBarColor, + filled: true, + focusColor: grayText, + enabledBorder: const OutlineInputBorder( + borderSide: + BorderSide(width: 1, color: grayColor), + borderRadius: + BorderRadius.all(Radius.circular(10))), + hintText: 'Chercher un son', + hintStyle: + GoogleFonts.plusJakartaSans(color: grayColor)), + ), + ), + ), + Flexible( + child: ScrollConfiguration( + behavior: ScrollBehavior().copyWith(scrollbars: true), + child: ListView.builder( + physics: const BouncingScrollPhysics( + decelerationRate: ScrollDecelerationRate.fast), + controller: _scrollController, + itemCount: filteredData.length, + itemBuilder: (context, index) { + if (playingIndex == index) { + return InkWell( + onTap: () { + widget.callback(filteredData[index]); + }, + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20), + child: MusicListComponent( + music: filteredData[index], + playing: true, + callback: playMusic, + index: index, + ), + )); + } + return InkWell( + onTap: () { + widget.callback(filteredData[index]); + }, + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20), + child: MusicListComponent( + music: filteredData[index], + playing: false, + callback: playMusic, + index: index, + ), + )); + }), + )) + ], + ), + ), + )); + } +} diff --git a/Sources/justMUSIC/lib/services/GeoApi.dart b/Sources/justMUSIC/lib/services/GeoApi.dart new file mode 100644 index 0000000..1f5e55e --- /dev/null +++ b/Sources/justMUSIC/lib/services/GeoApi.dart @@ -0,0 +1,62 @@ +import 'package:geolocator/geolocator.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +import 'package:tuple/tuple.dart'; + +import '../values/keys.dart'; + +class GeoApi { + final String apiKey = geoKey; + Future>?> getNearbyCities() async { + try { + LocationPermission permission = await Geolocator.checkPermission(); + bool serviceEnabled; + + // Test if location services are enabled. + serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) { + // Location services are not enabled don't continue + // accessing the position and request users of the + // App to enable the location services. + return Future.error('Location services are disabled.'); + } + + permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) { + return Future.error('Location permissions are denied'); + } + } + + if (permission == LocationPermission.deniedForever) { + return Future.error( + 'Location permissions are permanently denied, we cannot request permissions.'); + } + + Position position = await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.high); + String apiUrl = + 'http://api.openweathermap.org/data/2.5/find?lat=${position.latitude}&lon=${position.longitude}&cnt=10&appid=$apiKey'; + var response = await http.get(Uri.parse(apiUrl)); + if (response.statusCode == 200) { + var data = json.decode(response.body); + List cities = data['list']; + List> cityInfo = cities.map((city) { + String cityName = city['name'] as String; + String countryName = city['sys']['country'] as String; + return Tuple2(cityName, countryName); + }).toList(); + return cityInfo; + } else { + print('Failed to fetch data'); + } + } catch (e) { + print('Error: $e'); + } + return null; + } +} + +class Tuple {} diff --git a/Sources/justMUSIC/lib/values/constants.dart b/Sources/justMUSIC/lib/values/constants.dart index 60f494f..db5a300 100644 --- a/Sources/justMUSIC/lib/values/constants.dart +++ b/Sources/justMUSIC/lib/values/constants.dart @@ -1,26 +1,28 @@ -import 'package:flutter/material.dart'; - -// All needed color in the project - -const primaryColor = Color(0xFF643BF4); -const secondaryColor = Color(0xFF1C1B23); -const bgColor = Color(0xFF0C0C0C); -const grayColor = Color(0xFF242424); -const profileBttnColor = Color(0xFF232323); -const warningBttnColor = Color(0xFF141414); -const disabledBttnColor = Color(0xFF1F1B2E); -const bgTextField = Color(0xFF1C1B23); -const strokeTextField = Color(0xFF373546); -const unactiveFeed = Color(0xFF848484); -const gradiantPost = Color(0xFF0D0D0D); -const bgModal = Color(0xFF1E1E1E); -const textFieldMessage = Color(0xFF232323); -const bgComment = Color(0xFF222222); -const bgAppBar = Color(0xFF181818); -const grayText = Color(0xFF898989); -const settingColor = Color(0xFF232323); -const searchBarColor = Color(0xFF161616); -// All constants important too us - -const defaultPadding = 30.0; -const settingPadding = 12.0; +import 'package:flutter/material.dart'; + +// All needed color in the project + +const primaryColor = Color(0xFF643BF4); +const secondaryColor = Color(0xFF1C1B23); +const bgColor = Color(0xFF0C0C0C); +const grayColor = Color(0xFF242424); +const profileBttnColor = Color(0xFF232323); +const warningBttnColor = Color(0xFF141414); +const disabledBttnColor = Color(0xFF1F1B2E); +const bgTextField = Color(0xFF1C1B23); +const strokeTextField = Color(0xFF373546); +const unactiveFeed = Color(0xFF848484); +const gradiantPost = Color(0xFF0D0D0D); +const bgModal = Color(0xFF1E1E1E); +const textFieldMessage = Color(0xFF232323); +const bgComment = Color(0xFF222222); +const bgAppBar = Color(0xFF181818); +const grayText = Color(0xFF898989); +const settingColor = Color(0xFF232323); +const searchBarColor = Color(0xFF161616); +const postbutton = Color(0xFF1B1B1B); +const fillButton = Color(0xFF633AF4); +// All constants important too us + +const defaultPadding = 30.0; +const settingPadding = 12.0; diff --git a/Sources/justMUSIC/lib/values/keys.dart b/Sources/justMUSIC/lib/values/keys.dart new file mode 100644 index 0000000..4654117 --- /dev/null +++ b/Sources/justMUSIC/lib/values/keys.dart @@ -0,0 +1 @@ +const geoKey = "85a2724ad38b3994c2b7ebe1d239bbff"; diff --git a/Sources/justMUSIC/lib/view_model/MusicViewModel.dart b/Sources/justMUSIC/lib/view_model/MusicViewModel.dart index 5fe3443..d8cc9da 100644 --- a/Sources/justMUSIC/lib/view_model/MusicViewModel.dart +++ b/Sources/justMUSIC/lib/view_model/MusicViewModel.dart @@ -1,203 +1,224 @@ -import 'dart:convert'; - -import 'package:justmusic/view_model/TokenSpotify.dart'; -import 'package:http/http.dart' as http; -import '../model/Artist.dart'; -import '../model/Music.dart'; - -class MusicViewModel { - final String API_URL = "https://api.spotify.com/v1"; - late TokenSpotify _token; - - MusicViewModel() { - _token = new TokenSpotify(); - } - - // Methods - Future getMusic(String id) async { - var accessToken = await _token.getAccessToken(); - var response = await http.get(Uri.parse('$API_URL/tracks/$id'), headers: { - 'Authorization': 'Bearer $accessToken', - }); - - if (response.statusCode == 200) { - final responseData = jsonDecode(response.body); - List artists = - List.from(responseData['artists'].map((artist) { - return Artist(artist['id'], artist['name'], ''); - })); - - return Music( - responseData['id'], - responseData['name'], - responseData['album']['images'][0]['url'], - responseData['preview_url'], - DateTime.parse(responseData['album']['release_date']), - responseData['duration_ms'] / 1000, - responseData['explicit'], - artists); - } else { - throw Exception( - 'Error retrieving music information : ${response.statusCode} ${response.reasonPhrase}'); - } - } - - List _getMusicsFromResponse(Map responseData) { - List musics = []; - - List tracks = responseData['tracks']['items']; - for (var track in tracks) { - List artists = List.from(track['artists'].map((artist) { - return Artist(artist['id'], artist['name'], ''); - })); - - musics.add(Music( - track['id'], - track['name'], - track['album']['images'][0]['url'], - track['preview_url'], - DateTime.now(), - track['duration_ms'] / 1000, - track['explicit'], - artists)); - } - - return musics; - } - - Future> getMusicsWithName(String name, - {int limit = 20, int offset = 0, String market = "FR"}) async { - var accessToken = await _token.getAccessToken(); - var response = await http.get( - Uri.parse( - '$API_URL/search?q=track%3A$name&type=track&market=fr&limit=$limit&offset=$offset'), - headers: { - 'Authorization': 'Bearer $accessToken', - }); - - if (response.statusCode == 200) { - Map responseData = jsonDecode(response.body); - return _getMusicsFromResponse(responseData); - } else { - throw Exception( - 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); - } - } - - Future> getMusicsWithArtistName(String name, - {int limit = 20, int offset = 0, String market = "FR"}) async { - var accessToken = await _token.getAccessToken(); - var response = await http.get( - Uri.parse( - '$API_URL/search?q=artist%3A$name&type=track&market=fr&limit=$limit&offset=$offset'), - headers: { - 'Authorization': 'Bearer $accessToken', - }); - - if (response.statusCode == 200) { - Map responseData = jsonDecode(response.body); - return _getMusicsFromResponse(responseData); - } else { - throw Exception( - 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); - } - } - - Future getArtistWithName(String name, {String market = "FR"}) async { - var accessToken = await _token.getAccessToken(); - var response = await http.get( - Uri.parse( - '$API_URL/search?q=artist%3A$name&type=artist&market=$market'), - headers: { - 'Authorization': 'Bearer $accessToken', - }); - - if (response.statusCode == 200) { - final responseData = jsonDecode(response.body); - List artists = - List.from(responseData['artists']['items'].map((artist) { - String image = ''; - if (!artist['images'].isEmpty) { - image = artist['images'][0]['url']; - } - return Artist(artist['id'], artist['name'], image); - })); - - for (Artist a in artists) { - if (a.name?.toLowerCase() == name.toLowerCase()) { - return a; - } - } - - throw Exception('Artist not found : ${name}'); - } else { - throw Exception( - 'Error retrieving artist information : ${response.statusCode} ${response.reasonPhrase}'); - } - } - - Future> getArtistsWithName(String name, - {int limit = 20, int offset = 0, String market = "FR"}) async { - var accessToken = await _token.getAccessToken(); - var response = await http.get( - Uri.parse( - '$API_URL/search?q=artist%3A$name&type=artist&market=$market&limit=$limit&offset=$offset'), - headers: { - 'Authorization': 'Bearer $accessToken', - }); - - if (response.statusCode == 200) { - final responseData = jsonDecode(response.body); - List artists = - List.from(responseData['artists']['items'].map((artist) { - String image = ''; - if (!artist['images'].isEmpty) { - image = artist['images'][0]['url']; - } - return Artist(artist['id'], artist['name'], image); - })); - - return artists; - } else { - throw Exception( - 'Error while retrieving artist : ${response.statusCode} ${response.reasonPhrase}'); - } - } - - Future> getTopMusicsWithArtistId(String id, - {String market = "FR"}) async { - var accessToken = await _token.getAccessToken(); - var response = await http.get( - Uri.parse('$API_URL/artists/$id/top-tracks?market=$market'), - headers: { - 'Authorization': 'Bearer $accessToken', - }); - - if (response.statusCode == 200) { - Map responseData = jsonDecode(response.body); - List musics = []; - - List tracks = responseData['tracks']; - for (var track in tracks) { - List artists = List.from(track['artists'].map((artist) { - return Artist(artist['id'], artist['name'], ''); - })); - - musics.add(Music( - track['id'], - track['name'], - track['album']['images'][0]['url'], - track['preview_url'], - DateTime.now(), - track['duration_ms'] / 1000, - track['explicit'], - artists)); - } - - return musics; - } else { - throw Exception( - 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); - } - } -} +import 'dart:convert'; + +import 'package:justmusic/view_model/TokenSpotify.dart'; +import 'package:http/http.dart' as http; +import '../model/Artist.dart'; +import '../model/Music.dart'; + +class MusicViewModel { + final String API_URL = "https://api.spotify.com/v1"; + late TokenSpotify _token; + + MusicViewModel() { + _token = new TokenSpotify(); + } + + // Methods + Future getMusic(String id) async { + var accessToken = await _token.getAccessToken(); + var response = await http.get(Uri.parse('$API_URL/tracks/$id'), headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + final responseData = jsonDecode(response.body); + List artists = + List.from(responseData['artists'].map((artist) { + return Artist(artist['id'], artist['name'], ''); + })); + + return _getMusicFromResponse(responseData); + } else { + throw Exception( + 'Error retrieving music information : ${response.statusCode} ${response.reasonPhrase}'); + } + } + + Music _getMusicFromResponse(dynamic track) { + List artists = List.from(track['artists'].map((artist) { + return Artist(artist['id'], artist['name'], ''); + })); + + return Music( + track['id'], + track['name'], + track['album']['images'][0]['url'], + track['preview_url'], + int.parse(track['album']['release_date'].split('-')[0]), + track['duration_ms'] / 1000, + track['explicit'], + artists); + } + + Future> getMusicsWithName(String name, + {int limit = 20, int offset = 0, String market = "FR"}) async { + var accessToken = await _token.getAccessToken(); + var response = await http.get( + Uri.parse( + '$API_URL/search?q=track%3A$name&type=track&market=fr&limit=$limit&offset=$offset'), + headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + Map responseData = jsonDecode(response.body); + return List.from(responseData['tracks']['items'].map((track) { + return _getMusicFromResponse(track); + })); + } else { + throw Exception( + 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); + } + } + + Future> getMusicsWithArtistName(String name, + {int limit = 20, int offset = 0, String market = "FR"}) async { + var accessToken = await _token.getAccessToken(); + var response = await http.get( + Uri.parse( + '$API_URL/search?q=artist%3A$name&type=track&market=fr&limit=$limit&offset=$offset'), + headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + Map responseData = jsonDecode(response.body); + return List.from(responseData['tracks']['items'].map((track) { + return _getMusicFromResponse(track); + })); + } else { + throw Exception( + 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); + } + } + + Future getArtistWithName(String name, {String market = "FR"}) async { + var accessToken = await _token.getAccessToken(); + var response = await http.get( + Uri.parse( + '$API_URL/search?q=artist%3A$name&type=artist&market=$market'), + headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + final responseData = jsonDecode(response.body); + List artists = + List.from(responseData['artists']['items'].map((artist) { + String image = ''; + if (!artist['images'].isEmpty) { + image = artist['images'][0]['url']; + } + return Artist(artist['id'], artist['name'], image); + })); + + for (Artist a in artists) { + if (a.name?.toLowerCase() == name.toLowerCase()) { + return a; + } + } + + throw Exception('Artist not found : ${name}'); + } else { + throw Exception( + 'Error retrieving artist information : ${response.statusCode} ${response.reasonPhrase}'); + } + } + + Future> getArtistsWithName(String name, + {int limit = 20, int offset = 0, String market = "FR"}) async { + var accessToken = await _token.getAccessToken(); + var response = await http.get( + Uri.parse( + '$API_URL/search?q=artist%3A$name&type=artist&market=$market&limit=$limit&offset=$offset'), + headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + final responseData = jsonDecode(response.body); + List artists = + List.from(responseData['artists']['items'].map((artist) { + String image = ''; + if (!artist['images'].isEmpty) { + image = artist['images'][0]['url']; + } + return Artist(artist['id'], artist['name'], image); + })); + + return artists; + } else { + throw Exception( + 'Error while retrieving artist : ${response.statusCode} ${response.reasonPhrase}'); + } + } + + Future> getTopMusicsWithArtistId(String id, + {String market = "FR"}) async { + var accessToken = await _token.getAccessToken(); + var response = await http.get( + Uri.parse('$API_URL/artists/$id/top-tracks?market=$market'), + headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + Map responseData = jsonDecode(response.body); + return List.from(responseData['tracks'].map((track) { + return _getMusicFromResponse(track); + })); + } else { + throw Exception( + 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); + } + } + + Future> getMusicsWithPlaylistId(String id, + {String market = "FR"}) async { + var accessToken = await _token.getAccessToken(); + var response = await http + .get(Uri.parse('$API_URL/playlists/$id?market=$market'), headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + Map responseData = jsonDecode(response.body); + + List musics = []; + + List tracks = responseData['tracks']['items']; + for (var track in tracks) { + musics.add(_getMusicFromResponse(track['track'])); + } + + return musics; + } else { + throw Exception( + 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); + } + } + + Future> getMusicsWithIds(List ids, + {String market = "FR"}) async { + var accessToken = await _token.getAccessToken(); + String url = API_URL + '/tracks?market=$market&ids='; + + if (ids.length == 0) return []; + + url += ids.join('%2C'); + + var response = await http.get(Uri.parse(url), headers: { + 'Authorization': 'Bearer $accessToken', + }); + + if (response.statusCode == 200) { + Map responseData = jsonDecode(response.body); + return List.from(responseData['tracks'].map((track) { + return _getMusicFromResponse(track); + })); + } else { + throw Exception( + 'Error while retrieving music : ${response.statusCode} ${response.reasonPhrase}'); + } + } +} diff --git a/Sources/justMUSIC/pubspec.lock b/Sources/justMUSIC/pubspec.lock index f42c1e9..7903bf2 100644 --- a/Sources/justMUSIC/pubspec.lock +++ b/Sources/justMUSIC/pubspec.lock @@ -1,602 +1,810 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "5dce45a06d386358334eb1689108db6455d90ceb0d75848d5f4819283d4ee2b8" - url: "https://pub.dev" - source: hosted - version: "1.3.4" - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - audioplayers: - dependency: "direct main" - description: - name: audioplayers - sha256: "61583554386721772f9309f509e17712865b38565a903c761f96b1115a979282" - url: "https://pub.dev" - source: hosted - version: "4.1.0" - audioplayers_android: - dependency: transitive - description: - name: audioplayers_android - sha256: dbdc9b7f2aa2440314c638aa55aadd45c7705e8340d5eddf2e3fb8da32d4ae2c - url: "https://pub.dev" - source: hosted - version: "3.0.2" - audioplayers_darwin: - dependency: transitive - description: - name: audioplayers_darwin - sha256: "6aea96df1d12f7ad5a71d88c6d1b22a216211a9564219920124c16768e456e9d" - url: "https://pub.dev" - source: hosted - version: "4.1.0" - audioplayers_linux: - dependency: transitive - description: - name: audioplayers_linux - sha256: "396b62ac62c92dd26c3bc5106583747f57a8b325ebd2b41e5576f840cfc61338" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - audioplayers_platform_interface: - dependency: transitive - description: - name: audioplayers_platform_interface - sha256: f7daaed4659143094151ecf6bacd927d29ab8acffba98c110c59f0b81ae51143 - url: "https://pub.dev" - source: hosted - version: "5.0.1" - audioplayers_web: - dependency: transitive - description: - name: audioplayers_web - sha256: ec84fd46eed1577148ed4113f5998a36a18da4fce7170c37ce3e21b631393339 - url: "https://pub.dev" - source: hosted - version: "3.1.0" - audioplayers_windows: - dependency: transitive - description: - name: audioplayers_windows - sha256: "1d3aaac98a192b8488167711ba1e67d8b96333e8d0572ede4e2912e5bbce69a3" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - auto_size_text: - dependency: "direct main" - description: - name: auto_size_text - sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - circular_reveal_animation: - dependency: "direct main" - description: - name: circular_reveal_animation - sha256: "198f5a1fa27384dcf950807e0ae07a0da857c04df6233f7468755ee9db102b0c" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - clock: - dependency: transitive - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - cloud_firestore: - dependency: "direct main" - description: - name: cloud_firestore - sha256: f1a06ad4499ed9ab73703560d44893e6b9e66ce3923c9121f4ef3981c972057f - url: "https://pub.dev" - source: hosted - version: "4.8.4" - cloud_firestore_platform_interface: - dependency: transitive - description: - name: cloud_firestore_platform_interface - sha256: "86bd1865abbeb09a7d09da3e70364a09f894937270651fc611a1c6d6a9f7b02c" - url: "https://pub.dev" - source: hosted - version: "5.15.3" - cloud_firestore_web: - dependency: transitive - description: - name: cloud_firestore_web - sha256: ac2eeb2a7ab1928c3aacc30eed750fa839d6f620e112a5459e321df217be2f47 - url: "https://pub.dev" - source: hosted - version: "3.6.3" - collection: - dependency: transitive - description: - name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" - url: "https://pub.dev" - source: hosted - version: "1.17.1" - crypto: - dependency: transitive - description: - name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 - url: "https://pub.dev" - source: hosted - version: "3.0.2" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be - url: "https://pub.dev" - source: hosted - version: "1.0.5" - custom_draggable_widget: - dependency: "direct main" - description: - name: custom_draggable_widget - sha256: "15718003ebcebb84acdf0c625831a880d139a284d8de9d943ef0d0a669f10159" - url: "https://pub.dev" - source: hosted - version: "0.0.2" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - ffi: - dependency: transitive - description: - name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 - url: "https://pub.dev" - source: hosted - version: "2.0.2" - file: - dependency: transitive - description: - name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" - url: "https://pub.dev" - source: hosted - version: "6.1.4" - firebase_auth: - dependency: "direct main" - description: - name: firebase_auth - sha256: "49fd35ce06f2530dd460e5dc123235731cb61dd7c76b0af4b6e190404880d04d" - url: "https://pub.dev" - source: hosted - version: "4.7.2" - firebase_auth_platform_interface: - dependency: transitive - description: - name: firebase_auth_platform_interface - sha256: "817f3ceb84ef5e9adaaf50cf7a19255f6ffcdd12c6f9e9aa4cf00fc7f2eb3cfb" - url: "https://pub.dev" - source: hosted - version: "6.16.1" - firebase_auth_web: - dependency: transitive - description: - name: firebase_auth_web - sha256: e9044778287f1ff8f9f4cee7e247b03ec87bb8977e0e65ad27dc337e196132e8 - url: "https://pub.dev" - source: hosted - version: "5.6.2" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - sha256: "2e9324f719e90200dc7d3c4f5d2abc26052f9f2b995d3b6626c47a0dfe1c8192" - url: "https://pub.dev" - source: hosted - version: "2.15.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: b63e3be6c96ef5c33bdec1aab23c91eb00696f6452f0519401d640938c94cba2 - url: "https://pub.dev" - source: hosted - version: "4.8.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: "0fd5c4b228de29b55fac38aed0d9e42514b3d3bd47675de52bf7f8fccaf922fa" - url: "https://pub.dev" - source: hosted - version: "2.6.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_animated_play_button: - dependency: "direct main" - description: - name: flutter_animated_play_button - sha256: dd955a450a4514e935e2f410afbd03b3bcf5f31b933a8f1334199caa3c6a81e2 - url: "https://pub.dev" - source: hosted - version: "0.3.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - flutter_screenutil: - dependency: "direct main" - description: - name: flutter_screenutil - sha256: "0a122936b450324cbdfd51be0819cc6fcebb093eb65585e9cd92263f7a1a8a39" - url: "https://pub.dev" - source: hosted - version: "5.7.0" - flutter_signin_button: - dependency: "direct main" - description: - name: flutter_signin_button - sha256: a063ecc5d5308377e103c9c3a89084abf15fca4440636233af6a13abacd5dcae - url: "https://pub.dev" - source: hosted - version: "2.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - font_awesome_flutter: - dependency: transitive - description: - name: font_awesome_flutter - sha256: "1f93e5799f0e6c882819e8393a05c6ca5226010f289190f2242ec19f3f0fdba5" - url: "https://pub.dev" - source: hosted - version: "9.2.0" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: "6b6f10f0ce3c42f6552d1c70d2c28d764cf22bb487f50f66cca31dcd5194f4d6" - url: "https://pub.dev" - source: hosted - version: "4.0.4" - gradiantbutton: - dependency: "direct main" - description: - name: gradiantbutton - sha256: c88ac8567242630cd14231e2a6a861da4e40a02a9a0310af360e05634890d172 - url: "https://pub.dev" - source: hosted - version: "0.0.1" - gradient_borders: - dependency: "direct main" - description: - name: gradient_borders - sha256: "69eeaff519d145a4c6c213ada1abae386bcc8981a4970d923e478ce7ba19e309" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - http: - dependency: "direct main" - description: - name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" - url: "https://pub.dev" - source: hosted - version: "0.13.5" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - ionicons: - dependency: "direct main" - description: - name: ionicons - sha256: "5496bc65a16115ecf05b15b78f494ee4a8869504357668f0a11d689e970523cf" - url: "https://pub.dev" - source: hosted - version: "0.2.2" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" - lints: - dependency: transitive - description: - name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - matcher: - dependency: transitive - description: - name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" - url: "https://pub.dev" - source: hosted - version: "0.12.15" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - meta: - dependency: transitive - description: - name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - modal_bottom_sheet: - dependency: "direct main" - description: - name: modal_bottom_sheet - sha256: ef533916a2c3089571c32bd34e410faca77a6849a3f28f748e0794525c5658a0 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path: - dependency: transitive - description: - name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" - url: "https://pub.dev" - source: hosted - version: "1.8.3" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" - url: "https://pub.dev" - source: hosted - version: "2.0.15" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" - url: "https://pub.dev" - source: hosted - version: "2.0.27" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" - url: "https://pub.dev" - source: hosted - version: "2.2.4" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 - url: "https://pub.dev" - source: hosted - version: "2.1.11" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" - url: "https://pub.dev" - source: hosted - version: "2.0.6" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" - url: "https://pub.dev" - source: hosted - version: "2.1.7" - platform: - dependency: transitive - description: - name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - smooth_corner: - dependency: "direct main" - description: - name: smooth_corner - sha256: "1e920cffd9644d6f51f9a99674652f8c00f2e9074b275f3edde0de1441ba78e9" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 - url: "https://pub.dev" - source: hosted - version: "1.9.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 - url: "https://pub.dev" - source: hosted - version: "1.11.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - synchronized: - dependency: transitive - description: - name: synchronized - sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb - url: "https://pub.dev" - source: hosted - version: "0.5.1" - text_scroll: - dependency: "direct main" - description: - name: text_scroll - sha256: "7869d86a6fdd725dee56bdd150216a99f0372b82fbfcac319214dbd5f36e1908" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - top_snackbar_flutter: - dependency: "direct main" - description: - name: top_snackbar_flutter - sha256: "22d14664a13db6ac714934c3382bd8d4daa57fb888a672f922df71981c5a5cb2" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - uuid: - dependency: transitive - description: - name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" - url: "https://pub.dev" - source: hosted - version: "3.0.7" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - win32: - dependency: transitive - description: - name: win32 - sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" - url: "https://pub.dev" - source: hosted - version: "4.1.4" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff - url: "https://pub.dev" - source: hosted - version: "1.0.1" - zoom_tap_animation: - dependency: "direct main" - description: - name: zoom_tap_animation - sha256: d9f7a73cab65aa1546ba6886b5e21d3c8ccccb34e4e5f770301c306d4868bee0 - url: "https://pub.dev" - source: hosted - version: "1.1.0" -sdks: - dart: ">=3.0.0-0 <4.0.0" - flutter: ">=3.3.0" +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "5dce45a06d386358334eb1689108db6455d90ceb0d75848d5f4819283d4ee2b8" + url: "https://pub.dev" + source: hosted + version: "1.3.4" + animated_appear: + dependency: "direct main" + description: + name: animated_appear + sha256: "53097d7bb6d5e4a1a3a74c8f3028c47c87101c6ec8903f2002372d1eb5aee991" + url: "https://pub.dev" + source: hosted + version: "0.0.4" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + audioplayers: + dependency: "direct main" + description: + name: audioplayers + sha256: "61583554386721772f9309f509e17712865b38565a903c761f96b1115a979282" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + audioplayers_android: + dependency: transitive + description: + name: audioplayers_android + sha256: dbdc9b7f2aa2440314c638aa55aadd45c7705e8340d5eddf2e3fb8da32d4ae2c + url: "https://pub.dev" + source: hosted + version: "3.0.2" + audioplayers_darwin: + dependency: transitive + description: + name: audioplayers_darwin + sha256: "6aea96df1d12f7ad5a71d88c6d1b22a216211a9564219920124c16768e456e9d" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + audioplayers_linux: + dependency: transitive + description: + name: audioplayers_linux + sha256: "396b62ac62c92dd26c3bc5106583747f57a8b325ebd2b41e5576f840cfc61338" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + audioplayers_platform_interface: + dependency: transitive + description: + name: audioplayers_platform_interface + sha256: f7daaed4659143094151ecf6bacd927d29ab8acffba98c110c59f0b81ae51143 + url: "https://pub.dev" + source: hosted + version: "5.0.1" + audioplayers_web: + dependency: transitive + description: + name: audioplayers_web + sha256: ec84fd46eed1577148ed4113f5998a36a18da4fce7170c37ce3e21b631393339 + url: "https://pub.dev" + source: hosted + version: "3.1.0" + audioplayers_windows: + dependency: transitive + description: + name: audioplayers_windows + sha256: "1d3aaac98a192b8488167711ba1e67d8b96333e8d0572ede4e2912e5bbce69a3" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + circular_reveal_animation: + dependency: "direct main" + description: + name: circular_reveal_animation + sha256: "198f5a1fa27384dcf950807e0ae07a0da857c04df6233f7468755ee9db102b0c" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + cloud_firestore: + dependency: "direct main" + description: + name: cloud_firestore + sha256: f1a06ad4499ed9ab73703560d44893e6b9e66ce3923c9121f4ef3981c972057f + url: "https://pub.dev" + source: hosted + version: "4.8.4" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + sha256: "86bd1865abbeb09a7d09da3e70364a09f894937270651fc611a1c6d6a9f7b02c" + url: "https://pub.dev" + source: hosted + version: "5.15.3" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + sha256: ac2eeb2a7ab1928c3aacc30eed750fa839d6f620e112a5459e321df217be2f47 + url: "https://pub.dev" + source: hosted + version: "3.6.3" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" + source: hosted + version: "0.3.3+4" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + custom_draggable_widget: + dependency: "direct main" + description: + name: custom_draggable_widget + sha256: "15718003ebcebb84acdf0c625831a880d139a284d8de9d943ef0d0a669f10159" + url: "https://pub.dev" + source: hosted + version: "0.0.2" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "770eb1ab057b5ae4326d1c24cc57710758b9a46026349d021d6311bd27580046" + url: "https://pub.dev" + source: hosted + version: "0.9.2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "4ada532862917bf16e3adb3891fe3a5917a58bae03293e497082203a80909412" + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: "412705a646a0ae90f33f37acfae6a0f7cbc02222d6cd34e479421c3e74d3853c" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "1372760c6b389842b77156203308940558a2817360154084368608413835fc26" + url: "https://pub.dev" + source: hosted + version: "0.9.3" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: "49fd35ce06f2530dd460e5dc123235731cb61dd7c76b0af4b6e190404880d04d" + url: "https://pub.dev" + source: hosted + version: "4.7.2" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: "817f3ceb84ef5e9adaaf50cf7a19255f6ffcdd12c6f9e9aa4cf00fc7f2eb3cfb" + url: "https://pub.dev" + source: hosted + version: "6.16.1" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: e9044778287f1ff8f9f4cee7e247b03ec87bb8977e0e65ad27dc337e196132e8 + url: "https://pub.dev" + source: hosted + version: "5.6.2" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "2e9324f719e90200dc7d3c4f5d2abc26052f9f2b995d3b6626c47a0dfe1c8192" + url: "https://pub.dev" + source: hosted + version: "2.15.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: b63e3be6c96ef5c33bdec1aab23c91eb00696f6452f0519401d640938c94cba2 + url: "https://pub.dev" + source: hosted + version: "4.8.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "0fd5c4b228de29b55fac38aed0d9e42514b3d3bd47675de52bf7f8fccaf922fa" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_animated_play_button: + dependency: "direct main" + description: + name: flutter_animated_play_button + sha256: dd955a450a4514e935e2f410afbd03b3bcf5f31b933a8f1334199caa3c6a81e2 + url: "https://pub.dev" + source: hosted + version: "0.3.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" + url: "https://pub.dev" + source: hosted + version: "2.0.15" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + sha256: "1b61f8c4cbf965104b6ca7160880ff1af6755aad7fec70b58444245132453745" + url: "https://pub.dev" + source: hosted + version: "5.8.4" + flutter_signin_button: + dependency: "direct main" + description: + name: flutter_signin_button + sha256: a063ecc5d5308377e103c9c3a89084abf15fca4440636233af6a13abacd5dcae + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + font_awesome_flutter: + dependency: transitive + description: + name: font_awesome_flutter + sha256: "1f93e5799f0e6c882819e8393a05c6ca5226010f289190f2242ec19f3f0fdba5" + url: "https://pub.dev" + source: hosted + version: "9.2.0" + geolocator: + dependency: "direct main" + description: + name: geolocator + sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8" + url: "https://pub.dev" + source: hosted + version: "9.0.2" + geolocator_android: + dependency: transitive + description: + name: geolocator_android + sha256: b06c72853c993ae533f482d81a12805d7a441f5231d9668718bc7131d7464082 + url: "https://pub.dev" + source: hosted + version: "4.2.0" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + sha256: "36527c555f4c425f7d8fa8c7c07d67b78e3ff7590d40448051959e1860c1cfb4" + url: "https://pub.dev" + source: hosted + version: "2.2.7" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + sha256: af4d69231452f9620718588f41acc4cb58312368716bfff2e92e770b46ce6386 + url: "https://pub.dev" + source: hosted + version: "4.0.7" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + sha256: f68a122da48fcfff68bbc9846bb0b74ef651afe84a1b1f6ec20939de4d6860e1 + url: "https://pub.dev" + source: hosted + version: "2.1.6" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + sha256: f5911c88e23f48b598dd506c7c19eff0e001645bdc03bb6fecb9f4549208354d + url: "https://pub.dev" + source: hosted + version: "0.1.1" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: "6b6f10f0ce3c42f6552d1c70d2c28d764cf22bb487f50f66cca31dcd5194f4d6" + url: "https://pub.dev" + source: hosted + version: "4.0.4" + gradiantbutton: + dependency: "direct main" + description: + name: gradiantbutton + sha256: c88ac8567242630cd14231e2a6a861da4e40a02a9a0310af360e05634890d172 + url: "https://pub.dev" + source: hosted + version: "0.0.1" + gradient_borders: + dependency: "direct main" + description: + name: gradient_borders + sha256: "69eeaff519d145a4c6c213ada1abae386bcc8981a4970d923e478ce7ba19e309" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "6296e98782726d37f59663f0727d0e978eee1ced1ffed45ccaba591786a7f7b3" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "8179b54039b50eee561676232304f487602e2950ffb3e8995ed9034d6505ca34" + url: "https://pub.dev" + source: hosted + version: "0.8.7+4" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: b3e2f21feb28b24dd73a35d7ad6e83f568337c70afab5eabac876e23803f264b + url: "https://pub.dev" + source: hosted + version: "0.8.8" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "02cbc21fe1706b97942b575966e5fbbeaac535e76deef70d3a242e4afb857831" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: cee2aa86c56780c13af2c77b5f2f72973464db204569e1ba2dd744459a065af4 + url: "https://pub.dev" + source: hosted + version: "0.2.1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: c1134543ae2187e85299996d21c526b2f403854994026d575ae4cf30d7bb2a32 + url: "https://pub.dev" + source: hosted + version: "2.9.0" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: c3066601ea42113922232c7b7b3330a2d86f029f685bba99d82c30e799914952 + url: "https://pub.dev" + source: hosted + version: "0.2.1" + insta_image_viewer: + dependency: "direct main" + description: + name: insta_image_viewer + sha256: "9a81432b1ab907ea91c255ec079440afe43f999533422badffaa482dfb7fdfbb" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + ionicons: + dependency: "direct main" + description: + name: ionicons + sha256: "5496bc65a16115ecf05b15b78f494ee4a8869504357668f0a11d689e970523cf" + url: "https://pub.dev" + source: hosted + version: "0.2.2" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + modal_bottom_sheet: + dependency: "direct main" + description: + name: modal_bottom_sheet + sha256: ef533916a2c3089571c32bd34e410faca77a6849a3f28f748e0794525c5658a0 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + url: "https://pub.dev" + source: hosted + version: "2.0.15" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + url: "https://pub.dev" + source: hosted + version: "2.0.27" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + url: "https://pub.dev" + source: hosted + version: "2.1.11" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" + url: "https://pub.dev" + source: hosted + version: "2.1.7" + pinch_zoom: + dependency: "direct main" + description: + name: pinch_zoom + sha256: ad12872281742726afaf03438d99a4572c584a612630768953beb6dfd6f9389a + url: "https://pub.dev" + source: hosted + version: "1.0.0" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + smooth_corner: + dependency: "direct main" + description: + name: smooth_corner + sha256: "1e920cffd9644d6f51f9a99674652f8c00f2e9074b275f3edde0de1441ba78e9" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + smooth_list_view: + dependency: "direct main" + description: + name: smooth_list_view + sha256: d6eb3bed78881c50d4574b0dd466ed3321972477688c1c021178f3132155112a + url: "https://pub.dev" + source: hosted + version: "1.0.4" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + text_scroll: + dependency: "direct main" + description: + name: text_scroll + sha256: "7869d86a6fdd725dee56bdd150216a99f0372b82fbfcac319214dbd5f36e1908" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + top_snackbar_flutter: + dependency: "direct main" + description: + name: top_snackbar_flutter + sha256: "22d14664a13db6ac714934c3382bd8d4daa57fb888a672f922df71981c5a5cb2" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + tuple: + dependency: "direct main" + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + win32: + dependency: transitive + description: + name: win32 + sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 + url: "https://pub.dev" + source: hosted + version: "5.0.6" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff + url: "https://pub.dev" + source: hosted + version: "1.0.1" + zoom_tap_animation: + dependency: "direct main" + description: + name: zoom_tap_animation + sha256: d9f7a73cab65aa1546ba6886b5e21d3c8ccccb34e4e5f770301c306d4868bee0 + url: "https://pub.dev" + source: hosted + version: "1.1.0" +sdks: + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.10.0" diff --git a/Sources/justMUSIC/pubspec.yaml b/Sources/justMUSIC/pubspec.yaml index daebe28..808fac1 100644 --- a/Sources/justMUSIC/pubspec.yaml +++ b/Sources/justMUSIC/pubspec.yaml @@ -1,111 +1,118 @@ -name: justmusic -description: A new Flutter project. - -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+1 - -environment: - sdk: '>=2.18.2 <3.0.0' - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - http: ^0.13.5 - - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 - google_fonts: ^4.0.4 - gradiantbutton: ^0.0.1 - smooth_corner: ^1.1.0 - flutter_signin_button: ^2.0.0 - flutter_screenutil: ^5.7.0 - auto_size_text: ^3.0.0 - gradient_borders: ^1.0.0 - text_scroll: ^0.2.0 - circular_reveal_animation: ^2.0.1 - zoom_tap_animation: ^1.1.0 - custom_draggable_widget: ^0.0.2 - modal_bottom_sheet: ^2.1.2 - flutter_animated_play_button: ^0.3.0 - audioplayers: ^4.1.0 - ionicons: ^0.2.2 - top_snackbar_flutter: ^3.1.0 - firebase_core: ^2.15.0 - firebase_auth: ^4.7.2 - cloud_firestore: ^4.8.4 - -dev_dependencies: - flutter_test: - sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^2.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - assets: - - assets/images/ - - assets/ - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages +name: justmusic +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=2.18.2 <3.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + http: ^0.13.5 + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + google_fonts: ^4.0.4 + gradiantbutton: ^0.0.1 + smooth_corner: ^1.1.0 + flutter_signin_button: ^2.0.0 + flutter_screenutil: ^5.7.0 + auto_size_text: ^3.0.0 + gradient_borders: ^1.0.0 + text_scroll: ^0.2.0 + circular_reveal_animation: ^2.0.1 + zoom_tap_animation: ^1.1.0 + custom_draggable_widget: ^0.0.2 + modal_bottom_sheet: ^2.1.2 + flutter_animated_play_button: ^0.3.0 + audioplayers: ^4.1.0 + ionicons: ^0.2.2 + top_snackbar_flutter: ^3.1.0 + firebase_core: ^2.15.0 + firebase_auth: ^4.7.2 + cloud_firestore: ^4.8.4 + image_picker: ^1.0.1 + insta_image_viewer: ^1.0.2 + pinch_zoom: ^1.0.0 + smooth_list_view: ^1.0.4 + animated_appear: ^0.0.4 + geolocator: ^9.0.2 + tuple: ^2.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/ + - assets/ + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/Sources/justMUSIC/test/Music_test.dart b/Sources/justMUSIC/test/Music_test.dart index 2b958bb..482f4ff 100644 --- a/Sources/justMUSIC/test/Music_test.dart +++ b/Sources/justMUSIC/test/Music_test.dart @@ -1,60 +1,83 @@ -import 'package:justmusic/model/Artist.dart'; -import 'package:justmusic/model/Music.dart'; -import 'package:justmusic/view_model/MusicViewModel.dart'; - -Future main() async { - MusicViewModel musicVM = new MusicViewModel(); - Music m = await musicVM.getMusic('295SxdR1DqunCNwd0U767w'); - - print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); - print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); - for (Artist a in m.artists) { - print("id : ${a.id}, name : ${a.name}"); - } - - print('\nMusics :'); - - List musics = await musicVM.getMusicsWithName('Shavkat'); - for (Music m in musics) { - print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); - print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); - for (Artist a in m.artists) { - print("id : ${a.id}, name : ${a.name}"); - } - } - - print('\nMusics With Artist:'); - - List musics2 = await musicVM.getMusicsWithArtistName('jul'); - for (Music m in musics2) { - print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); - print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); - for (Artist a in m.artists) { - print("id : ${a.id}, name : ${a.name}"); - } - } - - print('\nArtist with Name:'); - - Artist a = await musicVM.getArtistWithName('jul'); - print("id : ${a.id}, name : ${a.name}, image : ${a.image}"); - - print('\nArtists with Name:'); - - List artists = await musicVM.getArtistsWithName('jul'); - for (Artist a in artists) { - print("id : ${a.id}, name : ${a.name}, image : ${a.image}"); - } - - print('\nTop Musics :'); - - List topMusics = await musicVM.getTopMusicsWithArtistId('3NH8t45zOTqzlZgBvZRjvB'); - for (Music m in topMusics) { - print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); - print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); - for (Artist a in m.artists) { - print("id : ${a.id}, name : ${a.name}"); - } - } - -} +import 'package:justmusic/model/Artist.dart'; +import 'package:justmusic/model/Music.dart'; +import 'package:justmusic/view_model/MusicViewModel.dart'; + +Future main() async { + MusicViewModel musicVM = new MusicViewModel(); + Music m = await musicVM.getMusic('295SxdR1DqunCNwd0U767w'); + + print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); + print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); + for (Artist a in m.artists) { + print("id : ${a.id}, name : ${a.name}"); + } + + print('\nMusics :'); + + List musics = await musicVM.getMusicsWithName('Shavkat'); + for (Music m in musics) { + print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); + print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); + for (Artist a in m.artists) { + print("id : ${a.id}, name : ${a.name}"); + } + } + + print('\nMusics With Artist:'); + + List musics2 = await musicVM.getMusicsWithArtistName('jul'); + for (Music m in musics2) { + print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); + print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); + for (Artist a in m.artists) { + print("id : ${a.id}, name : ${a.name}"); + } + } + + print('\nArtist with Name:'); + + Artist a = await musicVM.getArtistWithName('jul'); + print("id : ${a.id}, name : ${a.name}, image : ${a.image}"); + + print('\nArtists with Name:'); + + List artists = await musicVM.getArtistsWithName('jul'); + for (Artist a in artists) { + print("id : ${a.id}, name : ${a.name}, image : ${a.image}"); + } + + print('\nTop Musics :'); + + List topMusics = await musicVM.getTopMusicsWithArtistId('3NH8t45zOTqzlZgBvZRjvB'); + for (Music m in topMusics) { + print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); + print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); + for (Artist a in m.artists) { + print("id : ${a.id}, name : ${a.name}"); + } + } + + print('\nPlaylist Musics :'); + + List playlistMusics = await musicVM.getMusicsWithPlaylistId('37i9dQZF1DX1X23oiQRTB5'); + for (Music m in playlistMusics) { + print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); + print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); + for (Artist a in m.artists) { + print("id : ${a.id}, name : ${a.name}"); + } + } + + print('\nMusics With Ids :'); + + List musicsIds = await musicVM.getMusicsWithIds(['6D1HiF2e3Z0F8FwQ5uLxwn','6IGg7qsBvA5xbrwz3MNHWK']); + for (Music m in musicsIds) { + print("id : ${m.id.toString()}, cover : ${m.cover}, title : ${m.title}"); + print("date : ${m.date.toString()}, preview : ${m.previewUrl}, duration : ${m.duration}, explicit : ${m.explicit}"); + for (Artist a in m.artists) { + print("id : ${a.id}, name : ${a.name}"); + } + } + +} +