From 4a21249ee386426b0974451542a93e84f532fb3f Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Thu, 8 Jun 2023 09:03:18 +0600 Subject: [PATCH] fix: replace download multiple pops and add translations --- .../dialogs/replace_downloaded_dialog.dart | 34 +++++++++------- lib/l10n/app_en.arb | 8 +++- lib/pages/root/root_app.dart | 40 ++++++++++++++----- lib/provider/download_manager_provider.dart | 14 +++++++ 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/lib/components/shared/dialogs/replace_downloaded_dialog.dart b/lib/components/shared/dialogs/replace_downloaded_dialog.dart index a0d019868..777210411 100644 --- a/lib/components/shared/dialogs/replace_downloaded_dialog.dart +++ b/lib/components/shared/dialogs/replace_downloaded_dialog.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; +import 'package:spotube/extensions/context.dart'; final replaceDownloadedFileState = StateProvider((ref) => null); @@ -14,13 +15,14 @@ class ReplaceDownloadedDialog extends ConsumerWidget { Widget build(BuildContext context, ref) { final groupValue = ref.watch(replaceDownloadedFileState); final theme = Theme.of(context); + final replaceAll = ref.watch(replaceDownloadedFileState); return AlertDialog( - title: Text("Track ${track.name} Already Exists"), + title: Text(context.l10n.track_exists(track.name ?? "")), content: Column( mainAxisSize: MainAxisSize.min, children: [ - const Text("Do you want to replace the already downloaded track?"), + Text(context.l10n.do_you_want_to_replace), RadioListTile( dense: true, contentPadding: EdgeInsets.zero, @@ -29,10 +31,10 @@ class ReplaceDownloadedDialog extends ConsumerWidget { groupValue: groupValue, onChanged: (value) { if (value != null) { - ref.read(replaceDownloadedFileState.notifier).state = value; + ref.read(replaceDownloadedFileState.notifier).state = true; } }, - title: const Text("Replace all downloaded tracks"), + title: Text(context.l10n.replace_downloaded_tracks), ), RadioListTile( dense: true, @@ -42,25 +44,29 @@ class ReplaceDownloadedDialog extends ConsumerWidget { groupValue: groupValue, onChanged: (value) { if (value != null) { - ref.read(replaceDownloadedFileState.notifier).state = value; + ref.read(replaceDownloadedFileState.notifier).state = false; } }, - title: const Text("Skip downloading all downloaded tracks"), + title: Text(context.l10n.skip_download_tracks), ), ], ), actions: [ OutlinedButton( - child: const Text("No"), - onPressed: () { - Navigator.pop(context, false); - }, + onPressed: replaceAll == true + ? null + : () { + Navigator.pop(context, false); + }, + child: Text(context.l10n.skip), ), FilledButton( - child: const Text("Yes"), - onPressed: () { - Navigator.pop(context, true); - }, + onPressed: replaceAll == false + ? null + : () { + Navigator.pop(context, true); + }, + child: Text(context.l10n.replace), ), ], ); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5492ce384..60b5b3393 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -185,5 +185,11 @@ "something_went_wrong": "Something went wrong", "piped_instance": "Piped Server Instance", "piped_description": "The Piped server instance to use for track matching\nSome of them might not work well. So use at your own risk", - "generate_playlist": "Generate Playlist" + "generate_playlist": "Generate Playlist", + "track_exists": "Track {track} already exists", + "replace_downloaded_tracks": "Replace all downloaded tracks", + "skip_download_tracks": "Skip downloading all downloaded tracks", + "do_you_want_to_replace": "Do you want to replace the existing track??", + "replace": "Replace", + "skip": "Skip" } \ No newline at end of file diff --git a/lib/pages/root/root_app.dart b/lib/pages/root/root_app.dart index f520bf005..930c7f55f 100644 --- a/lib/pages/root/root_app.dart +++ b/lib/pages/root/root_app.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -9,7 +11,6 @@ import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/components/root/spotube_navigation_bar.dart'; import 'package:spotube/hooks/use_update_checker.dart'; import 'package:spotube/provider/download_manager_provider.dart'; -import 'package:spotube/provider/authentication_provider.dart'; const rootPaths = { 0: "/", @@ -29,19 +30,38 @@ class RootApp extends HookConsumerWidget { Widget build(BuildContext context, ref) { final index = useState(0); final isMounted = useIsMounted(); - final auth = ref.watch(AuthenticationNotifier.provider); - + final showingDialogCompleter = useRef(Completer()..complete()); final downloader = ref.watch(downloadManagerProvider.notifier); + useEffect(() { downloader.onFileExists = (track) async { if (!isMounted()) return false; - return await showDialog( - context: context, - builder: (context) => ReplaceDownloadedDialog( - track: track, - ), - ) ?? - false; + + if (!showingDialogCompleter.value.isCompleted) { + await showingDialogCompleter.value.future; + } + + final replaceAll = ref.read(replaceDownloadedFileState); + + if (replaceAll != null) return replaceAll; + + showingDialogCompleter.value = Completer(); + + if (context.mounted) { + final result = await showDialog( + context: context, + builder: (context) => ReplaceDownloadedDialog( + track: track, + ), + ) ?? + false; + + showingDialogCompleter.value.complete(); + return result; + } + + // it'll never reach here as root_app is always mounted + return false; }; return null; }, [downloader]); diff --git a/lib/provider/download_manager_provider.dart b/lib/provider/download_manager_provider.dart index 90e860645..4ad2ed948 100644 --- a/lib/provider/download_manager_provider.dart +++ b/lib/provider/download_manager_provider.dart @@ -49,6 +49,12 @@ class DownloadManagerProvider extends StateNotifier> { if (update.status == TaskStatus.complete) { final track = state.firstWhere((element) => element.id == update.task.taskId); + + // resetting the replace downloaded file state on queue completion + if (state.last == track) { + ref.read(replaceDownloadedFileState.notifier).state = null; + } + state = state .where((element) => element.id != update.task.taskId) .toList(); @@ -141,6 +147,9 @@ class DownloadManagerProvider extends StateNotifier> { final file = File(_getPathForTrack(track)); if (file.existsSync() && (replaceFileGlobal ?? await onFileExists?.call(track)) != true) { + if (state.isEmpty) { + ref.read(replaceDownloadedFileState.notifier).state = null; + } return null; } @@ -159,6 +168,11 @@ class DownloadManagerProvider extends StateNotifier> { } return enqueue(e); })); + + if (tasks.isEmpty) { + ref.read(replaceDownloadedFileState.notifier).state = null; + } + return tasks.whereType().toList(); }