mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
fix: replace download multiple pops and add translations
This commit is contained in:
parent
6752adc939
commit
4a21249ee3
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
|
import 'package:spotube/extensions/context.dart';
|
||||||
|
|
||||||
final replaceDownloadedFileState = StateProvider<bool?>((ref) => null);
|
final replaceDownloadedFileState = StateProvider<bool?>((ref) => null);
|
||||||
|
|
||||||
@ -14,13 +15,14 @@ class ReplaceDownloadedDialog extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final groupValue = ref.watch(replaceDownloadedFileState);
|
final groupValue = ref.watch(replaceDownloadedFileState);
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
final replaceAll = ref.watch(replaceDownloadedFileState);
|
||||||
|
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text("Track ${track.name} Already Exists"),
|
title: Text(context.l10n.track_exists(track.name ?? "")),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Text("Do you want to replace the already downloaded track?"),
|
Text(context.l10n.do_you_want_to_replace),
|
||||||
RadioListTile<bool>(
|
RadioListTile<bool>(
|
||||||
dense: true,
|
dense: true,
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
@ -29,10 +31,10 @@ class ReplaceDownloadedDialog extends ConsumerWidget {
|
|||||||
groupValue: groupValue,
|
groupValue: groupValue,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
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<bool>(
|
RadioListTile<bool>(
|
||||||
dense: true,
|
dense: true,
|
||||||
@ -42,25 +44,29 @@ class ReplaceDownloadedDialog extends ConsumerWidget {
|
|||||||
groupValue: groupValue,
|
groupValue: groupValue,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
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: [
|
actions: [
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
child: const Text("No"),
|
onPressed: replaceAll == true
|
||||||
onPressed: () {
|
? null
|
||||||
Navigator.pop(context, false);
|
: () {
|
||||||
},
|
Navigator.pop(context, false);
|
||||||
|
},
|
||||||
|
child: Text(context.l10n.skip),
|
||||||
),
|
),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
child: const Text("Yes"),
|
onPressed: replaceAll == false
|
||||||
onPressed: () {
|
? null
|
||||||
Navigator.pop(context, true);
|
: () {
|
||||||
},
|
Navigator.pop(context, true);
|
||||||
|
},
|
||||||
|
child: Text(context.l10n.replace),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -185,5 +185,11 @@
|
|||||||
"something_went_wrong": "Something went wrong",
|
"something_went_wrong": "Something went wrong",
|
||||||
"piped_instance": "Piped Server Instance",
|
"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",
|
"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"
|
||||||
}
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.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/components/root/spotube_navigation_bar.dart';
|
||||||
import 'package:spotube/hooks/use_update_checker.dart';
|
import 'package:spotube/hooks/use_update_checker.dart';
|
||||||
import 'package:spotube/provider/download_manager_provider.dart';
|
import 'package:spotube/provider/download_manager_provider.dart';
|
||||||
import 'package:spotube/provider/authentication_provider.dart';
|
|
||||||
|
|
||||||
const rootPaths = {
|
const rootPaths = {
|
||||||
0: "/",
|
0: "/",
|
||||||
@ -29,19 +30,38 @@ class RootApp extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final index = useState(0);
|
final index = useState(0);
|
||||||
final isMounted = useIsMounted();
|
final isMounted = useIsMounted();
|
||||||
final auth = ref.watch(AuthenticationNotifier.provider);
|
final showingDialogCompleter = useRef(Completer()..complete());
|
||||||
|
|
||||||
final downloader = ref.watch(downloadManagerProvider.notifier);
|
final downloader = ref.watch(downloadManagerProvider.notifier);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
downloader.onFileExists = (track) async {
|
downloader.onFileExists = (track) async {
|
||||||
if (!isMounted()) return false;
|
if (!isMounted()) return false;
|
||||||
return await showDialog<bool>(
|
|
||||||
context: context,
|
if (!showingDialogCompleter.value.isCompleted) {
|
||||||
builder: (context) => ReplaceDownloadedDialog(
|
await showingDialogCompleter.value.future;
|
||||||
track: track,
|
}
|
||||||
),
|
|
||||||
) ??
|
final replaceAll = ref.read(replaceDownloadedFileState);
|
||||||
false;
|
|
||||||
|
if (replaceAll != null) return replaceAll;
|
||||||
|
|
||||||
|
showingDialogCompleter.value = Completer();
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
final result = await showDialog<bool>(
|
||||||
|
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;
|
return null;
|
||||||
}, [downloader]);
|
}, [downloader]);
|
||||||
|
@ -49,6 +49,12 @@ class DownloadManagerProvider extends StateNotifier<List<SpotubeTrack>> {
|
|||||||
if (update.status == TaskStatus.complete) {
|
if (update.status == TaskStatus.complete) {
|
||||||
final track =
|
final track =
|
||||||
state.firstWhere((element) => element.id == update.task.taskId);
|
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
|
state = state
|
||||||
.where((element) => element.id != update.task.taskId)
|
.where((element) => element.id != update.task.taskId)
|
||||||
.toList();
|
.toList();
|
||||||
@ -141,6 +147,9 @@ class DownloadManagerProvider extends StateNotifier<List<SpotubeTrack>> {
|
|||||||
final file = File(_getPathForTrack(track));
|
final file = File(_getPathForTrack(track));
|
||||||
if (file.existsSync() &&
|
if (file.existsSync() &&
|
||||||
(replaceFileGlobal ?? await onFileExists?.call(track)) != true) {
|
(replaceFileGlobal ?? await onFileExists?.call(track)) != true) {
|
||||||
|
if (state.isEmpty) {
|
||||||
|
ref.read(replaceDownloadedFileState.notifier).state = null;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +168,11 @@ class DownloadManagerProvider extends StateNotifier<List<SpotubeTrack>> {
|
|||||||
}
|
}
|
||||||
return enqueue(e);
|
return enqueue(e);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (tasks.isEmpty) {
|
||||||
|
ref.read(replaceDownloadedFileState.notifier).state = null;
|
||||||
|
}
|
||||||
|
|
||||||
return tasks.whereType<Task>().toList();
|
return tasks.whereType<Task>().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user