diff --git a/assets/Launcher.png b/assets/Launcher.png new file mode 100644 index 0000000..5b50799 Binary files /dev/null and b/assets/Launcher.png differ diff --git a/assets/splash.png b/assets/splash.png deleted file mode 100644 index 9dd962f..0000000 Binary files a/assets/splash.png and /dev/null differ diff --git a/lib/controllers/dialog_contact.dart b/lib/controllers/dialog_contact.dart index 501879f..7608b85 100644 --- a/lib/controllers/dialog_contact.dart +++ b/lib/controllers/dialog_contact.dart @@ -6,10 +6,13 @@ import '../consts/colors.dart'; import '../consts/text_style.dart'; class DialogHelper { - static void showLinkDialog({required String url}) { + static void showLinkDialog({ + required String url, + required String title, + }) { Get.defaultDialog( title: "Open Link", - middleText: "Click the button to contact the developer.", + middleText: title, backgroundColor: whiteColor, titleStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), middleTextStyle: const TextStyle(fontSize: 14), diff --git a/lib/controllers/player_controller.dart b/lib/controllers/player_controller.dart index 7be8fcf..edcdd08 100644 --- a/lib/controllers/player_controller.dart +++ b/lib/controllers/player_controller.dart @@ -18,38 +18,39 @@ class PlayerController extends GetxController { var max = 0.0.obs; var value = 0.0.obs; - late List data; + var isLoading = true.obs; + List data = []; @override void onInit() { super.onInit(); checkPermission(); loadSongs(); - audioPlayer.positionStream.listen((position) { if (audioPlayer.duration != null && position >= audioPlayer.duration!) { - _playNextSong(); + playNextSong(); } }); } - loadSongs() async { + Future loadSongs() async { var perm = await Permission.storage.request(); if (perm.isGranted) { var songs = await audioQuery.querySongs(); - data = songs; + data = songs.isNotEmpty ? songs : []; } else { print("Permission denied!"); } + isLoading(false); } - _playNextSong() { - if (playIndex.value < data.length - 1) { - playSong(data[playIndex.value + 1].uri, playIndex.value + 1); - } else { - playSong(data[0].uri, 0); - } - } + // _playNextSong() { + // if (playIndex.value < data.length - 1) { + // playSong(data[playIndex.value + 1].uri, playIndex.value + 1); + // } else { + // playSong(data[0].uri, 0); + // } + // } updatePosition() { audioPlayer.durationStream.listen((d) { @@ -90,10 +91,36 @@ class PlayerController extends GetxController { } } + void playNextSong() { + if (playIndex.value < data.length - 1) { + playSong(data[playIndex.value + 1].uri, playIndex.value + 1); + } else { + playSong(data[0].uri, 0); + } +} + +void playPreviousSong() { + if (playIndex.value > 0) { + playSong(data[playIndex.value - 1].uri, playIndex.value - 1); + } else { + playSong(data[data.length - 1].uri, data.length - 1); + } +} + + + pauseOrResume() { + if (audioPlayer.playing) { + audioPlayer.pause(); + isPlaying(false); + } else { + audioPlayer.play(); + isPlaying(true); + } + } + checkPermission() async { var perm = await Permission.storage.request(); - if (perm.isGranted) { - } else { + if (!perm.isGranted) { checkPermission(); } } diff --git a/lib/main.dart b/lib/main.dart index 0afa155..28881f2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'pages/albums_screen.dart'; import 'pages/home.dart'; -import 'pages/playlist_screen.dart'; import 'widgets/drawer.dart'; void main() { @@ -34,4 +32,4 @@ class MyApp extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/pages/albums_screen.dart b/lib/pages/albums_screen.dart index 60467e6..5383a25 100644 --- a/lib/pages/albums_screen.dart +++ b/lib/pages/albums_screen.dart @@ -38,9 +38,9 @@ class _AlbumsScreenState extends State { ), child: Scaffold( appBar: appBar(), - floatingActionButton: FloatBotton(controller: controller), - floatingActionButtonLocation: - FloatingActionButtonLocation.centerFloat, + // floatingActionButton: FloatBotton(controller: controller), + // floatingActionButtonLocation: + // FloatingActionButtonLocation.centerFloat, backgroundColor: Colors.transparent, body: Column( children: [ diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 0bc309b..245581a 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -7,7 +7,6 @@ import '../consts/colors.dart'; import '../consts/text_style.dart'; import '../controllers/player_controller.dart'; import '../widgets/custom_nav_bar.dart'; -import '../widgets/float_botton.dart'; import 'player.dart'; class Home extends StatefulWidget { @@ -39,8 +38,8 @@ class _HomeState extends State { ), child: Scaffold( appBar: appBar(), - floatingActionButton: FloatBotton(controller: controller), - floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, + // floatingActionButton: FloatBotton(controller: controller), + // floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, backgroundColor: Colors.transparent, body: Column( children: [ @@ -76,93 +75,54 @@ class _HomeState extends State { children: [ Container( margin: const EdgeInsets.only(bottom: 5), - child: Obx( - () => ListTile( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - title: Text( - snapshot.data![index].displayNameWOExt, - style: ourStyle( - family: bold, - size: 15, - ), + child: ListTile( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + title: Text( + snapshot.data![index].displayNameWOExt, + style: ourStyle( + family: bold, + size: 15, ), - subtitle: Text( - snapshot.data![index].artist ?? "Unknown", - style: ourStyle( - family: bold, - size: 12, - ), + ), + subtitle: Text( + snapshot.data![index].artist ?? "Unknown", + style: ourStyle( + family: bold, + size: 12, ), - leading: snapshot.data![index].id != null - ? QueryArtworkWidget( - artworkBorder: - BorderRadius.circular(12), - id: snapshot.data![index].id, - type: ArtworkType.AUDIO, - nullArtworkWidget: const Icon( - Icons.music_note, - color: whiteColor, - size: 50, - ), - ) - : const Icon( + ), + leading: snapshot.data![index].id != null + ? QueryArtworkWidget( + artworkBorder: + BorderRadius.circular(12), + id: snapshot.data![index].id, + type: ArtworkType.AUDIO, + nullArtworkWidget: const Icon( Icons.music_note, color: whiteColor, size: 50, ), - trailing: GestureDetector( - onTap: () { - if (controller.playIndex.value == - index) { - if (controller.isPlaying.value) { - controller.audioPlayer.pause(); - controller.isPlaying.value = false; - } else { - controller.audioPlayer.play(); - controller.isPlaying.value = true; - } - } else { - controller.playSong( - snapshot.data![index].uri, index); - } - }, - child: Container( - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.white.withOpacity(0.1), + ) + : const Icon( + Icons.music_note, + color: whiteColor, + size: 50, ), - child: controller.playIndex.value == - index && - controller.isPlaying.value - ? const Icon( - Icons.pause, - color: whiteColor, - size: 26, - ) - : const Icon( - Icons.play_arrow_rounded, - color: whiteColor, - size: 26, - ), - ), - ), - onTap: () { - controller.playSong( - snapshot.data![index].uri, - index, - ); - Get.to( - () => Player(data: snapshot.data!), - transition: Transition.downToUp, - fullscreenDialog: false, - duration: - const Duration(milliseconds: 700), - ); - }, - ), + onTap: () { + controller.playSong( + snapshot.data![index].uri, + index, + ); + Get.to( + () => Player(data: snapshot.data!), + transition: Transition.downToUp, + fullscreenDialog: false, + duration: + const Duration(milliseconds: 700), + ); + }, ), ), const Divider( @@ -179,6 +139,88 @@ class _HomeState extends State { }, ), ), + Container( + padding: const EdgeInsets.all(5), + margin: const EdgeInsets.only(left: 20, right: 20, top: 5), + decoration: BoxDecoration( + color: whiteColor.withOpacity(0.5), + borderRadius: BorderRadius.circular(20), + ), + width: double.infinity, + height: 70, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + onPressed: () async { + List songs = + await controller.audioQuery.querySongs( + ignoreCase: true, + orderType: OrderType.ASC_OR_SMALLER, + sortType: null, + uriType: UriType.EXTERNAL, + ); + Get.to( + () => Player(data: songs), + transition: Transition.downToUp, + fullscreenDialog: false, + duration: const Duration(milliseconds: 700), + ); + }, + icon: SvgPicture.asset( + 'assets/icons/waves.svg', + width: 90, + colorFilter: + const ColorFilter.mode(whiteColor, BlendMode.srcIn), + ), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + onPressed: () { + controller.playPreviousSong(); + }, + icon: const Icon( + Icons.skip_previous_rounded, + color: whiteColor, + size: 40, + ), + ), + SizedBox(width: 25), + Obx( + () => IconButton( + onPressed: () { + controller.pauseOrResume(); + }, + icon: Icon( + controller.isPlaying.value + ? Icons.pause + : Icons.play_arrow_rounded, + color: whiteColor, + size: 45, + ), + ), + ), + SizedBox(width: 25), + IconButton( + onPressed: () { + controller.playNextSong(); + }, + icon: const Icon( + Icons.skip_next_rounded, + color: whiteColor, + size: 40, + ), + ), + ], + ), + ], + ), + ), + SizedBox(height: 30), ], ), ), @@ -187,63 +229,62 @@ class _HomeState extends State { AppBar appBar() { return AppBar( - leading: IconButton( + leading: IconButton( + onPressed: () { + setState(() { + if (isDrawerOpen) { + xOffset = 0; + yOffset = 0; + isDrawerOpen = false; + } else { + xOffset = 290; + yOffset = 80; + isDrawerOpen = true; + } + }); + }, + icon: isDrawerOpen + ? const Icon( + Icons.arrow_back_ios_new_rounded, + color: iconsColor, + ) + : SvgPicture.asset( + width: 20, + height: 20, + 'assets/icons/drawer.svg', + colorFilter: + const ColorFilter.mode(iconsColor, BlendMode.srcIn), + ), + ), + title: Text( + 'Audira', + style: TextStyle( + fontSize: 30, + color: whiteColor, + fontWeight: FontWeight.bold, + fontFamily: 'bold', + ), + ), + actions: [ + IconButton( onPressed: () { - setState(() { - if (isDrawerOpen) { - xOffset = 0; - yOffset = 0; - isDrawerOpen = false; - } else { - xOffset = 290; - yOffset = 80; - isDrawerOpen = true; - } - }); + Get.snackbar( + "In Progress", + "This feature is currently being developed. Stay tuned!", + colorText: Colors.white, + icon: const Icon(Icons.code_rounded, color: Colors.green), + isDismissible: true, + animationDuration: const Duration(milliseconds: 400), + ); }, - icon: isDrawerOpen - ? const Icon( - Icons.arrow_back_ios_new_rounded, - color: iconsColor, - ) - : SvgPicture.asset( - width: 20, - height: 20, - 'assets/icons/drawer.svg', - colorFilter: - const ColorFilter.mode(iconsColor, BlendMode.srcIn), - ), - ), - title: Text( - 'Audira', - style: TextStyle( - fontSize: 30, - color: whiteColor, - fontWeight: FontWeight.bold, - fontFamily: 'bold', + icon: SvgPicture.asset( + width: 22, + height: 22, + 'assets/icons/setting.svg', + colorFilter: const ColorFilter.mode(iconsColor, BlendMode.srcIn), ), - ), - actions: [ - IconButton( - onPressed: () { - Get.snackbar( - "In Progress", - "This feature is currently being developed. Stay tuned!", - colorText: Colors.white, - icon: const Icon(Icons.code_rounded, color: Colors.green), - isDismissible: true, - animationDuration: const Duration(milliseconds: 400), - ); - }, - icon: SvgPicture.asset( - width: 22, - height: 22, - 'assets/icons/setting.svg', - colorFilter: - const ColorFilter.mode(iconsColor, BlendMode.srcIn), - ), - ) - ], - ); + ) + ], + ); } } diff --git a/lib/pages/player.dart b/lib/pages/player.dart index 5da297f..1a0bfe4 100644 --- a/lib/pages/player.dart +++ b/lib/pages/player.dart @@ -84,6 +84,7 @@ class Player extends StatelessWidget { ), Expanded( child: Container( + padding: const EdgeInsets.only(left: 20, right: 20), alignment: Alignment.center, child: Obx( () => Column( @@ -200,4 +201,4 @@ class Player extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/pages/playlist_screen.dart b/lib/pages/playlist_screen.dart index 8a35d6a..18916f5 100644 --- a/lib/pages/playlist_screen.dart +++ b/lib/pages/playlist_screen.dart @@ -38,9 +38,9 @@ class _PlaylistScreenState extends State { ), child: Scaffold( appBar: appBar(), - floatingActionButton: FloatBotton(controller: controller), - floatingActionButtonLocation: - FloatingActionButtonLocation.centerFloat, + // floatingActionButton: FloatBotton(controller: controller), + // floatingActionButtonLocation: + // FloatingActionButtonLocation.centerFloat, backgroundColor: Colors.transparent, body: Column( children: [ diff --git a/lib/widgets/custom_nav_bar.dart b/lib/widgets/custom_nav_bar.dart index 5ff5039..4c7b423 100644 --- a/lib/widgets/custom_nav_bar.dart +++ b/lib/widgets/custom_nav_bar.dart @@ -2,10 +2,8 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../consts/colors.dart'; +import '../controllers/dialog_contact.dart'; import '../controllers/nav_bar_controller.dart'; -import '../pages/albums_screen.dart'; -import '../pages/home.dart'; -import '../pages/playlist_screen.dart'; class CustomNavBar extends StatelessWidget { const CustomNavBar({ @@ -19,7 +17,7 @@ class CustomNavBar extends StatelessWidget { final containerWidth = screenWidth * 0.3; return Container( - padding: EdgeInsets.only(left: 25, top: 15, bottom: 15), + padding: EdgeInsets.only(left: 15, top: 15, bottom: 15), color: Colors.transparent, child: SingleChildScrollView( scrollDirection: Axis.horizontal, @@ -29,8 +27,18 @@ class CustomNavBar extends StatelessWidget { GestureDetector( onTap: () { navBarController.setSelectedIndex(0); - Get.to( - () => PlaylistScreen(), + Get.snackbar( + "Playlists", + "This section is currently being developed. Stay tuned for updates!", + colorText: Colors.white, + isDismissible: true, + animationDuration: const Duration(milliseconds: 400), + onTap: (snack) { + DialogHelper.showLinkDialog( + url: 'https://linktr.ee/userahmed', + title: 'For updates, contact the developer here.', + ); + }, ); }, child: Obx(() { @@ -62,7 +70,6 @@ class CustomNavBar extends StatelessWidget { GestureDetector( onTap: () { navBarController.setSelectedIndex(1); - Get.to(() => Home()); }, child: Obx(() { return Container( @@ -93,7 +100,19 @@ class CustomNavBar extends StatelessWidget { GestureDetector( onTap: () { navBarController.setSelectedIndex(2); - Get.to(() => AlbumsScreen()); + Get.snackbar( + "Albums", + "This section is currently being developed. Stay tuned for updates!", + colorText: Colors.white, + isDismissible: true, + animationDuration: const Duration(milliseconds: 400), + onTap: (snack) { + DialogHelper.showLinkDialog( + url: 'https://linktr.ee/userahmed', + title: 'For updates, contact the developer here.', + ); + }, + ); }, child: Obx(() { return Container( diff --git a/lib/widgets/drawer.dart b/lib/widgets/drawer.dart index 9338309..edb0d02 100644 --- a/lib/widgets/drawer.dart +++ b/lib/widgets/drawer.dart @@ -91,6 +91,7 @@ class _DrawerScreenState extends State _buildAnimatedRow(0, 'Developer', Icons.person_outline, () { DialogHelper.showLinkDialog( url: 'https://linktr.ee/userahmed', + title: 'Click the button to contact the developer.', ); }), const SizedBox(height: 20), @@ -109,7 +110,7 @@ class _DrawerScreenState extends State _buildAnimatedRow(2, 'Stats', Icons.bar_chart_rounded, () { Get.snackbar( "In Progress", - "This feature is currently being developed. Stay tuned!", + "This feature is currently being developed. Stay tuned for updates!", colorText: Colors.white, icon: const Icon(Icons.code_rounded, color: Colors.green), isDismissible: true, @@ -120,7 +121,7 @@ class _DrawerScreenState extends State _buildAnimatedRow(3, 'Favorites', Icons.favorite_border, () { Get.snackbar( "In Progress", - "This feature is currently being developed. Stay tuned!", + "This feature is currently being developed. Stay tuned for updates!", colorText: Colors.white, icon: const Icon(Icons.code_rounded, color: Colors.green), isDismissible: true,