From e1734c58668d4bd09a9a3362ce0e2d79d9a430fe Mon Sep 17 00:00:00 2001 From: Anand kumar Date: Thu, 22 Jun 2023 19:11:02 +0530 Subject: [PATCH 1/6] Discover content selecter added in settings --- lib/main.dart | 3 +- lib/models/album.dart | 10 -- lib/models/artist.dart | 6 + lib/models/media_Item_builder.dart | 46 +++-- lib/models/playlist.dart | 12 -- lib/models/quick_picks.dart | 11 +- lib/services/music_service.dart | 39 +++- lib/services/nav_parser.dart | 118 +++++++++--- lib/ui/player/player_controller.dart | 15 ++ lib/ui/screens/home_screen.dart | 144 ++++++++------- lib/ui/screens/home_screen_controller.dart | 113 ++++++++++-- lib/ui/screens/settings_screen.dart | 170 +++++++++++++----- .../screens/settings_screen_controller.dart | 9 + lib/ui/widgets/quickpickswidget.dart | 2 +- pubspec.lock | 41 ----- pubspec.yaml | 3 +- .../flutter/generated_plugin_registrant.cc | 3 - windows/flutter/generated_plugins.cmake | 1 - 18 files changed, 499 insertions(+), 247 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 10047d50..f7a7be48 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -79,7 +79,8 @@ void _setAppInitPrefs() { "cacheSongs": false, "skipSilenceEnabled": false, 'streamingQuality': 1, - 'themePrimaryColor': 4278199603 + 'themePrimaryColor': 4278199603, + 'discoverContentType': "QP", }); } } diff --git a/lib/models/album.dart b/lib/models/album.dart index 956da987..866e70bd 100644 --- a/lib/models/album.dart +++ b/lib/models/album.dart @@ -4,16 +4,6 @@ class AlbumContent { AlbumContent({required this.title, required this.albumList}); final String title; final List albumList; - factory AlbumContent.fromJson(Map json) => AlbumContent( - title: json["title"], - albumList: (json["contents"]) - .map((item) { - if (item.containsKey('browseId') && !item.containsKey('videoId')) { - return Album.fromJson(item); - } - }) - .whereType() - .toList()); } class Album { diff --git a/lib/models/artist.dart b/lib/models/artist.dart index 384a396d..8e17df5a 100644 --- a/lib/models/artist.dart +++ b/lib/models/artist.dart @@ -34,3 +34,9 @@ class Artist { ] }; } + +class ArtistContent{ + ArtistContent(this.content,{this.title = "Artists"}); + final List content; + final String title; +} diff --git a/lib/models/media_Item_builder.dart b/lib/models/media_Item_builder.dart index e22223f1..9f568bf7 100644 --- a/lib/models/media_Item_builder.dart +++ b/lib/models/media_Item_builder.dart @@ -6,43 +6,50 @@ import 'package:harmonymusic/models/thumbnail.dart'; class MediaItemBuilder { static MediaItem fromJson(dynamic json, {String? url}) { String artistName = ''; - for (dynamic artist in json['artists']) { - artistName += "${artist['name']} • "; + if (json['artists'] != null) { + for (dynamic artist in json['artists']) { + artistName += "${artist['name']} • "; + } } - + return MediaItem( id: json["videoId"], title: json["title"], - duration:json['duration']!=null?Duration(seconds:json['duration']):toDuration(json['length'] ), - album: json['album']!=null ? json['album']['name']:null , - artist: artistName==""?artistName: artistName.substring(0,artistName.length-2), + duration: json['duration'] != null + ? Duration(seconds: json['duration']) + : toDuration(json['length']), + album: json['album'] != null ? json['album']['name'] : null, + artist: artistName == "" + ? artistName + : artistName.substring(0, artistName.length - 2), artUri: Uri.parse(Thumbnail(json["thumbnails"][0]['url']).high), extras: { 'url': json['url'] ?? url, 'length': json['length'], 'album': json['album'], 'artists': json['artists'], - 'date':json['date'] + 'date': json['date'] }); } -static Duration? toDuration(String? time){ - - if(time == null){ + static Duration? toDuration(String? time) { + if (time == null) { return null; } int sec = 0; final splitted = time.split(":"); - if(splitted.length==3){ - sec += int.parse(splitted[0])*3600 + int.parse(splitted[1])*60+int.parse(splitted[2]); - }else if(splitted.length ==2){ - sec += int.parse(splitted[0])*60+int.parse(splitted[1]); - }else if(splitted.length ==1){ - sec+=int.parse(splitted[0]); + if (splitted.length == 3) { + sec += int.parse(splitted[0]) * 3600 + + int.parse(splitted[1]) * 60 + + int.parse(splitted[2]); + } else if (splitted.length == 2) { + sec += int.parse(splitted[0]) * 60 + int.parse(splitted[1]); + } else if (splitted.length == 1) { + sec += int.parse(splitted[0]); } return Duration(seconds: sec); - } + } static Map toJson(MediaItem mediaItem) => { "videoId": mediaItem.id, @@ -50,8 +57,9 @@ static Duration? toDuration(String? time){ 'album': mediaItem.extras!['album'], 'artists': mediaItem.extras!['artists'], 'length': mediaItem.extras!['length'], - 'duration': mediaItem.duration!=null? mediaItem.duration!.inSeconds:null, - 'date':mediaItem.extras!['date'], + 'duration': + mediaItem.duration != null ? mediaItem.duration!.inSeconds : null, + 'date': mediaItem.extras!['date'], 'thumbnails': [ {'url': mediaItem.artUri.toString()} ], diff --git a/lib/models/playlist.dart b/lib/models/playlist.dart index e5dbebea..f7a4fa6a 100644 --- a/lib/models/playlist.dart +++ b/lib/models/playlist.dart @@ -4,18 +4,6 @@ class PlaylistContent { PlaylistContent({required this.title, required this.playlistList}); final String title; final List playlistList; - factory PlaylistContent.fromJson(Map json) => - PlaylistContent( - title: json["title"], - playlistList: (json["contents"]) - .map((item) { - if (item.containsKey('playlistId') && - !item.containsKey('videoId')) { - return Playlist.fromJson(item); - } - }) - .whereType() - .toList()); } class Playlist { diff --git a/lib/models/quick_picks.dart b/lib/models/quick_picks.dart index a6a39845..7a2e26c3 100644 --- a/lib/models/quick_picks.dart +++ b/lib/models/quick_picks.dart @@ -1,10 +1,7 @@ import 'package:audio_service/audio_service.dart'; -import 'package:harmonymusic/models/media_Item_builder.dart'; - -class QuickPicks{ - QuickPicks(this.songList); +class QuickPicks { + QuickPicks(this.songList, {this.title = "Discover"}); List songList; - - factory QuickPicks.fromJson(Map json)=>QuickPicks((json['contents']).map((item)=>MediaItemBuilder.fromJson(item)).toList()); -} \ No newline at end of file + final String title; +} diff --git a/lib/services/music_service.dart b/lib/services/music_service.dart index d8a33dd7..5f4542de 100644 --- a/lib/services/music_service.dart +++ b/lib/services/music_service.dart @@ -155,13 +155,31 @@ class MusicServices extends getx.GetxService { return home; } + Future>> getCharts({String? countryCode}) async { + final List> charts = []; + final data = Map.from(_context); + + data['browseId'] = 'FEmusic_charts'; + if(countryCode!=null){ + data['formData']= {'selectedValues': [countryCode]}; + } + final response = (await _sendRequest('browse', data)).data; + final results = nav(response,single_column_tab+section_list); + results.removeAt(0); + for(dynamic result in results){ + charts.add(parseChartsItem(result)); + } + + return charts; + } + Future> getWatchPlaylist( {String videoId = "", String? playlistId, int limit = 25, bool radio = false, bool shuffle = false, - String? additionalParamsNext}) async { + String? additionalParamsNext,bool onlyRelated = false}) async { final data = Map.from(_context); data['enablePersistentPlaylistPanel'] = true; data['isAudioOnly'] = true; @@ -210,6 +228,12 @@ class MusicServices extends getx.GetxService { lyricsBrowseId = getTabBrowseId(watchNextRenderer, 1); relatedBrowseId = getTabBrowseId(watchNextRenderer, 2); + if(onlyRelated){ + return { + 'lyrics': lyricsBrowseId, + 'related': relatedBrowseId, + }; + } results.addAll(nav(watchNextRenderer, [ ...tab_content, @@ -250,6 +274,17 @@ class MusicServices extends getx.GetxService { }; } + dynamic getContentRelatedToSong(String videoId) async { + final params = await getWatchPlaylist(videoId: videoId,onlyRelated: true); + final data = Map.from(_context); + data['browseId'] = params['related']; + final response = (await _sendRequest('browse', data)).data; + final sections = nav(response, ['contents'] + section_list); + final x= parseMixedContent(sections); + return x; + } + + Future> getPlaylistOrAlbumSongs( {String? playlistId, String? albumId, @@ -399,7 +434,7 @@ class MusicServices extends getx.GetxService { .url .toString(), streamUriList - .firstWhere((element) => GetPlatform.isWindows ? (element.tag == 140):(element.tag == 251) || element.tag == 140) + .firstWhere((element) => (element.tag == 251) || element.tag == 140) .url .toString() ]; diff --git a/lib/services/nav_parser.dart b/lib/services/nav_parser.dart index c47808ae..c1790fd1 100644 --- a/lib/services/nav_parser.dart +++ b/lib/services/nav_parser.dart @@ -152,7 +152,7 @@ List> parseMixedContent(List rows) { noneIfAbsent: true, funName: "mixed1"); if (pageType == null) { if (nav(data, navigation_watch_playlist_id) != null) { - content = parseWatchPlaylistHome(data); + // content = parseWatchPlaylistHome(data); } else { content = parseSong(data); } @@ -203,7 +203,7 @@ dynamic parseSingle(dynamic result) { }); } -Map parseSong(Map result) { +MediaItem parseSong(Map result) { //inspect(result); var song = { 'title': nav(result, title_text), @@ -214,7 +214,7 @@ Map parseSong(Map result) { }; song.addAll(parseSongRuns(result['subtitle']['runs'])); - return song; + return MediaItemBuilder.fromJson(song); } Map parseSongRuns(List runs) { @@ -262,7 +262,7 @@ Map parseSongRuns(List runs) { return parsed; } -dynamic parseAlbum(Map result, {bool reqAlbumObj = true}) { +Album parseAlbum(Map result, {bool reqAlbumObj = true}) { final List runs = nav(result, ['subtitle', 'runs']); final Map artistInfo = parseSongRuns(runs); Map albumMap = { @@ -272,21 +272,18 @@ dynamic parseAlbum(Map result, {bool reqAlbumObj = true}) { //'isExplicit': nav(result, subtitle_badge_label, noneIfAbsent: true) != null, }; albumMap.addAll(artistInfo); - if (reqAlbumObj) { - return Album.fromJson(albumMap); - } - return albumMap; + return Album.fromJson(albumMap); } -Map parseRelatedArtist(Map data) { - return { - 'title': nav(data, title_text), +Artist parseRelatedArtist(Map data) { + return Artist.fromJson({ + 'artist': nav(data, title_text), 'browseId': nav(data, n_title + navigation_browse_id), 'thumbnails': nav(data, thumbnail_renderer), - }; + }); } -Map parsePlaylist(Map data) { +Playlist parsePlaylist(Map data) { //inspect(data); Map playlist = { 'title': nav(data, title_text), @@ -304,7 +301,7 @@ Map parsePlaylist(Map data) { } } - return playlist; + return Playlist.fromJson(playlist); } List parseSongArtistsRuns(List runs) { @@ -321,7 +318,7 @@ List parseSongArtistsRuns(List runs) { return artists; } -Map parseSongFlat(Map data) { +MediaItem parseSongFlat(Map data) { //print(data); List> columns = []; for (int i = 0; i < data['flexColumns'].length; i++) { @@ -346,7 +343,7 @@ Map parseSongFlat(Map data) { } } - return song; + return MediaItemBuilder.fromJson(song); } List? parseSongArtists(Map data, int index) { @@ -822,10 +819,12 @@ Map parseArtistContents(List results) { final browseEndpoint = nav( result, ['musicShelfRenderer', 'bottomEndpoint', 'browseEndpoint']); - navigationEndpoints[title] = browseEndpoint!=null?{ - 'browseId': browseEndpoint['browseId'], - 'params': browseEndpoint['params'] - }:null; + navigationEndpoints[title] = browseEndpoint != null + ? { + 'browseId': browseEndpoint['browseId'], + 'params': browseEndpoint['params'] + } + : null; } else if (result.containsKey('musicCarouselShelfRenderer')) { final browseEndpoint = nav(result, [ 'musicCarouselShelfRenderer', @@ -837,7 +836,7 @@ Map parseArtistContents(List results) { 'browseEndpoint' ]); - if(browseEndpoint==null) continue; + if (browseEndpoint == null) continue; final title = nav(result, [ 'musicCarouselShelfRenderer', @@ -847,7 +846,6 @@ Map parseArtistContents(List results) { 'runs', 0 ])['text']; - navigationEndpoints[title] = { 'browseId': browseEndpoint['browseId'], @@ -866,3 +864,79 @@ dynamic parseContentList(results, Function parseFunc) { return contents; } + +Map parseChartsItem(dynamic result) { + final contentList = nav(result, ['musicCarouselShelfRenderer', 'contents']); + final String category = nav(result, [ + 'musicCarouselShelfRenderer', + 'header', + 'musicCarouselShelfBasicHeaderRenderer', + 'title', + ...run_text + ]); + if (category.contains('videos')) { + final videoList = contentList + .map((video) => parseVideo(video['musicTwoRowItemRenderer'])) + .toList(); + return {'title': category, 'contents': videoList}; + } else if (category.contains('artists')) { + final artists = contentList + .map((artist) => + parseChartsArtist(artist['musicResponsiveListItemRenderer'])) + .toList(); + return {'title': category, 'contents': artists}; + } else if (category.contains('Genres')) { + final playlists = contentList + .map((playlist) => parsePlaylist(playlist['musicTwoRowItemRenderer'])) + .toList(); + return { + 'title':category, + 'contents': playlists}; + } else if (category.contains('Trending')) { + final videoList = contentList + .map((video) => + parseChartsTrending(video['musicResponsiveListItemRenderer'])).whereType() + .toList(); + return { + 'title':category, + 'contents': videoList}; + } + return {}; +} + +Artist parseChartsArtist(dynamic data) { + final subscribers = getFlexColumnItem(data, 1); + dynamic subs; + if (subscribers.isNotEmpty) { + subs = nav(subscribers, text_run_text).split(' ')[0]; + } + + final parsed = { + 'artist': nav(getFlexColumnItem(data, 0), text_run_text), + 'browseId': nav(data, navigation_browse_id), + 'subscribers': subs, + 'thumbnails': nav(data, thumbnails), + }; + + return Artist.fromJson(parsed); +} + +MediaItem? parseChartsTrending(dynamic data) { + final flex_0 = getFlexColumnItem(data, 0); + final artists = parseSongArtists(data, 1); + + final video = { + 'title': nav(flex_0, text_run_text), + 'videoId': nav( + flex_0, + text_run + navigation_video_id, + ), + 'playlistId': nav(flex_0, text_run + navigation_playlist_id), + 'artists': artists, + 'thumbnails': nav(data, thumbnails), + }; + if(video['videoId']==null){ + return null; + } + return MediaItemBuilder.fromJson(video); +} diff --git a/lib/ui/player/player_controller.dart b/lib/ui/player/player_controller.dart index b40cd764..ed31cfa1 100644 --- a/lib/ui/player/player_controller.dart +++ b/lib/ui/player/player_controller.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/media_Item_builder.dart'; +import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; import 'package:harmonymusic/ui/screens/playlistnalbum_screen_controller.dart'; import 'package:hive/hive.dart'; import 'package:audio_service/audio_service.dart'; @@ -187,6 +188,11 @@ class PlayerController extends GetxController { if (playlistid != null) { _playerPanelCheck(); await _audioHandler.customAction("playByIndex", {"index": 0}); + } else { + if (Hive.box("AppPrefs").get("discoverContentType") == "BOLI") { + Get.find() + .changeDiscoverContent("BOLI", songId: mediaItem!.id); + } } }); @@ -205,6 +211,15 @@ class PlayerController extends GetxController { //open player pane,set current song and push first song into playing list, final init = _initFlagForPlayer; currentSong.value = mediaItems[index]; + + //for changing home content based on last interation + Future.delayed(const Duration(seconds: 3), () { + if (Hive.box("AppPrefs").get("discoverContentType") == "BOLI") { + Get.find() + .changeDiscoverContent("BOLI", songId: mediaItems[index].id); + } + }); + _playerPanelCheck(); !init ? await _audioHandler.updateQueue(mediaItems) diff --git a/lib/ui/screens/home_screen.dart b/lib/ui/screens/home_screen.dart index db94fa88..246a2a49 100644 --- a/lib/ui/screens/home_screen.dart +++ b/lib/ui/screens/home_screen.dart @@ -130,76 +130,79 @@ class Body extends StatelessWidget { if (homeScreenController.tabIndex.value == 0) { return Padding( padding: const EdgeInsets.only(left: 5.0), - child: SingleChildScrollView( - padding: EdgeInsets.only(bottom: 90, top: topPadding), - child: homeScreenController.networkError.isTrue - ? SizedBox( - height: MediaQuery.of(context).size.height - 180, - child: Column( - children: [ - Align( - alignment: Alignment.topLeft, - child: Text( - "Home", - style: Theme.of(context).textTheme.titleLarge, + child: Obx( + () => SingleChildScrollView( + padding: EdgeInsets.only(bottom: 90, top: topPadding), + child: homeScreenController.networkError.isTrue + ? SizedBox( + height: MediaQuery.of(context).size.height - 180, + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + "Home", + style: Theme.of(context).textTheme.titleLarge, + ), ), - ), - Expanded( - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Oops Network Error!", - style: - Theme.of(context).textTheme.titleMedium, - ), - const SizedBox( - height: 10, - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 15, vertical: 10), - decoration: BoxDecoration( - color: Theme.of(context) - .textTheme - .titleLarge! - .color, - borderRadius: BorderRadius.circular(10)), - child: InkWell( - onTap: () { - homeScreenController.init(); - }, - child: Text( - "Retry!", - style: TextStyle( - color: Theme.of(context).canvasColor), + Expanded( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Oops Network Error!", + style: + Theme.of(context).textTheme.titleMedium, + ), + const SizedBox( + height: 10, + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + decoration: BoxDecoration( + color: Theme.of(context) + .textTheme + .titleLarge! + .color, + borderRadius: + BorderRadius.circular(10)), + child: InkWell( + onTap: () { + homeScreenController.init(); + }, + child: Text( + "Retry!", + style: TextStyle( + color: + Theme.of(context).canvasColor), + ), ), ), - ), - ]), - ), - ) - ], - ), - ) - : Obx(() { - return Column( - children: homeScreenController.isContentFetched.value - ? (homeScreenController.homeContentList).map((element) { - if (element.runtimeType.toString() == - "QuickPicks") { - //return contentWidget(); - return QuickPicksWidget(content: element); - } else { - return ContentListWidget( - content: element, - ); - } - }).toList() - : [const HomeShimmer()], - ); - }), + ]), + ), + ) + ], + ), + ) + : Obx(() { + return Column( + children: homeScreenController.isContentFetched.value + ? [ + Obx(() => QuickPicksWidget( + content: + homeScreenController.quickPicks.value)), + ...getWidgetList( + homeScreenController.middleContent), + ...getWidgetList( + homeScreenController.fixedContent, + ) + ] + : [const HomeShimmer()], + ); + }), + ), ), ); } else if (homeScreenController.tabIndex.value == 1) { @@ -265,6 +268,13 @@ class Body extends StatelessWidget { ); } } + + List getWidgetList(dynamic list) { + return list + .map((content) => ContentListWidget(content: content)) + .whereType() + .toList(); + } } class LibraryArtistWidget extends StatelessWidget { diff --git a/lib/ui/screens/home_screen_controller.dart b/lib/ui/screens/home_screen_controller.dart index 20e3921e..4d8ec997 100644 --- a/lib/ui/screens/home_screen_controller.dart +++ b/lib/ui/screens/home_screen_controller.dart @@ -1,28 +1,78 @@ - +import 'package:audio_service/audio_service.dart'; import 'package:get/get.dart'; import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/album.dart'; import 'package:harmonymusic/models/playlist.dart'; import 'package:harmonymusic/models/quick_picks.dart'; import 'package:harmonymusic/services/music_service.dart'; +import 'package:hive/hive.dart'; class HomeScreenController extends GetxController { final MusicServices _musicServices = Get.find(); final isContentFetched = false.obs; - final homeContentList = [].obs; final tabIndex = 0.obs; final networkError = false.obs; + final quickPicks = QuickPicks([]).obs; + final middleContent = [].obs; + final fixedContent = [].obs; HomeScreenController() { init(); } Future init() async { + final box = Hive.box("AppPrefs"); + String contentType = box.get("discoverContentType") as String; + networkError.value = false; try { + List middleContentTemp =[]; final homeContentListMap = await _musicServices.getHome(limit: 10); - _setHomeContentList(homeContentListMap); + if (contentType == "TR") { + final index = homeContentListMap + .indexWhere((element) => element['title'] == "Trending"); + if (index != -1 && index != 0) { + quickPicks.value = QuickPicks(List.from(homeContentListMap[index]["contents"]),title: "Trending"); + } else if (index == -1) { + List charts = await _musicServices.getCharts(); + final con = + charts.length == 4 ? charts.removeAt(3) : charts.removeAt(2); + quickPicks.value = QuickPicks(List.from(con["contents"]), + title: con['title']); + middleContentTemp.addAll(charts); + } + } else if (contentType == "TMV") { + final index = homeContentListMap + .indexWhere((element) => element['title'] == "Top music videos"); + if (index != -1 && index != 0) { + final con = homeContentListMap.removeAt(index); + quickPicks.value = QuickPicks(List.from(con["contents"])); + } else if (index == -1) { + List charts = await _musicServices.getCharts(); + quickPicks.value = QuickPicks( + List.from(charts[0]["contents"]), + title: charts[0]["title"]); + middleContentTemp.addAll(charts.sublist(1)); + } + } else if (contentType == "BOLI") { + final songId = box.get("recentSongId"); + if (songId != null) { + final rel = (await _musicServices.getContentRelatedToSong(songId)); + final con = rel.removeAt(0); + quickPicks.value = QuickPicks(List.from(con["contents"])); + middleContentTemp.addAll(rel); + } + } else if (quickPicks.value.songList.isEmpty) { + final index = homeContentListMap + .indexWhere((element) => element['title'] == "Quick picks"); + final con = homeContentListMap.removeAt(index); + quickPicks.value = QuickPicks(List.from(con["contents"]), + title: "Quick Pics"); + } + middleContent.value = _setContentList(middleContentTemp); + fixedContent.value = _setContentList(homeContentListMap); + isContentFetched.value = true; - // ignore: unused_catch_stack + // ignore: unused_catch_stack } on NetworkError catch (_, e) { printERROR("Home Content not loaded due to ${_.message}"); await Future.delayed(const Duration(seconds: 1)); @@ -30,25 +80,56 @@ class HomeScreenController extends GetxController { } } - void _setHomeContentList(List contents) { + List _setContentList( + List contents, + ) { + List contentTemp = []; for (var content in contents) { - if ((content["title"]).contains("Videos") || - (content["title"]).contains("videos") || - content["contents"][1] == null) { - } else if (content["title"] == "Quick picks") { - homeContentList.add(QuickPicks.fromJson(content)); - } else if (content["contents"][0].containsKey("playlistId")) { - final tmp = PlaylistContent.fromJson(content); + if ((content["contents"][0]).runtimeType == Playlist) { + final tmp = PlaylistContent( + playlistList: List.from(content["contents"]), + title: content["title"]); if (tmp.playlistList.length >= 2) { - homeContentList.add(tmp); + contentTemp.add(tmp); } - } else if (content["contents"][0].containsKey("browseId")) { - final tmp = AlbumContent.fromJson(content); + } else if ((content["contents"][0]).runtimeType == Album) { + final tmp = AlbumContent( + albumList: List.from(content["contents"]), + title: content["title"]); if (tmp.albumList.length >= 2) { - homeContentList.add(tmp); + contentTemp.add(tmp); + } + } + } + return contentTemp; + } + + Future changeDiscoverContent(dynamic val, {String? songId}) async { + QuickPicks? quickPicks_; + if (val == 'QP') { + final homeContentListMap = await _musicServices.getHome(limit: 3); + quickPicks_ = QuickPicks( + List.from(homeContentListMap[0]["contents"]), + title: homeContentListMap[0]["title"]); + } else if (val == "TMV" || val == 'TR') { + final charts = await _musicServices.getCharts(); + final index =val == "TMV" ?0: charts.length == 4 ?3:2; + quickPicks_ = + QuickPicks(List.from(charts[index]["contents"]), title: charts[index]["title"]); + } else { + songId ??= Hive.box("AppPrefs").get("recentSongId"); + if (songId != null) { + final value = await _musicServices.getContentRelatedToSong(songId); + middleContent.value = _setContentList(value); + if ((value[0]['title']).contains("like")) { + quickPicks_ = QuickPicks(List.from(value[0]["contents"])); } + Hive.box("AppPrefs").put("recentSongId", songId); } } + if (quickPicks_ == null) return; + + quickPicks.value = quickPicks_; } void onTabSelected(int index) { diff --git a/lib/ui/screens/settings_screen.dart b/lib/ui/screens/settings_screen.dart index 86197589..e6d50a43 100644 --- a/lib/ui/screens/settings_screen.dart +++ b/lib/ui/screens/settings_screen.dart @@ -52,6 +52,24 @@ class SettingsScreen extends StatelessWidget { builder: (context) => const ThemeSelectorDialog(), ), ), + ListTile( + contentPadding: const EdgeInsets.only(left: 5, right: 10), + title: const Text("Set Discover content"), + subtitle: Obx(() => Text( + settingsController.discoverContentType.value == "QP" + ? "Quick Pics" + : settingsController.discoverContentType.value == "TMV" + ? "Top Music Videos" + : settingsController.discoverContentType.value == + "TR" + ? "Trending" + : "Based on last interaction", + style: Theme.of(context).textTheme.bodyMedium)), + onTap: () => showDialog( + context: context, + builder: (context) => const DiscoverContentSelectorDialog(), + ), + ), ListTile( contentPadding: const EdgeInsets.only(left: 5, right: 10), title: const Text("Cache songs"), @@ -95,32 +113,38 @@ class SettingsScreen extends StatelessWidget { ), ), ), - GetPlatform.isAndroid? Obx( - () => ListTile( - contentPadding: const EdgeInsets.only(left: 5, right: 10), - title: const Text("Ignore battery optimization"), - onTap: settingsController - .isIgnoringBatteryOptimizations.isFalse - ? settingsController.enableIgnoringBatteryOptimizations - : null, - subtitle: Obx(() => RichText( - text: TextSpan( - text: - "Status: ${settingsController.isIgnoringBatteryOptimizations.isTrue ? "Enabled" : "Disblaled"}\n", - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(fontWeight: FontWeight.bold), - children: [ - TextSpan( + GetPlatform.isAndroid + ? Obx( + () => ListTile( + contentPadding: + const EdgeInsets.only(left: 5, right: 10), + title: const Text("Ignore battery optimization"), + onTap: settingsController + .isIgnoringBatteryOptimizations.isFalse + ? settingsController + .enableIgnoringBatteryOptimizations + : null, + subtitle: Obx(() => RichText( + text: TextSpan( text: - "If you are facing notification issues or playback stopped by system optimization, please enable this option", - style: Theme.of(context).textTheme.bodyMedium), - ], - ), - )), - ), - ):const SizedBox.shrink(), + "Status: ${settingsController.isIgnoringBatteryOptimizations.isTrue ? "Enabled" : "Disblaled"}\n", + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontWeight: FontWeight.bold), + children: [ + TextSpan( + text: + "If you are facing notification issues or playback stopped by system optimization, please enable this option", + style: Theme.of(context) + .textTheme + .bodyMedium), + ], + ), + )), + ), + ) + : const SizedBox.shrink(), ListTile( contentPadding: const EdgeInsets.only(left: 5, right: 10), title: const Text("Github"), @@ -177,9 +201,10 @@ class ThemeSelectorDialog extends StatelessWidget { ), ), radioWidget( - label: "Dynamic", - controller: settingsController, - value: ThemeType.dynamic), + label: "Dynamic", + controller: settingsController, + value: ThemeType.dynamic, + ), radioWidget( label: "System default", controller: settingsController, @@ -205,21 +230,80 @@ class ThemeSelectorDialog extends StatelessWidget { ), ); } +} - Widget radioWidget( - {required String label, - required SettingsScreenController controller, - required value}) { - return Obx(() => ListTile( - visualDensity: const VisualDensity(vertical: -4), - onTap: () { - controller.onThemeChange(value); - }, - leading: Radio( - value: value, - groupValue: controller.themeModetype.value, - onChanged: controller.onThemeChange), - title: Text(label), - )); +class DiscoverContentSelectorDialog extends StatelessWidget { + const DiscoverContentSelectorDialog({super.key}); + + @override + Widget build(BuildContext context) { + final settingsController = Get.find(); + return Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + height: 280, + //color: Theme.of(context).cardColor, + padding: const EdgeInsets.only(top: 30, left: 5, right: 30, bottom: 10), + child: Column(children: [ + Padding( + padding: const EdgeInsets.only(left: 20.0, bottom: 5), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + "Set Discover content", + style: Theme.of(context).textTheme.titleLarge, + ), + ), + ), + radioWidget( + label: "Quick Pics", controller: settingsController, value: "QP"), + radioWidget( + label: "Top Music Videos", + controller: settingsController, + value: "TMV"), + radioWidget( + label: "Trending", controller: settingsController, value: "TR"), + radioWidget( + label: "Based on last interaction", + controller: settingsController, + value: "BOLI"), + Align( + alignment: Alignment.centerRight, + child: InkWell( + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Text("Cancel"), + ), + onTap: () => Navigator.of(context).pop(), + )) + ]), + ), + ); } } + +Widget radioWidget( + {required String label, + required SettingsScreenController controller, + required value}) { + return Obx(() => ListTile( + visualDensity: const VisualDensity(vertical: -4), + onTap: () { + if (value.runtimeType == ThemeType) { + controller.onThemeChange(value); + } else { + controller.onContentChange(value); + Navigator.of(Get.context!).pop(); + } + }, + leading: Radio( + value: value, + groupValue: value.runtimeType == ThemeType + ? controller.themeModetype.value + : controller.discoverContentType.value, + onChanged: value.runtimeType == ThemeType + ? controller.onThemeChange + : controller.onContentChange), + title: Text(label), + )); +} diff --git a/lib/ui/screens/settings_screen_controller.dart b/lib/ui/screens/settings_screen_controller.dart index 342199b1..0f4c22bc 100644 --- a/lib/ui/screens/settings_screen_controller.dart +++ b/lib/ui/screens/settings_screen_controller.dart @@ -2,6 +2,7 @@ import 'package:android_power_manager/android_power_manager.dart'; import 'package:get/get.dart'; import 'package:harmonymusic/services/music_service.dart'; import 'package:harmonymusic/ui/player/player_controller.dart'; +import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; import 'package:harmonymusic/ui/utils/theme_controller.dart'; import 'package:hive_flutter/hive_flutter.dart'; @@ -12,6 +13,7 @@ class SettingsScreenController extends GetxController { final skipSilenceEnabled = false.obs; final streamingQuality = AudioQuality.High.obs; final isIgnoringBatteryOptimizations = false.obs; + final discoverContentType = "QP".obs; @override void onInit() { _setInitValue(); @@ -24,6 +26,7 @@ class SettingsScreenController extends GetxController { skipSilenceEnabled.value = setBox.get("skipSilenceEnabled"); streamingQuality.value = AudioQuality.values[setBox.get('streamingQuality')]; + discoverContentType.value = setBox.get('discoverContentType'); if (GetPlatform.isAndroid) { isIgnoringBatteryOptimizations.value = (await AndroidPowerManager.isIgnoringBatteryOptimizations)!; @@ -41,6 +44,12 @@ class SettingsScreenController extends GetxController { Get.find().changeThemeModeType(val); } + void onContentChange(dynamic value){ + setBox.put('discoverContentType', value); + discoverContentType.value = value; + Get.find().changeDiscoverContent(value); + } + void toggleCachingSongsValue(bool value) { setBox.put("cacheSongs", value); cacheSongs.value = value; diff --git a/lib/ui/widgets/quickpickswidget.dart b/lib/ui/widgets/quickpickswidget.dart index 2252fae4..9e781c83 100644 --- a/lib/ui/widgets/quickpickswidget.dart +++ b/lib/ui/widgets/quickpickswidget.dart @@ -22,7 +22,7 @@ class QuickPicksWidget extends StatelessWidget { Align( alignment: Alignment.centerLeft, child: Text( - "Discover", + content.title, style: Theme.of(context).textTheme.titleLarge, )), const SizedBox(height: 10), diff --git a/pubspec.lock b/pubspec.lock index 19bb8a80..41a21a94 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -336,15 +336,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.33" - just_audio_libwinmedia: - dependency: "direct main" - description: - path: "." - ref: HEAD - resolved-ref: "331cd3ef198dcf2da15684c1f2021c99a330a41c" - url: "https://github.com/anandnet/just_audio_libwinmedia.git" - source: git - version: "0.0.4+1" just_audio_platform_interface: dependency: transitive description: @@ -385,22 +376,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" - media_kit: - dependency: transitive - description: - name: media_kit - sha256: "080cfb5af8d04f8cc454cb4c5ea34b19de5b8e1a1b3af62a34e766364b5244ad" - url: "https://pub.dev" - source: hosted - version: "0.0.11" - media_kit_libs_windows_audio: - dependency: transitive - description: - name: media_kit_libs_windows_audio - sha256: f6ad5a1b910a6748a7350360756cd99a718fc9661a9583a7fd86a308d068dd81 - url: "https://pub.dev" - source: hosted - version: "1.0.3" meta: dependency: transitive description: @@ -537,14 +512,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.27.7" - safe_local_storage: - dependency: transitive - description: - name: safe_local_storage - sha256: ede4eb6cb7d88a116b3d3bf1df70790b9e2038bc37cb19112e381217c74d9440 - url: "https://pub.dev" - source: hosted - version: "1.0.2" share_plus: dependency: "direct main" description: @@ -654,14 +621,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - uri_parser: - dependency: transitive - description: - name: uri_parser - sha256: "6543c9fd86d2862fac55d800a43e67c0dcd1a41677cb69c2f8edfe73bbcf1835" - url: "https://pub.dev" - source: hosted - version: "2.0.2" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 5d5a70fd..056032ec 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -52,8 +52,7 @@ dependencies: url_launcher: ^6.1.11 share_plus: ^7.0.1 android_power_manager: ^1.0.0 - just_audio_libwinmedia: - git: "https://github.com/anandnet/just_audio_libwinmedia.git" + dev_dependencies: flutter_test: sdk: flutter diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 10a336ae..c3384ec5 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,13 +6,10 @@ #include "generated_plugin_registrant.h" -#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { - MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("MediaKitLibsWindowsAudioPluginCApi")); SharePlusWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 66fb2167..01d38362 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,7 +3,6 @@ # list(APPEND FLUTTER_PLUGIN_LIST - media_kit_libs_windows_audio share_plus url_launcher_windows ) From 613ffbfdbb4346e8620004cd7a3305a7e411f663 Mon Sep 17 00:00:00 2001 From: Anand kumar Date: Thu, 22 Jun 2023 22:08:47 +0530 Subject: [PATCH 2/6] Internal client error 403 handled using workaround --- lib/services/audio_handler.dart | 25 ++++++++++++++++------ lib/services/music_service.dart | 1 - lib/ui/screens/home_screen_controller.dart | 4 ++-- lib/ui/screens/settings_screen.dart | 4 ++-- lib/ui/utils/home_library_controller.dart | 2 +- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index 9d3139ad..ba0c7ac4 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -116,6 +116,7 @@ class MyAudioHandler extends BaseAudioHandler with GetxServiceMixin { final box = Hive.box("songsUrlCache"); if (box.containsKey(mediaItem.value!.id)) { if (isExpired(url: box.get(mediaItem.value!.id)[1])) { + await _player.stop(); await customAction("playByIndex", {'index': currentIndex}); return; } @@ -127,8 +128,17 @@ class MyAudioHandler extends BaseAudioHandler with GetxServiceMixin { await _player.seek(curPos, index: 0); await _player.play(); } - await _player.stop(); - networkErrorPause = true; + + //Workaround when 403 error encountered + customAction("playByIndex", {'index': currentIndex, 'newUrl': true}) + .whenComplete(() async { + await _player.stop(); + if (currentSongUrl == null) { + networkErrorPause = true; + } else { + _player.play(); + } + }); } }); } @@ -308,9 +318,11 @@ class MyAudioHandler extends BaseAudioHandler with GetxServiceMixin { } else if (name == 'playByIndex') { await _playList.clear(); currentIndex = extras!['index']; + final isNewUrlReq = extras['newUrl'] ?? false; final currentSong = queue.value[currentIndex]; mediaItem.add(currentSong); - final url = await checkNGetUrl(currentSong.id); + final url = + await checkNGetUrl(currentSong.id, generateNewUrl: isNewUrlReq); currentSongUrl = url; if (url == null) { return; @@ -387,7 +399,7 @@ class MyAudioHandler extends BaseAudioHandler with GetxServiceMixin { } else if (name == 'addPlayNextItem') { final song = extras!['mediaItem'] as MediaItem; final currentQueue = queue.value; - currentQueue.insert(currentIndex+1, song); + currentQueue.insert(currentIndex + 1, song); queue.add(currentQueue); } } @@ -407,7 +419,8 @@ class MyAudioHandler extends BaseAudioHandler with GetxServiceMixin { // Work around used [useNewInstanceOfExplode = false] to Fix Connection closed before full header was received issue Future checkNGetUrl(String songId, - {bool useNewInstanceOfExplode = false}) async { + {bool useNewInstanceOfExplode = false, + bool generateNewUrl = false}) async { final songsCacheBox = Hive.box("SongsCache"); if (songsCacheBox.containsKey(songId)) { printINFO("Got Song from cachedbox ($songId)"); @@ -420,7 +433,7 @@ class MyAudioHandler extends BaseAudioHandler with GetxServiceMixin { final newMusicServicesIns = useNewInstanceOfExplode ? MusicServices(false) : null; dynamic url; - if (songsUrlCacheBox.containsKey(songId)) { + if (songsUrlCacheBox.containsKey(songId) && !generateNewUrl) { if (isExpired(url: songsUrlCacheBox.get(songId)[qualityIndex])) { url = useNewInstanceOfExplode ? await newMusicServicesIns!.getSongUri(songId) diff --git a/lib/services/music_service.dart b/lib/services/music_service.dart index 5f4542de..776c04a0 100644 --- a/lib/services/music_service.dart +++ b/lib/services/music_service.dart @@ -4,7 +4,6 @@ import 'dart:convert'; import 'dart:math'; import 'package:dio/dio.dart'; import 'package:get/get.dart' as getx; -import 'package:get/get_utils/get_utils.dart'; import 'package:harmonymusic/models/album.dart'; import 'package:harmonymusic/services/utils.dart'; import 'package:hive/hive.dart'; diff --git a/lib/ui/screens/home_screen_controller.dart b/lib/ui/screens/home_screen_controller.dart index 4d8ec997..0ebc06b3 100644 --- a/lib/ui/screens/home_screen_controller.dart +++ b/lib/ui/screens/home_screen_controller.dart @@ -45,7 +45,7 @@ class HomeScreenController extends GetxController { .indexWhere((element) => element['title'] == "Top music videos"); if (index != -1 && index != 0) { final con = homeContentListMap.removeAt(index); - quickPicks.value = QuickPicks(List.from(con["contents"])); + quickPicks.value = QuickPicks(List.from(con["contents"]),title: con["title"] ); } else if (index == -1) { List charts = await _musicServices.getCharts(); quickPicks.value = QuickPicks( @@ -66,7 +66,7 @@ class HomeScreenController extends GetxController { .indexWhere((element) => element['title'] == "Quick picks"); final con = homeContentListMap.removeAt(index); quickPicks.value = QuickPicks(List.from(con["contents"]), - title: "Quick Pics"); + title: "Quick picks"); } middleContent.value = _setContentList(middleContentTemp); fixedContent.value = _setContentList(homeContentListMap); diff --git a/lib/ui/screens/settings_screen.dart b/lib/ui/screens/settings_screen.dart index e6d50a43..7ff6a50b 100644 --- a/lib/ui/screens/settings_screen.dart +++ b/lib/ui/screens/settings_screen.dart @@ -57,7 +57,7 @@ class SettingsScreen extends StatelessWidget { title: const Text("Set Discover content"), subtitle: Obx(() => Text( settingsController.discoverContentType.value == "QP" - ? "Quick Pics" + ? "Quick Picks" : settingsController.discoverContentType.value == "TMV" ? "Top Music Videos" : settingsController.discoverContentType.value == @@ -256,7 +256,7 @@ class DiscoverContentSelectorDialog extends StatelessWidget { ), ), radioWidget( - label: "Quick Pics", controller: settingsController, value: "QP"), + label: "Quick Picks", controller: settingsController, value: "QP"), radioWidget( label: "Top Music Videos", controller: settingsController, diff --git a/lib/ui/utils/home_library_controller.dart b/lib/ui/utils/home_library_controller.dart index 71e3108a..4067e9db 100644 --- a/lib/ui/utils/home_library_controller.dart +++ b/lib/ui/utils/home_library_controller.dart @@ -75,7 +75,7 @@ class LibraryPlaylistsController extends GetxController { thumbnailUrl: "", isCloudPlaylist: false), Playlist( - title: "Favourite", + title: "Favorites", playlistId: "LIBFAV", thumbnailUrl: "", isCloudPlaylist: false), From fd43ce3e0b4254a5bd62cf9c978b202e63abfa56 Mon Sep 17 00:00:00 2001 From: Anand kumar Date: Thu, 29 Jun 2023 21:58:14 +0530 Subject: [PATCH 3/6] Lyrics support added,images resolution changes done & some fixes --- lib/models/album.dart | 2 +- lib/models/media_Item_builder.dart | 2 +- lib/models/playlist.dart | 2 +- lib/models/thumbnail.dart | 6 +- lib/services/music_service.dart | 36 ++++-- lib/ui/home.dart | 26 ++-- lib/ui/player/Player.dart | 126 ++++++++++++++++--- lib/ui/player/player_controller.dart | 22 ++++ lib/ui/screens/artist_screen.dart | 40 +++--- lib/ui/screens/home_screen_controller.dart | 4 +- lib/ui/screens/playlistnalbum_screen.dart | 15 ++- lib/ui/widgets/content_list_widget.dart | 6 +- lib/ui/widgets/content_list_widget_item.dart | 58 +++++---- lib/ui/widgets/image_widget.dart | 67 ++++++---- lib/ui/widgets/list_widget.dart | 44 +++---- lib/ui/widgets/quickpickswidget.dart | 4 +- lib/ui/widgets/songinfo_bottom_sheet.dart | 9 +- 17 files changed, 304 insertions(+), 165 deletions(-) diff --git a/lib/models/album.dart b/lib/models/album.dart index 866e70bd..723c0173 100644 --- a/lib/models/album.dart +++ b/lib/models/album.dart @@ -27,7 +27,7 @@ class Album { artists:json["artists"]!=null? List>.from(json["artists"]):[{'name':''}], year: json['year'], - thumbnailUrl: Thumbnail(json["thumbnails"][0]["url"]).high); + thumbnailUrl: Thumbnail(json["thumbnails"][0]["url"]).medium); Map toJson()=>{ "title":title, diff --git a/lib/models/media_Item_builder.dart b/lib/models/media_Item_builder.dart index 9f568bf7..ce09de8e 100644 --- a/lib/models/media_Item_builder.dart +++ b/lib/models/media_Item_builder.dart @@ -22,7 +22,7 @@ class MediaItemBuilder { artist: artistName == "" ? artistName : artistName.substring(0, artistName.length - 2), - artUri: Uri.parse(Thumbnail(json["thumbnails"][0]['url']).high), + artUri: Uri.parse(Thumbnail(json["thumbnails"][0]['url']).low), extras: { 'url': json['url'] ?? url, 'length': json['length'], diff --git a/lib/models/playlist.dart b/lib/models/playlist.dart index f7a4fa6a..ce052ca9 100644 --- a/lib/models/playlist.dart +++ b/lib/models/playlist.dart @@ -24,7 +24,7 @@ class Playlist { factory Playlist.fromJson(Map json) => Playlist( title: json["title"], playlistId: json["playlistId"] ?? json["browseId"], - thumbnailUrl: Thumbnail(json["thumbnails"][0]["url"]).high, + thumbnailUrl: Thumbnail(json["thumbnails"][0]["url"]).medium, description: json["description"], songCount: json['itemCount'], isCloudPlaylist: json["isCloudPlaylist"] ?? true); diff --git a/lib/models/thumbnail.dart b/lib/models/thumbnail.dart index d394edb2..5b33acf1 100644 --- a/lib/models/thumbnail.dart +++ b/lib/models/thumbnail.dart @@ -3,7 +3,7 @@ class Thumbnail { final String _url; String sizewith(int size) => "${_url.split("=")[0]}=w$size-h$size-l90-rj"; String get url => _url; - String get high => sizewith(544); - String get medium => sizewith(300); - String get low => sizewith(200); + String get high => sizewith(450); + String get medium => sizewith(350); + String get low => sizewith(150); } diff --git a/lib/services/music_service.dart b/lib/services/music_service.dart index 776c04a0..06ae675d 100644 --- a/lib/services/music_service.dart +++ b/lib/services/music_service.dart @@ -155,21 +155,23 @@ class MusicServices extends getx.GetxService { } Future>> getCharts({String? countryCode}) async { - final List> charts = []; + final List> charts = []; final data = Map.from(_context); data['browseId'] = 'FEmusic_charts'; - if(countryCode!=null){ - data['formData']= {'selectedValues': [countryCode]}; + if (countryCode != null) { + data['formData'] = { + 'selectedValues': [countryCode] + }; } final response = (await _sendRequest('browse', data)).data; - final results = nav(response,single_column_tab+section_list); + final results = nav(response, single_column_tab + section_list); results.removeAt(0); - for(dynamic result in results){ + for (dynamic result in results) { charts.add(parseChartsItem(result)); } - - return charts; + + return charts; } Future> getWatchPlaylist( @@ -178,7 +180,8 @@ class MusicServices extends getx.GetxService { int limit = 25, bool radio = false, bool shuffle = false, - String? additionalParamsNext,bool onlyRelated = false}) async { + String? additionalParamsNext, + bool onlyRelated = false}) async { final data = Map.from(_context); data['enablePersistentPlaylistPanel'] = true; data['isAudioOnly'] = true; @@ -227,8 +230,8 @@ class MusicServices extends getx.GetxService { lyricsBrowseId = getTabBrowseId(watchNextRenderer, 1); relatedBrowseId = getTabBrowseId(watchNextRenderer, 2); - if(onlyRelated){ - return { + if (onlyRelated) { + return { 'lyrics': lyricsBrowseId, 'related': relatedBrowseId, }; @@ -274,15 +277,24 @@ class MusicServices extends getx.GetxService { } dynamic getContentRelatedToSong(String videoId) async { - final params = await getWatchPlaylist(videoId: videoId,onlyRelated: true); + final params = await getWatchPlaylist(videoId: videoId, onlyRelated: true); final data = Map.from(_context); data['browseId'] = params['related']; final response = (await _sendRequest('browse', data)).data; final sections = nav(response, ['contents'] + section_list); - final x= parseMixedContent(sections); + final x = parseMixedContent(sections); return x; } + dynamic getLyrics(String browseId) async { + final data = Map.from(_context); + data['browseId'] = browseId; + final response = (await _sendRequest('browse', data)).data; + return nav( + response, + ['contents', ...section_list_item, ...description_shelf, ...description], + ); + } Future> getPlaylistOrAlbumSongs( {String? playlistId, diff --git a/lib/ui/home.dart b/lib/ui/home.dart index 360e50c1..2a894e66 100644 --- a/lib/ui/home.dart +++ b/lib/ui/home.dart @@ -77,21 +77,17 @@ class Home extends StatelessWidget { MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - SizedBox.square( - dimension: 50, - //width: 40, - child: - playerController.currentSong.value != - null - ? ImageWidget( - song: playerController - .currentSong.value!, - ) - : const SizedBox( - height: 50, - width: 50, - ), - ), + playerController.currentSong.value != + null + ? ImageWidget( + size: 50, + song: playerController + .currentSong.value!, + ) + : const SizedBox( + height: 50, + width: 50, + ), const SizedBox( width: 10, ), diff --git a/lib/ui/player/Player.dart b/lib/ui/player/Player.dart index 12a5e9ae..f7956021 100644 --- a/lib/ui/player/Player.dart +++ b/lib/ui/player/Player.dart @@ -23,6 +23,7 @@ class Player extends StatelessWidget { final size = MediaQuery.of(context).size; final PlayerController playerController = Get.find(); final ThemeController themeController = Get.find(); + final playerArtImageSize = size.width - ((size.height < 750) ? 90 : 60); return Scaffold( body: SlidingUpPanel( minHeight: 65 + Get.mediaQuery.padding.bottom, @@ -98,12 +99,11 @@ class Player extends StatelessWidget { : Theme.of(homeScaffoldContext) .bottomSheetTheme .backgroundColor, - leading: SizedBox.square( - dimension: 50, - child: ImageWidget( - song: playerController - .currentQueue[index], - )), + leading: ImageWidget( + size: 50, + song: + playerController.currentQueue[index], + ), title: Text( playerController .currentQueue[index].title, @@ -229,13 +229,13 @@ class Player extends StatelessWidget { SizedBox( height: size.height < 750 ? 80 : 120, ), - SizedBox( - height: size.width - ((size.height < 750) ? 90 : 60), - width: size.width - ((size.height < 750) ? 90 : 60), - child: Obx(() => playerController.currentSong.value != - null - ? InkWell( + Obx(() => playerController.currentSong.value != null + ? Stack( + children: [ + InkWell( onLongPress: () { + // printINFO( + // "${size.width - ((size.height < 750) ? 90 : 60)}"); showModalBottomSheet( barrierColor: Colors.transparent.withAlpha(100), @@ -246,12 +246,108 @@ class Player extends StatelessWidget { ).whenComplete( () => Get.delete()); }, + onTap: () { + playerController.showLyrics(); + }, child: ImageWidget( + size: playerArtImageSize, song: playerController.currentSong.value!, - isLargeImage: true, + isPlayerArtImage: true, ), - ) - : Container())), + ), + Obx(() => playerController.showLyricsflag.isTrue + ? InkWell( + onTap: () { + playerController.showLyrics(); + }, + child: Container( + height: playerArtImageSize, + width: playerArtImageSize, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.8), + borderRadius: + BorderRadius.circular(5), + ), + child: Stack( + children: [ + Center( + child: SingleChildScrollView( + physics: + const BouncingScrollPhysics(), + padding: EdgeInsets.symmetric( + horizontal: 0, + vertical: + playerArtImageSize / + 3.5), + child: Obx( + () => playerController + .isLyricsLoading + .isFalse + ? Text( + playerController + .lyrics + .value == + "NA" + ? "Lyrics not available!" + : playerController + .lyrics.value, + textAlign: + TextAlign.center, + style: Theme.of( + context) + .textTheme + .titleMedium! + .copyWith( + color: Colors + .white), + ) + : const Center( + child: RefreshProgressIndicator( + backgroundColor: + Colors + .transparent), + ), + ), + ), + ), + IgnorePointer( + child: Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(5), + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Theme.of(context) + .primaryColor + .withOpacity(0.90), + Colors.transparent, + Colors.transparent, + Colors.transparent, + Theme.of(context) + .primaryColor + .withOpacity(0.90) + ], + stops: const [ + 0, + 0.2, + 0.5, + 0.8, + 1 + ], + ), + ), + ), + ) + ], + ), + ), + ) + : const SizedBox.shrink()), + ], + ) + : Container()), Expanded(child: Container()), Obx(() { return MarqueeWidget( diff --git a/lib/ui/player/player_controller.dart b/lib/ui/player/player_controller.dart index ed31cfa1..9a4a1665 100644 --- a/lib/ui/player/player_controller.dart +++ b/lib/ui/player/player_controller.dart @@ -40,6 +40,9 @@ class PlayerController extends GetxController { final isLoopModeEnabled = false.obs; final currentSong = Rxn(); final isCurrentSongFav = false.obs; + final showLyricsflag = false.obs; + final isLyricsLoading = false.obs; + final lyrics = "".obs; ScrollController scrollController = ScrollController(); final GlobalKey homeScaffoldkey = GlobalKey(); @@ -156,6 +159,8 @@ class PlayerController extends GetxController { if (isRadioModeOn && (currentSong.value!.id == currentQueue.last.id)) { await _addRadioContinuation(radioInitiatorItem!); } + lyrics.value = ""; + showLyricsflag.value = false; } }); } @@ -414,6 +419,23 @@ class PlayerController extends GetxController { recentItem = mediaItem; } + Future showLyrics() async { + showLyricsflag.value = !showLyricsflag.value; + if (lyrics.isEmpty && showLyricsflag.value) { + isLyricsLoading.value = true; + final related = await _musicServices.getWatchPlaylist( + videoId: currentSong.value!.id, onlyRelated: true); + final relatedLyricsId = related['lyrics']; + if (relatedLyricsId != null) { + final lyrics_ = await _musicServices.getLyrics(relatedLyricsId); + lyrics.value = lyrics_ as String; + }else{ + lyrics.value = "NA"; + } + isLyricsLoading.value = false; + } + } + @override void dispose() { _audioHandler.customAction('dispose'); diff --git a/lib/ui/screens/artist_screen.dart b/lib/ui/screens/artist_screen.dart index 6cecb391..bab69ad6 100644 --- a/lib/ui/screens/artist_screen.dart +++ b/lib/ui/screens/artist_screen.dart @@ -37,9 +37,10 @@ class ArtistScreen extends StatelessWidget { onPressed: () async { final radioId = artistScreenController.artist_.radioId; if (radioId == null) { - ScaffoldMessenger.of(context).showSnackBar( - snackbar(context, "Radio not available for this artist!", size: SanckBarSize.BIG)); - return; + ScaffoldMessenger.of(context).showSnackBar(snackbar( + context, "Radio not available for this artist!", + size: SanckBarSize.BIG)); + return; } playerController.startRadio(null, playlistid: artistScreenController.artist_.radioId); @@ -94,8 +95,10 @@ class ArtistScreen extends StatelessWidget { final artistData = artistScreenController.artistData; final separatedContent = artistScreenController.sepataredContent; - if(artistScreenController.isSeparatedArtistContentFetced.isFalse && - artistScreenController.navigationRailCurrentIndex.value !=0){ + if (artistScreenController + .isSeparatedArtistContentFetced.isFalse && + artistScreenController.navigationRailCurrentIndex.value != + 0) { return const Center(child: RefreshProgressIndicator()); } @@ -120,16 +123,11 @@ class ArtistScreen extends StatelessWidget { child: Stack( children: [ Center( - child: ClipOval( - child: SizedBox( - height: 200, - width: 200, - child: ImageWidget( - artist: - artistScreenController - .artist_, - isLargeImage: true), - ), + child: ImageWidget( + size: 200, + artist: + artistScreenController + .artist_, ), ), Align( @@ -162,7 +160,8 @@ class ArtistScreen extends StatelessWidget { : Icon(artistScreenController .isAddedToLibrary .isFalse - ? Icons.bookmark_add_rounded + ? Icons + .bookmark_add_rounded : Icons .bookmark_added_rounded), ), @@ -181,7 +180,8 @@ class ArtistScreen extends StatelessWidget { .titleLarge, ), ), - (artistData.containsKey("description") && + (artistData.containsKey( + "description") && artistData["description"] != null) ? Align( @@ -224,7 +224,8 @@ class ArtistScreen extends StatelessWidget { : [], title: "Songs", topPadding: 75, - scrollController: artistScreenController.songScrollController, + scrollController: + artistScreenController.songScrollController, ); } case 2: @@ -236,7 +237,8 @@ class ArtistScreen extends StatelessWidget { : [], title: "Videos", topPadding: 75, - scrollController: artistScreenController.videoScrollController, + scrollController: + artistScreenController.videoScrollController, ); } case 3: diff --git a/lib/ui/screens/home_screen_controller.dart b/lib/ui/screens/home_screen_controller.dart index 0ebc06b3..f0ff8905 100644 --- a/lib/ui/screens/home_screen_controller.dart +++ b/lib/ui/screens/home_screen_controller.dart @@ -87,14 +87,14 @@ class HomeScreenController extends GetxController { for (var content in contents) { if ((content["contents"][0]).runtimeType == Playlist) { final tmp = PlaylistContent( - playlistList: List.from(content["contents"]), + playlistList: (content["contents"]).whereType().toList(), title: content["title"]); if (tmp.playlistList.length >= 2) { contentTemp.add(tmp); } } else if ((content["contents"][0]).runtimeType == Album) { final tmp = AlbumContent( - albumList: List.from(content["contents"]), + albumList: (content["contents"]).whereType().toList(), title: content["title"]); if (tmp.albumList.length >= 2) { contentTemp.add(tmp); diff --git a/lib/ui/screens/playlistnalbum_screen.dart b/lib/ui/screens/playlistnalbum_screen.dart index 16e66cb9..eb8fc2d2 100644 --- a/lib/ui/screens/playlistnalbum_screen.dart +++ b/lib/ui/screens/playlistnalbum_screen.dart @@ -110,7 +110,8 @@ class PlaylistNAlbumScreen extends StatelessWidget { child: Column( children: [ ListTile( - leading: const Icon(Icons.edit_rounded), + leading: const Icon( + Icons.edit_rounded), title: const Text("Rename playlist"), onTap: () { @@ -172,14 +173,14 @@ class PlaylistNAlbumScreen extends StatelessWidget { playListNAlbumScreenController .isAlbum.isTrue ? ImageWidget( + size: 200, album: playListNAlbumScreenController .contentRenderer, - isLargeImage: true, ) : ImageWidget( + size: 200, playlist: content, - isLargeImage: true, ), Align( alignment: Alignment.topRight, @@ -228,8 +229,10 @@ class PlaylistNAlbumScreen extends StatelessWidget { playListNAlbumScreenController .isAddedToLibrary .isFalse - ? Icons.bookmark_add_rounded - : Icons.bookmark_added_rounded)), + ? Icons + .bookmark_add_rounded + : Icons + .bookmark_added_rounded)), )), ), Padding( @@ -321,7 +324,7 @@ class PlaylistNAlbumScreen extends StatelessWidget { "${playListNAlbumScreenController.songList.length} songs", titleLeftPadding: 9, isDurationOptionRequired: true, - onSort: (a,b,c,d) { + onSort: (a, b, c, d) { playListNAlbumScreenController.onSort( a, c, d); }, diff --git a/lib/ui/widgets/content_list_widget.dart b/lib/ui/widgets/content_list_widget.dart index 915950cf..702a4ced 100644 --- a/lib/ui/widgets/content_list_widget.dart +++ b/lib/ui/widgets/content_list_widget.dart @@ -24,7 +24,9 @@ class ContentListWidget extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - content.title.length>12 ?"${content.title.substring(0,12)}...":content.title, + content.title.length > 12 + ? "${content.title.substring(0, 12)}..." + : content.title, //maxLines: 2, style: Theme.of(context).textTheme.titleLarge, ), @@ -46,6 +48,8 @@ class ContentListWidget extends StatelessWidget { height: 200, //color: Colors.blueAccent, child: ListView.separated( + addAutomaticKeepAlives: false, //Testing going + addRepaintBoundaries: false, //on this physics: const BouncingScrollPhysics(), separatorBuilder: (context, index) => const SizedBox( width: 15, diff --git a/lib/ui/widgets/content_list_widget_item.dart b/lib/ui/widgets/content_list_widget_item.dart index 2ae22dcc..8b00c139 100644 --- a/lib/ui/widgets/content_list_widget_item.dart +++ b/lib/ui/widgets/content_list_widget_item.dart @@ -28,36 +28,34 @@ class ContentListItem extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - height: 120, - width: 120, - child: isAlbum - ? ImageWidget( - album: content, - isMediumImage: true, - ) - : content.isCloudPlaylist - ? ImageWidget( - playlist: content, - isMediumImage: true, - ) - : Container( - decoration: BoxDecoration( - color: Theme.of(context).primaryColorLight, - borderRadius: BorderRadius.circular(10)), - child: Center( - child: Icon( - content.playlistId == 'LIBRP' - ? Icons.history_rounded - : content.playlistId == 'LIBFAV' - ? Icons.favorite_rounded - : content.playlistId == 'SongsCache' - ? Icons.flight_rounded - : Icons.playlist_play_rounded, - color: Colors.white, - size: 40, - ))), - ), + isAlbum + ? ImageWidget( + size: 120, + album: content, + ) + : content.isCloudPlaylist + ? ImageWidget( + size: 120, + playlist: content, + ) + : Container( + height: 120, + width: 120, + decoration: BoxDecoration( + color: Theme.of(context).primaryColorLight, + borderRadius: BorderRadius.circular(10)), + child: Center( + child: Icon( + content.playlistId == 'LIBRP' + ? Icons.history_rounded + : content.playlistId == 'LIBFAV' + ? Icons.favorite_rounded + : content.playlistId == 'SongsCache' + ? Icons.flight_rounded + : Icons.playlist_play_rounded, + color: Colors.white, + size: 40, + ))), const SizedBox(height: 5), Text( content.title, diff --git a/lib/ui/widgets/image_widget.dart b/lib/ui/widgets/image_widget.dart index cf6f67a0..baf3a448 100644 --- a/lib/ui/widgets/image_widget.dart +++ b/lib/ui/widgets/image_widget.dart @@ -3,31 +3,35 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:harmonymusic/models/artist.dart'; +import 'package:harmonymusic/models/thumbnail.dart'; import 'package:shimmer/shimmer.dart'; import '../../models/album.dart'; import '../../models/playlist.dart'; class ImageWidget extends StatelessWidget { - const ImageWidget( - {super.key, - this.song, - this.playlist, - this.album, - this.artist, - this.isLargeImage = false, - this.isMediumImage = false}); + const ImageWidget({ + super.key, + this.song, + this.playlist, + this.album, + this.artist, + required this.size, + this.isPlayerArtImage = false, + }); final MediaItem? song; final Playlist? playlist; final Album? album; - final bool isLargeImage; - final bool isMediumImage; + final bool isPlayerArtImage; final Artist? artist; + final double size; @override Widget build(BuildContext context) { String imageUrl = song != null - ? song!.artUri.toString() + ? isPlayerArtImage + ? Thumbnail(song!.artUri.toString()).high + : song!.artUri.toString() : playlist != null ? playlist!.thumbnailUrl : album != null @@ -36,7 +40,9 @@ class ImageWidget extends StatelessWidget { ? artist!.thumbnailUrl : ""; String cacheKey = song != null - ? "${song!.id}_song" + ? isPlayerArtImage + ? "${song!.id}_song_pl" + : "${song!.id}_song" : playlist != null ? "${playlist!.playlistId}_playlist" : album != null @@ -47,25 +53,33 @@ class ImageWidget extends StatelessWidget { return GetPlatform.isWeb ? Image.network( imageUrl, - fit: BoxFit.fitHeight, + fit: BoxFit.fill, ) - : ClipRRect( - borderRadius: BorderRadius.circular(5), + : SizedBox.square( + dimension: size, child: CachedNetworkImage( - memCacheHeight: isLargeImage - ? 500 - : isMediumImage - ? 300 - : 150, cacheKey: cacheKey, imageUrl: imageUrl, - fit: BoxFit.cover, + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + shape: artist != null ? BoxShape.circle : BoxShape.rectangle, + borderRadius: + artist != null ? null : BorderRadius.circular(5), + image: + DecorationImage(image: imageProvider, fit: BoxFit.cover), + ), + ), errorWidget: (context, url, error) => Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.secondary, - borderRadius: BorderRadius.circular(10)), - child: Image.asset("assets/icons/${song!=null?"song":artist!=null?"artist":"album"}.png")), + color: Theme.of(context).colorScheme.secondary, + shape: + artist != null ? BoxShape.circle : BoxShape.rectangle, + borderRadius: + artist != null ? null : BorderRadius.circular(10), + ), + child: Image.asset( + "assets/icons/${song != null ? "song" : artist != null ? "artist" : "album"}.png")), progressIndicatorBuilder: ((_, __, ___) => Shimmer.fromColors( baseColor: Colors.grey[500]!, highlightColor: Colors.grey[300]!, @@ -73,7 +87,10 @@ class ImageWidget extends StatelessWidget { direction: ShimmerDirection.ltr, child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), + shape: + artist != null ? BoxShape.circle : BoxShape.rectangle, + borderRadius: + artist != null ? null : BorderRadius.circular(10), color: Colors.white54, ), ))), diff --git a/lib/ui/widgets/list_widget.dart b/lib/ui/widgets/list_widget.dart index fecc751c..c8b9790e 100644 --- a/lib/ui/widgets/list_widget.dart +++ b/lib/ui/widgets/list_widget.dart @@ -64,6 +64,8 @@ class ListWidget extends StatelessWidget { {bool isPlaylist = false, Playlist? playlist, ScrollController? sc}) { final playerController = Get.find(); return ListView.builder( + addRepaintBoundaries: false, + addAutomaticKeepAlives: false, controller: sc, padding: EdgeInsets.only( top: 0, @@ -97,11 +99,10 @@ class ListWidget extends StatelessWidget { ).whenComplete(() => Get.delete()); }, contentPadding: const EdgeInsets.only(top: 0, left: 5, right: 30), - leading: SizedBox.square( - dimension: 50, - child: ImageWidget( - song: items[index], - )), + leading: ImageWidget( + size: 55, + song: items[index], + ), title: Text( items[index].title, maxLines: 1, @@ -142,12 +143,10 @@ class ListWidget extends StatelessWidget { }, contentPadding: const EdgeInsets.only(top: 0, bottom: 0, left: 10), - leading: SizedBox.square( - dimension: 100, - child: ImageWidget( - playlist: playlists[index], - isMediumImage: true, - )), + leading: ImageWidget( + size: 100, + playlist: playlists[index], + ), title: Text( playlists[index].title, maxLines: 1, @@ -192,12 +191,10 @@ class ListWidget extends StatelessWidget { arguments: [true, albums[index], false]); }, contentPadding: const EdgeInsets.only(top: 0, bottom: 0, left: 10), - leading: SizedBox.square( - dimension: 100, - child: ImageWidget( - album: albums[index], - isMediumImage: true, - )), + leading: ImageWidget( + size: 100, + album: albums[index], + ), title: Text( albums[index].title, maxLines: 1, @@ -237,15 +234,10 @@ class ListWidget extends StatelessWidget { arguments: [false, artists[index]]); }, contentPadding: const EdgeInsets.only(top: 0, bottom: 0, left: 5), - leading: Container( - height: 90, - width: 90, - clipBehavior: Clip.antiAlias, - decoration: const BoxDecoration(shape: BoxShape.circle), - child: ImageWidget( - artist: artists[index], - isMediumImage: true, - )), + leading: ImageWidget( + size: 90, + artist: artists[index], + ), title: Text( artists[index].name, maxLines: 1, diff --git a/lib/ui/widgets/quickpickswidget.dart b/lib/ui/widgets/quickpickswidget.dart index 9e781c83..8874d139 100644 --- a/lib/ui/widgets/quickpickswidget.dart +++ b/lib/ui/widgets/quickpickswidget.dart @@ -40,9 +40,7 @@ class QuickPicksWidget extends StatelessWidget { itemBuilder: (_, item) { return ListTile( contentPadding: const EdgeInsets.only(left: 5), - leading: SizedBox( - width: 50, - child: ImageWidget(song: content.songList[item])), + leading: ImageWidget(song: content.songList[item],size: 55,), title: Text( content.songList[item].title, overflow: TextOverflow.ellipsis, diff --git a/lib/ui/widgets/songinfo_bottom_sheet.dart b/lib/ui/widgets/songinfo_bottom_sheet.dart index 4cf27794..e9c29af1 100644 --- a/lib/ui/widgets/songinfo_bottom_sheet.dart +++ b/lib/ui/widgets/songinfo_bottom_sheet.dart @@ -35,11 +35,10 @@ class SongInfoBottomSheet extends StatelessWidget { ListTile( contentPadding: const EdgeInsets.only(left: 15, top: 7, right: 10, bottom: 0), - leading: SizedBox.square( - dimension: 50, - child: ImageWidget( - song: song, - )), + leading: ImageWidget( + song: song, + size: 50, + ), title: Text( song.title, maxLines: 1, From 075d1a02f14c7b202dbdc2df6eea6e4447cc0e24 Mon Sep 17 00:00:00 2001 From: Anand kumar Date: Sun, 2 Jul 2023 00:41:53 +0530 Subject: [PATCH 4/6] Equalizer support & App new version notifier added --- lib/helper.dart | 23 ++++++- lib/main.dart | 1 + lib/services/audio_handler.dart | 3 + lib/ui/player/player_controller.dart | 4 ++ lib/ui/screens/home_screen_controller.dart | 49 +++++++++++--- lib/ui/screens/settings_screen.dart | 54 ++++++++++++++- .../screens/settings_screen_controller.dart | 12 +++- lib/ui/widgets/new_version_dialog.dart | 66 +++++++++++++++++++ linux/flutter/generated_plugin_registrant.cc | 4 ++ linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 11 +++- pubspec.yaml | 4 ++ .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 15 files changed, 223 insertions(+), 15 deletions(-) create mode 100644 lib/ui/widgets/new_version_dialog.dart diff --git a/lib/helper.dart b/lib/helper.dart index fc892555..b021a6ab 100644 --- a/lib/helper.dart +++ b/lib/helper.dart @@ -1,6 +1,6 @@ +import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; - void printERROR(dynamic text, {String tag = "Harmony Music"}) { debugPrint("\x1B[31m[$tag]: $text"); } @@ -77,3 +77,24 @@ void sortArtist( artistList.sort((a, b) => isAscending ? a.name.compareTo(b.name) : b.name.compareTo(a.name)); } + +/// Return true if new version available +Future newVersionCheck(String currentVersion) async { + final tags = (await Dio() + .get("https://api.github.com/repos/anandnet/Harmony-Music/tags")) + .data; + final availableVersion = tags[0]['name'] as String; + List currentVersion_ = currentVersion.substring(1).split("."); + List availableVersion_ = availableVersion.substring(1).split("."); + if (int.parse(availableVersion_[0]) > int.parse(currentVersion_[0])) { + return true; + } else if (int.parse(availableVersion_[1]) > int.parse(currentVersion_[1]) && + int.parse(availableVersion_[0]) == int.parse(currentVersion_[0])) { + return true; + } else if (int.parse(availableVersion_[2]) > int.parse(currentVersion_[2]) && + int.parse(availableVersion_[0]) == int.parse(currentVersion_[0]) && + int.parse(availableVersion_[1]) == int.parse(currentVersion_[1])) { + return true; + } + return false; +} diff --git a/lib/main.dart b/lib/main.dart index f7a7be48..9dd01e04 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -81,6 +81,7 @@ void _setAppInitPrefs() { 'streamingQuality': 1, 'themePrimaryColor': 4278199603, 'discoverContentType': "QP", + 'newVersionVisibility':true }); } } diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index ba0c7ac4..3d631d43 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:audio_service/audio_service.dart'; +import 'package:device_equalizer/device_equalizer.dart'; import 'package:get/get.dart'; import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/media_Item_builder.dart'; @@ -401,6 +402,8 @@ class MyAudioHandler extends BaseAudioHandler with GetxServiceMixin { final currentQueue = queue.value; currentQueue.insert(currentIndex + 1, song); queue.add(currentQueue); + }else if (name == 'openEqualizer') { + await DeviceEqualizer().open(_player.androidAudioSessionId!); } } diff --git a/lib/ui/player/player_controller.dart b/lib/ui/player/player_controller.dart index 9a4a1665..a90510f9 100644 --- a/lib/ui/player/player_controller.dart +++ b/lib/ui/player/player_controller.dart @@ -436,6 +436,10 @@ class PlayerController extends GetxController { } } + Future openEqualizer() async { + await _audioHandler.customAction("openEqualizer"); + } + @override void dispose() { _audioHandler.customAction('dispose'); diff --git a/lib/ui/screens/home_screen_controller.dart b/lib/ui/screens/home_screen_controller.dart index f0ff8905..51427f05 100644 --- a/lib/ui/screens/home_screen_controller.dart +++ b/lib/ui/screens/home_screen_controller.dart @@ -1,10 +1,13 @@ import 'package:audio_service/audio_service.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/album.dart'; import 'package:harmonymusic/models/playlist.dart'; import 'package:harmonymusic/models/quick_picks.dart'; import 'package:harmonymusic/services/music_service.dart'; +import 'package:harmonymusic/ui/screens/settings_screen_controller.dart'; +import 'package:harmonymusic/ui/widgets/new_version_dialog.dart'; import 'package:hive/hive.dart'; class HomeScreenController extends GetxController { @@ -15,8 +18,11 @@ class HomeScreenController extends GetxController { final quickPicks = QuickPicks([]).obs; final middleContent = [].obs; final fixedContent = [].obs; + final showVersionDialog = true.obs; + HomeScreenController() { init(); + _checkNewVersion(); } Future init() async { @@ -25,13 +31,15 @@ class HomeScreenController extends GetxController { networkError.value = false; try { - List middleContentTemp =[]; + List middleContentTemp = []; final homeContentListMap = await _musicServices.getHome(limit: 10); if (contentType == "TR") { final index = homeContentListMap .indexWhere((element) => element['title'] == "Trending"); if (index != -1 && index != 0) { - quickPicks.value = QuickPicks(List.from(homeContentListMap[index]["contents"]),title: "Trending"); + quickPicks.value = QuickPicks( + List.from(homeContentListMap[index]["contents"]), + title: "Trending"); } else if (index == -1) { List charts = await _musicServices.getCharts(); final con = @@ -45,7 +53,8 @@ class HomeScreenController extends GetxController { .indexWhere((element) => element['title'] == "Top music videos"); if (index != -1 && index != 0) { final con = homeContentListMap.removeAt(index); - quickPicks.value = QuickPicks(List.from(con["contents"]),title: con["title"] ); + quickPicks.value = QuickPicks(List.from(con["contents"]), + title: con["title"]); } else if (index == -1) { List charts = await _musicServices.getCharts(); quickPicks.value = QuickPicks( @@ -113,9 +122,13 @@ class HomeScreenController extends GetxController { title: homeContentListMap[0]["title"]); } else if (val == "TMV" || val == 'TR') { final charts = await _musicServices.getCharts(); - final index =val == "TMV" ?0: charts.length == 4 ?3:2; - quickPicks_ = - QuickPicks(List.from(charts[index]["contents"]), title: charts[index]["title"]); + final index = val == "TMV" + ? 0 + : charts.length == 4 + ? 3 + : 2; + quickPicks_ = QuickPicks(List.from(charts[index]["contents"]), + title: charts[index]["title"]); } else { songId ??= Hive.box("AppPrefs").get("recentSongId"); if (songId != null) { @@ -128,13 +141,31 @@ class HomeScreenController extends GetxController { } } if (quickPicks_ == null) return; - - quickPicks.value = quickPicks_; + + quickPicks.value = quickPicks_; } void onTabSelected(int index) { tabIndex.value = index; } - void getRelatedArtist() {} + void _checkNewVersion() { + showVersionDialog.value = + Hive.box("AppPrefs").get("newVersionVisibility") ?? true; + if (showVersionDialog.isTrue) { + newVersionCheck(Get.find().currentVersion) + .then((value) { + if (value) { + showDialog( + context: Get.context!, + builder: (context) => const NewVersionDialog()); + } + }); + } + } + + void onChangeVersionVisibility(bool val) { + Hive.box("AppPrefs").put("newVersionVisibility", !val); + showVersionDialog.value = !val; + } } diff --git a/lib/ui/screens/settings_screen.dart b/lib/ui/screens/settings_screen.dart index 7ff6a50b..5190892e 100644 --- a/lib/ui/screens/settings_screen.dart +++ b/lib/ui/screens/settings_screen.dart @@ -30,6 +30,43 @@ class SettingsScreen extends StatelessWidget { physics: const BouncingScrollPhysics(), padding: const EdgeInsets.only(bottom: 90), children: [ + Obx( + () => settingsController.isNewVersionAvailable.value + ? Padding( + padding: const EdgeInsets.only(top: 8.0, right: 10), + child: Material( + type: MaterialType.transparency, + child: ListTile( + onTap: () { + launchUrl( + Uri.parse( + 'https://github.com/anandnet/Harmony-Music/releases/latest', + ), + mode: LaunchMode.externalApplication, + ); + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + tileColor: Theme.of(context).colorScheme.secondary, + contentPadding: + const EdgeInsets.only(left: 8, right: 10), + leading: const CircleAvatar( + child: Icon(Icons.download_rounded)), + title: const Text("New Version available!"), + visualDensity: const VisualDensity(horizontal: -2), + subtitle: Text( + "Click here to go to download page", + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith( + color: Colors.white70, fontSize: 13), + ), + ), + ), + ) + : const SizedBox.shrink(), + ), ListTile( contentPadding: const EdgeInsets.only(left: 5, right: 10), title: const Text("Theme mode"), @@ -113,6 +150,15 @@ class SettingsScreen extends StatelessWidget { ), ), ), + ListTile( + contentPadding: const EdgeInsets.only(left: 5, right: 10,top: 0), + title: const Text("Equalizer"), + subtitle: Text("Open system euqalizer", + style: Theme.of(context).textTheme.bodyMedium), + onTap: () async { + await Get.find().openEqualizer(); + }, + ), GetPlatform.isAndroid ? Obx( () => ListTile( @@ -149,7 +195,7 @@ class SettingsScreen extends StatelessWidget { contentPadding: const EdgeInsets.only(left: 5, right: 10), title: const Text("Github"), subtitle: Text( - "View Github source code \nif you like this project, don't forget to give a ⭐${((Get.find().playerPanelMinHeight.value) == 0) ? "" : "\n\nV 1.1.0 by anandnet"}", + "View Github source code \nif you like this project, don't forget to give a ⭐${((Get.find().playerPanelMinHeight.value) == 0) ? "" : "\n\n${settingsController.currentVersion} by anandnet"}", style: Theme.of(context).textTheme.bodyMedium, ), isThreeLine: true, @@ -167,7 +213,7 @@ class SettingsScreen extends StatelessWidget { Padding( padding: const EdgeInsets.only(bottom: 20.0), child: Text( - "V 1.1.0 by anandnet", + "${settingsController.currentVersion} by anandnet", style: Theme.of(context).textTheme.bodySmall, ), ), @@ -256,7 +302,9 @@ class DiscoverContentSelectorDialog extends StatelessWidget { ), ), radioWidget( - label: "Quick Picks", controller: settingsController, value: "QP"), + label: "Quick Picks", + controller: settingsController, + value: "QP"), radioWidget( label: "Top Music Videos", controller: settingsController, diff --git a/lib/ui/screens/settings_screen_controller.dart b/lib/ui/screens/settings_screen_controller.dart index 0f4c22bc..06914c38 100644 --- a/lib/ui/screens/settings_screen_controller.dart +++ b/lib/ui/screens/settings_screen_controller.dart @@ -1,5 +1,6 @@ import 'package:android_power_manager/android_power_manager.dart'; import 'package:get/get.dart'; +import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/services/music_service.dart'; import 'package:harmonymusic/ui/player/player_controller.dart'; import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; @@ -14,12 +15,21 @@ class SettingsScreenController extends GetxController { final streamingQuality = AudioQuality.High.obs; final isIgnoringBatteryOptimizations = false.obs; final discoverContentType = "QP".obs; + final isNewVersionAvailable = false.obs; + final currentVersion = "V1.1.0"; @override void onInit() { _setInitValue(); + _checkNewVersion(); super.onInit(); } + get currentVision=>currentVersion; + + _checkNewVersion() { + newVersionCheck(currentVersion).then((value) => isNewVersionAvailable.value = value); + } + Future _setInitValue() async { cacheSongs.value = setBox.get('cacheSongs'); themeModetype.value = ThemeType.values[setBox.get('themeModeType')]; @@ -44,7 +54,7 @@ class SettingsScreenController extends GetxController { Get.find().changeThemeModeType(val); } - void onContentChange(dynamic value){ + void onContentChange(dynamic value) { setBox.put('discoverContentType', value); discoverContentType.value = value; Get.find().changeDiscoverContent(value); diff --git a/lib/ui/widgets/new_version_dialog.dart b/lib/ui/widgets/new_version_dialog.dart new file mode 100644 index 00000000..081d852f --- /dev/null +++ b/lib/ui/widgets/new_version_dialog.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class NewVersionDialog extends StatelessWidget { + const NewVersionDialog({super.key}); + + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + child: Container( + height: 330, + padding: const EdgeInsets.only(top: 40, bottom: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "New Version available!", + style: Theme.of(context).textTheme.titleMedium, + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: SizedBox.square( + dimension: 100, + child: FittedBox( + child: FloatingActionButton( + onPressed: () { + launchUrl( + Uri.parse( + 'https://github.com/anandnet/Harmony-Music/releases/latest', + ), + mode: LaunchMode.externalApplication, + ); + }, + child: const Icon( + Icons.download_rounded, + size: 30, + ), + ), + ), + )), + Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GetX(builder: (controller) { + return Checkbox( + value: controller.showVersionDialog.isFalse, + onChanged: (val){ + controller.onChangeVersionVisibility(val??false); + }, + shape: const CircleBorder()); + }), + const Text("Dont show this info again!") + ], + ), + ), + FilledButton(onPressed: ()=>Navigator.of(context).pop(), child: const Text("Dismiss")) + ], + ), + ), + ); + } +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index f6f23bfe..1c938046 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,9 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) device_equalizer_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DeviceEqualizerPlugin"); + device_equalizer_plugin_register_with_registrar(device_equalizer_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index f16b4c34..c31d5693 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + device_equalizer url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 0970594a..af10c576 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,6 +7,7 @@ import Foundation import audio_service import audio_session +import device_equalizer import just_audio import path_provider_foundation import share_plus @@ -16,6 +17,7 @@ import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin")) AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) + DeviceEqualizerPlugin.register(with: registry.registrar(forPlugin: "DeviceEqualizerPlugin")) JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 41a21a94..e806c36f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -137,6 +137,15 @@ packages: url: "https://pub.dev" source: hosted version: "0.17.3" + device_equalizer: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "4b87c8a307559d204f0f0d70c2096a41ec34ab7c" + url: "https://github.com/anandnet/device_equalizer.git" + source: git + version: "0.0.1" dio: dependency: "direct main" description: @@ -734,5 +743,5 @@ packages: source: hosted version: "1.12.4" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.0.5 <4.0.0" flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index 056032ec..90cf058c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -52,6 +52,10 @@ dependencies: url_launcher: ^6.1.11 share_plus: ^7.0.1 android_power_manager: ^1.0.0 + device_equalizer: + git: + url: https://github.com/anandnet/device_equalizer.git + ref: main dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index c3384ec5..0dee1567 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,10 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + DeviceEqualizerPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DeviceEqualizerPluginCApi")); SharePlusWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 01d38362..3d51da30 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + device_equalizer share_plus url_launcher_windows ) From 0dd8a75c71ae22553820b0767c29ec9aee0db40e Mon Sep 17 00:00:00 2001 From: Anand kumar Date: Sun, 2 Jul 2023 14:52:56 +0530 Subject: [PATCH 5/6] Hide FAB from settings,fixed newVersionDialog,cached song file removal added & arranged imports --- lib/main.dart | 26 ++++++---- lib/services/audio_handler.dart | 13 ++--- lib/services/music_service.dart | 5 +- lib/services/nav_parser.dart | 2 +- lib/ui/home.dart | 2 +- lib/ui/navigator.dart | 2 +- lib/ui/player/Player.dart | 7 ++- lib/ui/player/player_controller.dart | 9 ++-- lib/ui/screens/artist_screen.dart | 2 +- lib/ui/screens/artist_screen_controller.dart | 2 +- lib/ui/screens/home_screen.dart | 51 ++++++++++--------- lib/ui/screens/home_screen_controller.dart | 4 +- lib/ui/screens/playlistnalbum_screen.dart | 2 +- .../playlistnalbum_screen_controller.dart | 3 +- .../search_result_screen_controller.dart | 1 + lib/ui/screens/search_screen.dart | 1 + lib/ui/screens/search_screen_controller.dart | 1 + lib/ui/screens/settings_screen.dart | 4 +- .../screens/settings_screen_controller.dart | 8 +-- lib/ui/utils/home_library_controller.dart | 16 ++++-- lib/ui/widgets/add_to_playlist.dart | 4 +- lib/ui/widgets/content_list_widget.dart | 1 + lib/ui/widgets/create_playlist_dialog.dart | 2 +- lib/ui/widgets/image_widget.dart | 4 +- lib/ui/widgets/new_version_dialog.dart | 23 +++++++-- lib/ui/widgets/quickpickswidget.dart | 2 +- lib/ui/widgets/search_related_widgets.dart | 2 +- lib/ui/widgets/songinfo_bottom_sheet.dart | 33 ++++++------ 28 files changed, 136 insertions(+), 96 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9dd01e04..2a26c1ff 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,18 +1,17 @@ import 'dart:io'; - import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:path_provider/path_provider.dart'; + import 'package:harmonymusic/services/audio_handler.dart'; import 'package:harmonymusic/services/music_service.dart'; import 'package:harmonymusic/ui/home.dart'; import 'package:harmonymusic/ui/player/player_controller.dart'; import 'package:harmonymusic/ui/screens/settings_screen_controller.dart'; import 'package:harmonymusic/ui/utils/theme_controller.dart'; -import 'package:hive_flutter/hive_flutter.dart'; -import 'package:path_provider/path_provider.dart'; - import 'ui/screens/home_screen_controller.dart'; import 'ui/utils/home_library_controller.dart'; @@ -42,11 +41,18 @@ class MyApp extends StatelessWidget { }); return GetX(builder: (controller) { return GetMaterialApp( - title: 'Harmony Music', - theme: controller.themedata.value, - home: const Home(), - debugShowCheckedModeBanner: false, - ); + title: 'Harmony Music', + theme: controller.themedata.value, + home: const Home(), + debugShowCheckedModeBanner: false, + builder: (context, child) { + final scale = + MediaQuery.of(context).textScaleFactor.clamp(1.0, 1.3); + return MediaQuery( + data: MediaQuery.of(context).copyWith(textScaleFactor: scale), + child: child!, + ); + }); }); } } @@ -81,7 +87,7 @@ void _setAppInitPrefs() { 'streamingQuality': 1, 'themePrimaryColor': 4278199603, 'discoverContentType': "QP", - 'newVersionVisibility':true + 'newVersionVisibility': true }); } } diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index 3d631d43..83b4f126 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -1,18 +1,15 @@ import 'dart:io'; - +import 'package:hive/hive.dart'; +import 'package:get/get.dart'; +import 'package:just_audio/just_audio.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:audio_service/audio_service.dart'; import 'package:device_equalizer/device_equalizer.dart'; -import 'package:get/get.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/media_Item_builder.dart'; import 'package:harmonymusic/services/utils.dart'; import 'package:harmonymusic/ui/screens/settings_screen_controller.dart'; -import 'package:hive/hive.dart'; - -import 'package:just_audio/just_audio.dart'; - -import 'package:path_provider/path_provider.dart'; - import '../ui/utils/home_library_controller.dart'; import 'music_service.dart'; diff --git a/lib/services/music_service.dart b/lib/services/music_service.dart index 06ae675d..89495bae 100644 --- a/lib/services/music_service.dart +++ b/lib/services/music_service.dart @@ -4,10 +4,11 @@ import 'dart:convert'; import 'dart:math'; import 'package:dio/dio.dart'; import 'package:get/get.dart' as getx; -import 'package:harmonymusic/models/album.dart'; -import 'package:harmonymusic/services/utils.dart'; import 'package:hive/hive.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; + +import 'package:harmonymusic/models/album.dart'; +import 'package:harmonymusic/services/utils.dart'; import '../helper.dart'; import 'constant.dart'; import 'continuations.dart'; diff --git a/lib/services/nav_parser.dart b/lib/services/nav_parser.dart index c1790fd1..a9a817eb 100644 --- a/lib/services/nav_parser.dart +++ b/lib/services/nav_parser.dart @@ -2,9 +2,9 @@ // ignore_for_file: constant_identifier_names import 'package:audio_service/audio_service.dart'; + import 'package:harmonymusic/models/media_Item_builder.dart'; import 'package:harmonymusic/services/utils.dart'; - import '../models/album.dart'; import '../models/artist.dart'; import '../models/playlist.dart'; diff --git a/lib/ui/home.dart b/lib/ui/home.dart index 2a894e66..0ab0b1cf 100644 --- a/lib/ui/home.dart +++ b/lib/ui/home.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/ui/navigator.dart'; import 'package:harmonymusic/ui/player/player.dart'; - import 'player/player_controller.dart'; import 'widgets/image_widget.dart'; import 'widgets/mini_player_progress_bar.dart'; diff --git a/lib/ui/navigator.dart b/lib/ui/navigator.dart index df83c6c5..d4e5471e 100644 --- a/lib/ui/navigator.dart +++ b/lib/ui/navigator.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/ui/screens/artist_screen.dart'; import 'package:harmonymusic/ui/screens/home_screen.dart'; import 'package:harmonymusic/ui/screens/playlistnalbum_screen.dart'; import 'package:harmonymusic/ui/screens/search_screen.dart'; - import 'screens/search_result_screen.dart'; class ScreenNavigationSetup { diff --git a/lib/ui/player/Player.dart b/lib/ui/player/Player.dart index f7956021..76b7fcd2 100644 --- a/lib/ui/player/Player.dart +++ b/lib/ui/player/Player.dart @@ -1,16 +1,15 @@ import 'dart:ui'; - +import 'package:get/get.dart'; +import 'package:flutter/material.dart'; import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; import 'package:cached_network_image/cached_network_image.dart'; -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/ui/player/player_controller.dart'; import 'package:harmonymusic/ui/screens/settings_screen_controller.dart'; import 'package:harmonymusic/ui/utils/theme_controller.dart'; import 'package:harmonymusic/ui/widgets/marqwee_widget.dart'; import 'package:harmonymusic/ui/widgets/songinfo_bottom_sheet.dart'; - import '../widgets/image_widget.dart'; import '../widgets/sliding_up_panel.dart'; diff --git a/lib/ui/player/player_controller.dart b/lib/ui/player/player_controller.dart index a90510f9..1cb08f1d 100644 --- a/lib/ui/player/player_controller.dart +++ b/lib/ui/player/player_controller.dart @@ -1,15 +1,14 @@ import 'dart:async'; - +import 'package:hive/hive.dart'; +import 'package:get/get.dart'; import 'package:flutter/material.dart'; +import 'package:audio_service/audio_service.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/media_Item_builder.dart'; import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; import 'package:harmonymusic/ui/screens/playlistnalbum_screen_controller.dart'; -import 'package:hive/hive.dart'; -import 'package:audio_service/audio_service.dart'; -import 'package:get/get.dart'; - import '../widgets/sliding_up_panel.dart'; import '/models/durationstate.dart'; import '/services/music_service.dart'; diff --git a/lib/ui/screens/artist_screen.dart b/lib/ui/screens/artist_screen.dart index bab69ad6..d9436eb8 100644 --- a/lib/ui/screens/artist_screen.dart +++ b/lib/ui/screens/artist_screen.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/ui/player/player_controller.dart'; import 'package:harmonymusic/ui/screens/artist_screen_controller.dart'; import 'package:harmonymusic/ui/widgets/image_widget.dart'; import 'package:harmonymusic/ui/widgets/search_related_widgets.dart'; - import '../navigator.dart'; import '../widgets/snackbar.dart'; diff --git a/lib/ui/screens/artist_screen_controller.dart b/lib/ui/screens/artist_screen_controller.dart index 68b5349e..6410147f 100644 --- a/lib/ui/screens/artist_screen_controller.dart +++ b/lib/ui/screens/artist_screen_controller.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:harmonymusic/services/music_service.dart'; import 'package:hive/hive.dart'; import '../../helper.dart'; import '../../models/artist.dart'; import '../utils/home_library_controller.dart'; +import 'package:harmonymusic/services/music_service.dart'; class ArtistScreenController extends GetxController { final isArtistContentFetced = false.obs; diff --git a/lib/ui/screens/home_screen.dart b/lib/ui/screens/home_screen.dart index 246a2a49..577d450d 100644 --- a/lib/ui/screens/home_screen.dart +++ b/lib/ui/screens/home_screen.dart @@ -25,29 +25,34 @@ class HomeScreen extends StatelessWidget { final size = MediaQuery.of(context).size; return Scaffold( floatingActionButton: Obx( - () => Padding( - padding: EdgeInsets.only( - bottom: - playerController.playerPanelMinHeight.value == 0 ? 20 : 75), - child: SizedBox( - height: 60, - width: 60, - child: FittedBox( - child: FloatingActionButton( - focusElevation: 0, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(14))), - elevation: 0, - onPressed: () async { - Get.toNamed(ScreenNavigationSetup.searchScreen, - id: ScreenNavigationSetup.id); - // file:///data/user/0/com.example.harmonymusic/cache/libCachedImageData/ - //file:///data/user/0/com.example.harmonymusic/cache/just_audio_cache/ - }, - child: const Icon(Icons.search_rounded)), + () => homeScreenController.tabIndex.value != 5? + Obx( + () => Padding( + padding: EdgeInsets.only( + bottom: playerController.playerPanelMinHeight.value == 0 + ? 20 + : 75), + child: SizedBox( + height: 60, + width: 60, + child: FittedBox( + child: FloatingActionButton( + focusElevation: 0, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(14))), + elevation: 0, + onPressed: () async { + Get.toNamed(ScreenNavigationSetup.searchScreen, + id: ScreenNavigationSetup.id); + // file:///data/user/0/com.example.harmonymusic/cache/libCachedImageData/ + //file:///data/user/0/com.example.harmonymusic/cache/just_audio_cache/ + }, + child: const Icon(Icons.search_rounded)), + ), + ), ), - ), - ), + + ):const SizedBox.shrink(), ), body: Row( children: [ @@ -193,7 +198,7 @@ class Body extends StatelessWidget { Obx(() => QuickPicksWidget( content: homeScreenController.quickPicks.value)), - ...getWidgetList( + ...getWidgetList( homeScreenController.middleContent), ...getWidgetList( homeScreenController.fixedContent, diff --git a/lib/ui/screens/home_screen_controller.dart b/lib/ui/screens/home_screen_controller.dart index 51427f05..0e29ce51 100644 --- a/lib/ui/screens/home_screen_controller.dart +++ b/lib/ui/screens/home_screen_controller.dart @@ -1,6 +1,8 @@ import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:hive/hive.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/album.dart'; import 'package:harmonymusic/models/playlist.dart'; @@ -8,7 +10,7 @@ import 'package:harmonymusic/models/quick_picks.dart'; import 'package:harmonymusic/services/music_service.dart'; import 'package:harmonymusic/ui/screens/settings_screen_controller.dart'; import 'package:harmonymusic/ui/widgets/new_version_dialog.dart'; -import 'package:hive/hive.dart'; + class HomeScreenController extends GetxController { final MusicServices _musicServices = Get.find(); diff --git a/lib/ui/screens/playlistnalbum_screen.dart b/lib/ui/screens/playlistnalbum_screen.dart index eb8fc2d2..a6b14436 100644 --- a/lib/ui/screens/playlistnalbum_screen.dart +++ b/lib/ui/screens/playlistnalbum_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/ui/navigator.dart'; import 'package:harmonymusic/ui/screens/playlistnalbum_screen_controller.dart'; import 'package:harmonymusic/ui/widgets/create_playlist_dialog.dart'; @@ -7,7 +8,6 @@ import 'package:harmonymusic/ui/widgets/list_widget.dart'; import 'package:harmonymusic/ui/widgets/shimmer_widgets/song_list_shimmer.dart'; import 'package:harmonymusic/ui/widgets/snackbar.dart'; import 'package:harmonymusic/ui/widgets/sort_widget.dart'; - import '../../models/playlist.dart'; import '../player/player_controller.dart'; import '../widgets/image_widget.dart'; diff --git a/lib/ui/screens/playlistnalbum_screen_controller.dart b/lib/ui/screens/playlistnalbum_screen_controller.dart index 5e2f265a..12ffe668 100644 --- a/lib/ui/screens/playlistnalbum_screen_controller.dart +++ b/lib/ui/screens/playlistnalbum_screen_controller.dart @@ -1,9 +1,10 @@ import 'package:audio_service/audio_service.dart'; import 'package:get/get.dart'; +import 'package:hive/hive.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/album.dart'; import 'package:harmonymusic/models/thumbnail.dart'; -import 'package:hive/hive.dart'; import '../../models/media_Item_builder.dart'; import '../../services/music_service.dart'; import '../utils/home_library_controller.dart'; diff --git a/lib/ui/screens/search_result_screen_controller.dart b/lib/ui/screens/search_result_screen_controller.dart index 1064f0e7..41fa29bd 100644 --- a/lib/ui/screens/search_result_screen_controller.dart +++ b/lib/ui/screens/search_result_screen_controller.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/services/music_service.dart'; diff --git a/lib/ui/screens/search_screen.dart b/lib/ui/screens/search_screen.dart index d556bedb..d12ae073 100644 --- a/lib/ui/screens/search_screen.dart +++ b/lib/ui/screens/search_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/ui/navigator.dart'; import 'package:harmonymusic/ui/screens/search_screen_controller.dart'; diff --git a/lib/ui/screens/search_screen_controller.dart b/lib/ui/screens/search_screen_controller.dart index 685bc43b..4bbd698e 100644 --- a/lib/ui/screens/search_screen_controller.dart +++ b/lib/ui/screens/search_screen_controller.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/services/music_service.dart'; class SearchScreenController extends GetxController { diff --git a/lib/ui/screens/settings_screen.dart b/lib/ui/screens/settings_screen.dart index 5190892e..639345e3 100644 --- a/lib/ui/screens/settings_screen.dart +++ b/lib/ui/screens/settings_screen.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:url_launcher/url_launcher.dart'; + import 'package:harmonymusic/services/music_service.dart'; import 'package:harmonymusic/ui/player/player_controller.dart'; import 'package:harmonymusic/ui/utils/theme_controller.dart'; -import 'package:url_launcher/url_launcher.dart'; - import 'settings_screen_controller.dart'; class SettingsScreen extends StatelessWidget { diff --git a/lib/ui/screens/settings_screen_controller.dart b/lib/ui/screens/settings_screen_controller.dart index 06914c38..5587a795 100644 --- a/lib/ui/screens/settings_screen_controller.dart +++ b/lib/ui/screens/settings_screen_controller.dart @@ -1,11 +1,12 @@ import 'package:android_power_manager/android_power_manager.dart'; import 'package:get/get.dart'; +import 'package:hive_flutter/hive_flutter.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/services/music_service.dart'; import 'package:harmonymusic/ui/player/player_controller.dart'; import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; import 'package:harmonymusic/ui/utils/theme_controller.dart'; -import 'package:hive_flutter/hive_flutter.dart'; class SettingsScreenController extends GetxController { final cacheSongs = false.obs; @@ -24,10 +25,11 @@ class SettingsScreenController extends GetxController { super.onInit(); } - get currentVision=>currentVersion; + get currentVision => currentVersion; _checkNewVersion() { - newVersionCheck(currentVersion).then((value) => isNewVersionAvailable.value = value); + newVersionCheck(currentVersion) + .then((value) => isNewVersionAvailable.value = value); } Future _setInitValue() async { diff --git a/lib/ui/utils/home_library_controller.dart b/lib/ui/utils/home_library_controller.dart index 4067e9db..f7eb9322 100644 --- a/lib/ui/utils/home_library_controller.dart +++ b/lib/ui/utils/home_library_controller.dart @@ -1,15 +1,16 @@ import 'dart:io'; - import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:hive/hive.dart'; +import 'package:path_provider/path_provider.dart'; + import 'package:harmonymusic/helper.dart'; import 'package:harmonymusic/models/album.dart'; import 'package:harmonymusic/models/artist.dart'; import 'package:harmonymusic/models/media_Item_builder.dart'; import 'package:harmonymusic/models/playlist.dart'; -import 'package:hive/hive.dart'; -import 'package:path_provider/path_provider.dart'; + class LibrarySongsController extends GetxController { late RxList cachedSongsList = RxList(); @@ -65,6 +66,15 @@ class LibrarySongsController extends GetxController { songlist, sortByName, sortByDate, sortByDuration, isAscending); cachedSongsList.value = songlist; } + + Future removeSong(MediaItem item) async { + cachedSongsList.remove(item); + final cacheDir = (await getTemporaryDirectory()).path; + if(await File("$cacheDir/cachedSongs/${item.id}.mp3").exists()){ + await (File("$cacheDir/cachedSongs/${item.id}.mp3")).delete(); + } + + } } class LibraryPlaylistsController extends GetxController { diff --git a/lib/ui/widgets/add_to_playlist.dart b/lib/ui/widgets/add_to_playlist.dart index c42f0dbf..539fa350 100644 --- a/lib/ui/widgets/add_to_playlist.dart +++ b/lib/ui/widgets/add_to_playlist.dart @@ -1,10 +1,10 @@ import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:harmonymusic/models/media_Item_builder.dart'; -import 'package:harmonymusic/ui/widgets/create_playlist_dialog.dart'; import 'package:hive/hive.dart'; +import 'package:harmonymusic/models/media_Item_builder.dart'; +import 'package:harmonymusic/ui/widgets/create_playlist_dialog.dart'; import '../../models/playlist.dart'; import 'snackbar.dart'; diff --git a/lib/ui/widgets/content_list_widget.dart b/lib/ui/widgets/content_list_widget.dart index 702a4ced..678d3ce5 100644 --- a/lib/ui/widgets/content_list_widget.dart +++ b/lib/ui/widgets/content_list_widget.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/ui/screens/search_result_screen_controller.dart'; import 'package:harmonymusic/ui/widgets/content_list_widget_item.dart'; diff --git a/lib/ui/widgets/create_playlist_dialog.dart b/lib/ui/widgets/create_playlist_dialog.dart index ef633bd8..dc4d8a54 100644 --- a/lib/ui/widgets/create_playlist_dialog.dart +++ b/lib/ui/widgets/create_playlist_dialog.dart @@ -1,9 +1,9 @@ import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/ui/utils/home_library_controller.dart'; import 'package:harmonymusic/ui/widgets/snackbar.dart'; - import '../../models/playlist.dart'; class CreateNRenamePlaylistPopup extends StatelessWidget { diff --git a/lib/ui/widgets/image_widget.dart b/lib/ui/widgets/image_widget.dart index baf3a448..fc2838dd 100644 --- a/lib/ui/widgets/image_widget.dart +++ b/lib/ui/widgets/image_widget.dart @@ -2,10 +2,10 @@ import 'package:audio_service/audio_service.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:harmonymusic/models/artist.dart'; -import 'package:harmonymusic/models/thumbnail.dart'; import 'package:shimmer/shimmer.dart'; +import 'package:harmonymusic/models/artist.dart'; +import 'package:harmonymusic/models/thumbnail.dart'; import '../../models/album.dart'; import '../../models/playlist.dart'; diff --git a/lib/ui/widgets/new_version_dialog.dart b/lib/ui/widgets/new_version_dialog.dart index 081d852f..fe88b775 100644 --- a/lib/ui/widgets/new_version_dialog.dart +++ b/lib/ui/widgets/new_version_dialog.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:harmonymusic/ui/screens/home_screen_controller.dart'; + class NewVersionDialog extends StatelessWidget { const NewVersionDialog({super.key}); @@ -11,7 +12,7 @@ class NewVersionDialog extends StatelessWidget { return Dialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), child: Container( - height: 330, + height: 320, padding: const EdgeInsets.only(top: 40, bottom: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -48,8 +49,8 @@ class NewVersionDialog extends StatelessWidget { GetX(builder: (controller) { return Checkbox( value: controller.showVersionDialog.isFalse, - onChanged: (val){ - controller.onChangeVersionVisibility(val??false); + onChanged: (val) { + controller.onChangeVersionVisibility(val ?? false); }, shape: const CircleBorder()); }), @@ -57,7 +58,19 @@ class NewVersionDialog extends StatelessWidget { ], ), ), - FilledButton(onPressed: ()=>Navigator.of(context).pop(), child: const Text("Dismiss")) + Container( + decoration: BoxDecoration( + color: Theme.of(context).textTheme.titleLarge!.color, + borderRadius: BorderRadius.circular(10)), + child: InkWell( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15.0, vertical: 10), + child: Text("Dismiss", + style: TextStyle(color: Theme.of(context).canvasColor)), + ), + onTap: () => Navigator.of(context).pop(), + )) ], ), ), diff --git a/lib/ui/widgets/quickpickswidget.dart b/lib/ui/widgets/quickpickswidget.dart index 8874d139..f94281a0 100644 --- a/lib/ui/widgets/quickpickswidget.dart +++ b/lib/ui/widgets/quickpickswidget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:harmonymusic/models/quick_picks.dart'; +import 'package:harmonymusic/models/quick_picks.dart'; import '../player/player_controller.dart'; import 'image_widget.dart'; import 'songinfo_bottom_sheet.dart'; diff --git a/lib/ui/widgets/search_related_widgets.dart b/lib/ui/widgets/search_related_widgets.dart index dd85cfe0..4c2c1bae 100644 --- a/lib/ui/widgets/search_related_widgets.dart +++ b/lib/ui/widgets/search_related_widgets.dart @@ -1,6 +1,7 @@ import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; + import 'package:harmonymusic/models/album.dart'; import 'package:harmonymusic/models/artist.dart'; import 'package:harmonymusic/models/playlist.dart'; @@ -8,7 +9,6 @@ import 'package:harmonymusic/ui/screens/artist_screen_controller.dart'; import 'package:harmonymusic/ui/screens/search_result_screen_controller.dart'; import 'package:harmonymusic/ui/widgets/content_list_widget.dart'; import 'package:harmonymusic/ui/widgets/sort_widget.dart'; - import 'list_widget.dart'; class ResultWidget extends StatelessWidget { diff --git a/lib/ui/widgets/songinfo_bottom_sheet.dart b/lib/ui/widgets/songinfo_bottom_sheet.dart index e9c29af1..0f5c120a 100644 --- a/lib/ui/widgets/songinfo_bottom_sheet.dart +++ b/lib/ui/widgets/songinfo_bottom_sheet.dart @@ -1,14 +1,14 @@ import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:hive/hive.dart'; +import 'package:share_plus/share_plus.dart'; + import 'package:harmonymusic/ui/player/player_controller.dart'; import 'package:harmonymusic/ui/screens/playlistnalbum_screen_controller.dart'; import 'package:harmonymusic/ui/utils/home_library_controller.dart'; import 'package:harmonymusic/ui/widgets/add_to_playlist.dart'; import 'package:harmonymusic/ui/widgets/snackbar.dart'; -import 'package:hive/hive.dart'; -import 'package:share_plus/share_plus.dart'; - import '../../models/media_Item_builder.dart'; import '../../models/playlist.dart'; import '../navigator.dart'; @@ -63,16 +63,17 @@ class SongInfoBottomSheet extends StatelessWidget { Get.find().startRadio(song); }, ), - - (calledFromPlayer||calledFromQueue)?const SizedBox.shrink(): ListTile( - visualDensity: const VisualDensity(vertical: -1), - leading: const Icon(Icons.playlist_play_rounded), - title: const Text("Play next"), - onTap: () { - Navigator.of(context).pop(); - Get.find().playNext(song); - }, - ), + (calledFromPlayer || calledFromQueue) + ? const SizedBox.shrink() + : ListTile( + visualDensity: const VisualDensity(vertical: -1), + leading: const Icon(Icons.playlist_play_rounded), + title: const Text("Play next"), + onTap: () { + Navigator.of(context).pop(); + Get.find().playNext(song); + }, + ), ListTile( visualDensity: const VisualDensity(vertical: -1), leading: const Icon(Icons.playlist_add_rounded), @@ -137,12 +138,12 @@ class SongInfoBottomSheet extends StatelessWidget { ...artistWidgetList(song, context), (playlist != null && !playlist!.isCloudPlaylist && - !(playlist!.playlistId == "LIBCAC") && !(playlist!.playlistId == "LIBRP")) ? ListTile( visualDensity: const VisualDensity(vertical: -1), leading: const Icon(Icons.delete_rounded), - title: const Text("Remove form playlist"), + title: playlist!.playlistId == "SongsCache"? const Text("Remove from cache") + : const Text("Remove from playlist"), onTap: () { Navigator.of(context).pop(); songInfoController @@ -274,7 +275,7 @@ class SongInfoController extends GetxController { } catch (e) {} //Updating Library song list in frontend if (playlist.playlistId == "SongsCache") { - Get.find().cachedSongsList.remove(item); + Get.find().removeSong(item); return; } box.close(); From a79fe8bea88ff8403cd187f94e5ecde48e59edaa Mon Sep 17 00:00:00 2001 From: Anand kumar Date: Sun, 2 Jul 2023 15:16:04 +0530 Subject: [PATCH 6/6] version 1.2.0 updated --- CHANGELOG.md | 17 +++++++++++++++++ README.md | 7 +++++-- lib/ui/screens/settings_screen_controller.dart | 2 +- pubspec.yaml | 2 +- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d4f1531..2cfdd0a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## 1.2.0 +* Discover content selecter added in settings +* Equalizer support added +* Lyrics support added +* images resolution changes done +* App new version notifier added +* Hide Search FAB from settings +* Internal client error 403 handled using workaround + +## 1.1.0 + +* Radio feature added +* Search/(Artist-song/videos) list continuation added +* List sorting feature added +* PlayNext option added +* Bug Fixes + ## 1.0.1 * Some Network Exceptions handled diff --git a/README.md b/README.md index db4bfde7..60b73faa 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ An app for music streaming made with Flutter(Currently support Android only). * Streaming quality control * Skip silence * Dynamic Theme +* Equalizer support +* Lyrics support * No Advertisment * No Login required * No permission required @@ -22,8 +24,9 @@ An app for music streaming made with Flutter(Currently support Android only). # To Do * Backup & Restore -* Lyrics support -* Equalizer support + +# Troubleshoot +* if you are facing Notification control issue or music playpack stopped by system optimization, please enable ignore battery optimization option from settings # Disclaimer ``` diff --git a/lib/ui/screens/settings_screen_controller.dart b/lib/ui/screens/settings_screen_controller.dart index 5587a795..1a4270e8 100644 --- a/lib/ui/screens/settings_screen_controller.dart +++ b/lib/ui/screens/settings_screen_controller.dart @@ -17,7 +17,7 @@ class SettingsScreenController extends GetxController { final isIgnoringBatteryOptimizations = false.obs; final discoverContentType = "QP".obs; final isNewVersionAvailable = false.obs; - final currentVersion = "V1.1.0"; + final currentVersion = "V1.2.0"; @override void onInit() { _setInitValue(); diff --git a/pubspec.yaml b/pubspec.yaml index 90cf058c..0a7b7f3c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # 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.1.0 +version: 1.2.0 environment: sdk: '>=2.19.1 <3.0.0'