diff --git a/lib/controller/settings_controller.dart b/lib/controller/settings_controller.dart index 4a5dd984..b6c3d75e 100644 --- a/lib/controller/settings_controller.dart +++ b/lib/controller/settings_controller.dart @@ -77,6 +77,8 @@ class SettingsController { final RxBool genreSortReversed = false.obs; final Rx playlistSort = GroupSortType.dateModified.obs; final RxBool playlistSortReversed = false.obs; + final Rx ytPlaylistSort = GroupSortType.dateModified.obs; + final RxBool ytPlaylistSortReversed = true.obs; final RxInt indexMinDurationInSec = 5.obs; final RxInt indexMinFileSizeInB = (100 * 1024).obs; final RxList trackSearchFilter = [ @@ -367,6 +369,8 @@ class SettingsController { genreSortReversed.value = json['genreSortReversed'] ?? genreSortReversed.value; playlistSort.value = GroupSortType.values.getEnum(json['playlistSort']) ?? playlistSort.value; playlistSortReversed.value = json['playlistSortReversed'] ?? playlistSortReversed.value; + ytPlaylistSort.value = GroupSortType.values.getEnum(json['ytPlaylistSort']) ?? ytPlaylistSort.value; + ytPlaylistSortReversed.value = json['ytPlaylistSortReversed'] ?? ytPlaylistSortReversed.value; indexMinDurationInSec.value = json['indexMinDurationInSec'] ?? indexMinDurationInSec.value; indexMinFileSizeInB.value = json['indexMinFileSizeInB'] ?? indexMinFileSizeInB.value; @@ -597,6 +601,8 @@ class SettingsController { 'genreSortReversed': genreSortReversed.value, 'playlistSort': playlistSort.value.convertToString, 'playlistSortReversed': playlistSortReversed.value, + 'ytPlaylistSort': ytPlaylistSort.value.convertToString, + 'ytPlaylistSortReversed': ytPlaylistSortReversed.value, 'indexMinDurationInSec': indexMinDurationInSec.value, 'indexMinFileSizeInB': indexMinFileSizeInB.value, 'trackSearchFilter': trackSearchFilter.mapped((e) => e.convertToString), @@ -776,6 +782,8 @@ class SettingsController { bool? genreSortReversed, GroupSortType? playlistSort, bool? playlistSortReversed, + GroupSortType? ytPlaylistSort, + bool? ytPlaylistSortReversed, bool? displayThirdRow, bool? displayThirdItemInEachRow, String? trackTileSeparator, @@ -1063,6 +1071,12 @@ class SettingsController { if (playlistSortReversed != null) { this.playlistSortReversed.value = playlistSortReversed; } + if (ytPlaylistSort != null) { + this.ytPlaylistSort.value = ytPlaylistSort; + } + if (ytPlaylistSortReversed != null) { + this.ytPlaylistSortReversed.value = ytPlaylistSortReversed; + } if (displayThirdRow != null) { this.displayThirdRow.value = displayThirdRow; } diff --git a/lib/youtube/controller/youtube_import_controller.dart b/lib/youtube/controller/youtube_import_controller.dart index 794d1493..2301572b 100644 --- a/lib/youtube/controller/youtube_import_controller.dart +++ b/lib/youtube/controller/youtube_import_controller.dart @@ -36,6 +36,10 @@ class YoutubeImportController { Future importPlaylists(String playlistsDirectoryPath) async { isImportingPlaylists.value = true; final res = await _parsePlaylistsFiles.thready(playlistsDirectoryPath); + if (res.isEmpty) { + isImportingPlaylists.value = false; + return 0; + } final completer = Completer(); res.loop((playlist, index) { @@ -138,9 +142,12 @@ class YoutubeImportController { final playlistsMetadata = {}; - final plMetaFile = File("$dirPath/playlists.csv"); - if (plMetaFile.existsSync()) { - files.remove(plMetaFile); + // final plMetaFile = File("$dirPath/playlists.csv"); + final plMetaFileIndex = files.indexWhere((element) => element.path.endsWith('/playlists.csv')); + final plMetaFile = plMetaFileIndex == -1 ? null : files[plMetaFileIndex]; + + if (plMetaFile != null && plMetaFile is File) { + files.removeAt(plMetaFileIndex); try { final plLines = plMetaFile.readAsLinesSync(); plLines.removeAt(0); diff --git a/lib/youtube/controller/youtube_playlist_controller.dart b/lib/youtube/controller/youtube_playlist_controller.dart index 10eea5ef..fe935ff7 100644 --- a/lib/youtube/controller/youtube_playlist_controller.dart +++ b/lib/youtube/controller/youtube_playlist_controller.dart @@ -7,7 +7,9 @@ import 'package:playlist_manager/module/playlist_id.dart'; import 'package:playlist_manager/playlist_manager.dart'; import 'package:namida/class/video.dart'; +import 'package:namida/controller/settings_controller.dart'; import 'package:namida/core/constants.dart'; +import 'package:namida/core/enums.dart'; import 'package:namida/core/extensions.dart'; import 'package:namida/core/translations/language.dart'; import 'package:namida/youtube/class/youtube_id.dart'; @@ -87,6 +89,42 @@ class YoutubePlaylistController extends PlaylistManager { ); } + void sortYTPlaylists({GroupSortType? sortBy, bool? reverse}) { + sortBy ??= settings.ytPlaylistSort.value; + reverse ??= settings.ytPlaylistSortReversed.value; + + final playlistList = playlistsMap.entries.toList(); + void sortThis(Comparable Function(MapEntry> p) comparable) => + reverse! ? playlistList.sortByReverse(comparable) : playlistList.sortBy(comparable); + + switch (sortBy) { + case GroupSortType.title: + sortThis((p) => p.key.toLowerCase()); + break; + case GroupSortType.creationDate: + sortThis((p) => p.value.creationDate); + break; + case GroupSortType.modifiedDate: + sortThis((p) => p.value.modifiedDate); + break; + case GroupSortType.numberOfTracks: + sortThis((p) => p.value.tracks.length); + break; + case GroupSortType.shuffle: + playlistList.shuffle(); + break; + + default: + null; + } + + playlistsMap + ..clear() + ..addEntries(playlistList); + + settings.save(ytPlaylistSort: sortBy, ytPlaylistSortReversed: reverse); + } + Future prepareAllPlaylists() async => await super.prepareAllPlaylistsFile(); @override @@ -167,5 +205,5 @@ class YoutubePlaylistController extends PlaylistManager { } @override - void sortPlaylists() {} + void sortPlaylists() => sortYTPlaylists(); } diff --git a/lib/youtube/youtube_playlists_view.dart b/lib/youtube/youtube_playlists_view.dart index 88c74580..82241c1b 100644 --- a/lib/youtube/youtube_playlists_view.dart +++ b/lib/youtube/youtube_playlists_view.dart @@ -1,6 +1,9 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:namida/controller/settings_controller.dart'; +import 'package:namida/core/enums.dart'; +import 'package:namida/core/namida_converter_ext.dart'; import 'package:playlist_manager/module/playlist_id.dart'; import 'package:namida/controller/navigator_controller.dart'; @@ -240,6 +243,65 @@ class YoutubePlaylistsView extends StatelessWidget { title: "${lang.PLAYLISTS} - ${YoutubePlaylistController.inst.playlistsMap.length}", icon: Broken.music_library_2, trailing: const SizedBox(), + subtitleWidget: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + NamidaPopupWrapper( + useRootNavigator: false, + children: [ + Obx( + () { + final playlistSort = settings.ytPlaylistSort.value; + return Column( + children: [ + ListTileWithCheckMark( + active: settings.ytPlaylistSortReversed.value, + onTap: () => YoutubePlaylistController.inst.sortYTPlaylists(reverse: !settings.ytPlaylistSortReversed.value), + ), + ...[ + GroupSortType.title, + GroupSortType.creationDate, + GroupSortType.modifiedDate, + GroupSortType.numberOfTracks, + GroupSortType.shuffle, + ].map( + (e) => SmallListTile( + title: e.toText(), + active: playlistSort == e, + onTap: () => YoutubePlaylistController.inst.sortYTPlaylists(sortBy: e), + ), + ), + ], + ); + }, + ), + ], + child: NamidaInkWell( + child: Obx( + () => Text( + settings.ytPlaylistSort.value.toText(), + style: context.textTheme.displaySmall?.copyWith( + color: context.theme.colorScheme.secondary, + ), + ), + ), + ), + ), + const SizedBox(width: 4.0), + NamidaInkWell( + onTap: () { + YoutubePlaylistController.inst.sortYTPlaylists(reverse: !settings.ytPlaylistSortReversed.value); + }, + child: Obx( + () => Icon( + settings.ytPlaylistSortReversed.value ? Broken.arrow_up_3 : Broken.arrow_down_2, + size: 16.0, + color: context.theme.colorScheme.secondary, + ), + ), + ), + ], + ), ), ), ),