diff --git a/lib/controller/backup_controller.dart b/lib/controller/backup_controller.dart index 0b2ddad4..3b471a1b 100644 --- a/lib/controller/backup_controller.dart +++ b/lib/controller/backup_controller.dart @@ -70,7 +70,10 @@ class BackupController { } Future createBackupFile(List backupItemsPaths, {String fileSuffix = ''}) async { - if (isCreatingBackup.value) return snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + if (isCreatingBackup.value) { + snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + return; + } if (!await requestManageStoragePermission()) return; @@ -209,7 +212,10 @@ class BackupController { } Future restoreBackupOnTap(bool auto) async { - if (isRestoringBackup.value) return snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + if (isRestoringBackup.value) { + snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + return; + } File? backupzip; if (auto) { diff --git a/lib/controller/indexer_controller.dart b/lib/controller/indexer_controller.dart index bcc3a003..5c485278 100644 --- a/lib/controller/indexer_controller.dart +++ b/lib/controller/indexer_controller.dart @@ -174,7 +174,10 @@ class Indexer { bool allowDeletion = true, bool showFinishedSnackbar = true, }) async { - if (isIndexing.value) return snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + if (isIndexing.value) { + snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + return; + } isIndexing.value = true; useMediaStore ??= _defaultUseMediaStore; diff --git a/lib/controller/navigator_controller.dart b/lib/controller/navigator_controller.dart index d6c17d47..c0870ffd 100644 --- a/lib/controller/navigator_controller.dart +++ b/lib/controller/navigator_controller.dart @@ -493,7 +493,7 @@ class NamidaNavigator { } } -void snackyy({ +SnackbarController? snackyy({ IconData? icon, String title = '', required String message, @@ -533,6 +533,9 @@ void snackyy({ } else { paddingInsets = const EdgeInsets.symmetric(horizontal: 12.0, vertical: 16.0); } + + bool alreadyTappedButton = false; + final content = Padding( padding: paddingInsets, child: SizedBox( @@ -552,11 +555,11 @@ void snackyy({ if (title != '') Text( title, - style: getTextStyle(FontWeight.w700, 17.0), + style: getTextStyle(FontWeight.w700, 16), ), Text( message, - style: title != '' ? getTextStyle(FontWeight.w400, 14.0) : getTextStyle(FontWeight.w600, 15.0), + style: title != '' ? getTextStyle(FontWeight.w400, 13.0) : getTextStyle(FontWeight.w600, 14.0), maxLines: maxLinesMessage, overflow: maxLinesMessage == null ? null : TextOverflow.ellipsis, ), @@ -567,6 +570,8 @@ void snackyy({ TextButton( style: const ButtonStyle(tapTargetSize: MaterialTapTargetSize.shrinkWrap), onPressed: () { + if (alreadyTappedButton) return; + alreadyTappedButton = true; button.$2(); snackbarController?.close(); }, @@ -623,4 +628,5 @@ void snackyy({ snackbarController = SnackbarController(snackbar); snackbarController.show(); + return snackbarController; } diff --git a/lib/controller/queue_controller.dart b/lib/controller/queue_controller.dart index 1d50199c..3cbd3e49 100644 --- a/lib/controller/queue_controller.dart +++ b/lib/controller/queue_controller.dart @@ -263,14 +263,13 @@ class QueueController { String type = ''; final queue = []; switch (items.firstOrNull.runtimeType) { + case const (Selectable): case const (Track): - type = LibraryCategory.localTracks; - (items.cast()).loop((e) => queue.add(e.path)); - break; case const (TrackWithDate): type = LibraryCategory.localTracks; - (items.cast()).loop((e) => queue.add(e.track.path)); + items.loop((e) => queue.add((e as Selectable).track.path)); break; + case const (YoutubeID): type = LibraryCategory.youtube; (items.cast()).loop((e) => queue.add(e.toJson())); diff --git a/lib/core/namida_converter_ext.dart b/lib/core/namida_converter_ext.dart index cb612c25..37130d15 100644 --- a/lib/core/namida_converter_ext.dart +++ b/lib/core/namida_converter_ext.dart @@ -467,9 +467,15 @@ extension OnYoutubeLinkOpenActionUtils on OnYoutubeLinkOpenAction { Future executePlaylist(String playlistUrl, {YoutubePlaylist? playlist, required BuildContext? context}) async { final plInfo = playlist ?? await YoutubeController.inst.getPlaylistInfo(playlistUrl); - if (plInfo == null) return snackyy(title: lang.ERROR, message: 'error retrieving playlist info, check your connection?'); + if (plInfo == null) { + snackyy(title: lang.ERROR, message: 'error retrieving playlist info, check your connection?'); + return; + } final didFetch = await plInfo.fetchAllPlaylistStreams(context: context?.mounted == true ? context : null); - if (!didFetch) return snackyy(title: lang.ERROR, message: 'error fetching playlist videos'); + if (!didFetch) { + snackyy(title: lang.ERROR, message: 'error fetching playlist videos'); + return; + } final streams = plInfo.streams; diff --git a/lib/packages/miniplayer_base.dart b/lib/packages/miniplayer_base.dart index 14442d3d..38472732 100644 --- a/lib/packages/miniplayer_base.dart +++ b/lib/packages/miniplayer_base.dart @@ -140,6 +140,24 @@ class _NamidaMiniPlayerBaseState extends State> { } } + SnackbarController? _latestSnacky; + void _onRemoveFromQueue(int index) { + _latestSnacky?.close(); + final item = Player.inst.currentQueue.value[index]; + Player.inst.removeFromQueue(index); + _latestSnacky = snackyy( + icon: Broken.rotate_left, + title: lang.UNDO_CHANGES, + message: lang.UNDO_CHANGES_DELETED_TRACK, + displaySeconds: 2, + top: false, + button: ( + lang.UNDO, + () => Player.inst.insertInQueue([item], index), + ), + ); + } + @override Widget build(BuildContext context) { final onSecondary = context.theme.colorScheme.onSecondaryContainer; @@ -337,7 +355,7 @@ class _NamidaMiniPlayerBaseState extends State> { return FadeDismissible( key: Key("Diss_${i}_${childWK.$2}_${queue.length}"), // queue length only for when removing current item and next is the same. onDismissed: (direction) { - Player.inst.removeFromQueue(i); + _onRemoveFromQueue(i); MiniPlayerController.inst.invokeDoneReordering(); }, onDismissStart: (_) => MiniPlayerController.inst.invokeStartReordering(), diff --git a/lib/ui/pages/onboarding.dart b/lib/ui/pages/onboarding.dart index 0291fe71..afb63574 100644 --- a/lib/ui/pages/onboarding.dart +++ b/lib/ui/pages/onboarding.dart @@ -251,7 +251,8 @@ class _FirstRunConfigureScreenState extends State { onTap: () async { await _requestPermission(); if (BackupController.inst.isRestoringBackup.value) { - return snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + return; } _navigateToNamida(); }, diff --git a/lib/ui/widgets/settings/backup_restore_settings.dart b/lib/ui/widgets/settings/backup_restore_settings.dart index 8a156087..416482ec 100644 --- a/lib/ui/widgets/settings/backup_restore_settings.dart +++ b/lib/ui/widgets/settings/backup_restore_settings.dart @@ -78,7 +78,8 @@ class BackupAndRestore extends SettingSubpageProvider { ), onTap: () async { if (BackupController.inst.isRestoringBackup.value) { - return snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + return; } NamidaNavigator.inst.navigateDialog( @@ -164,7 +165,8 @@ class BackupAndRestore extends SettingSubpageProvider { ), onTap: () { if (BackupController.inst.isCreatingBackup.value) { - return snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + snackyy(title: lang.NOTE, message: lang.ANOTHER_PROCESS_IS_RUNNING); + return; } bool isActive(List items) => items.every((element) => settings.backupItemslist.contains(element)); diff --git a/lib/ui/widgets/video_widget.dart b/lib/ui/widgets/video_widget.dart index a529ab2a..3589d3f4 100644 --- a/lib/ui/widgets/video_widget.dart +++ b/lib/ui/widgets/video_widget.dart @@ -1641,7 +1641,10 @@ class __SpeedsEditorDialogState extends State<_SpeedsEditorDialog> { ), child: InkWell( onTap: () { - if (e == 1.0) return snackyy(message: lang.ERROR); + if (e == 1.0) { + snackyy(message: lang.ERROR); // we already ignore tap but uh + return; + } if (settings.player.speeds.length <= 4) return showMinimumItemsSnack(4); settings.player.speeds diff --git a/lib/youtube/functions/yt_playlist_utils.dart b/lib/youtube/functions/yt_playlist_utils.dart index 760c4cf2..5f7fe199 100644 --- a/lib/youtube/functions/yt_playlist_utils.dart +++ b/lib/youtube/functions/yt_playlist_utils.dart @@ -243,7 +243,10 @@ extension YoutubePlaylistHostedUtils on yt.YoutubePlaylist { onTap: () async { final playlist = this; final didFetch = await playlist.fetchAllPlaylistStreams(context: context); - if (!didFetch) return snackyy(title: lang.ERROR, message: 'error fetching playlist videos'); + if (!didFetch) { + snackyy(title: lang.ERROR, message: 'error fetching playlist videos'); + return; + } final ids = []; final info = {}; diff --git a/pubspec.yaml b/pubspec.yaml index 72df68ad..b7d1bb9f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: namida description: A Beautiful and Feature-rich Music Player, With YouTube & Video Support Built in Flutter publish_to: "none" -version: 2.6.1-beta+240606012 +version: 2.6.2-beta+240606016 environment: sdk: ">=3.4.0 <4.0.0"