feat(download): preserve quality variants

This commit is contained in:
zarzet
2026-07-16 08:45:01 +07:00
parent 491998e5c5
commit 0961c09a6d
41 changed files with 545 additions and 75 deletions
@@ -4,8 +4,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotiflac_android/l10n/l10n.dart';
import 'package:spotiflac_android/models/track.dart';
import 'package:spotiflac_android/providers/library_collections_provider.dart';
import 'package:spotiflac_android/providers/settings_provider.dart';
import 'package:spotiflac_android/services/cover_cache_manager.dart';
import 'package:spotiflac_android/widgets/playlist_picker_sheet.dart';
import 'package:spotiflac_android/widgets/track_detail_actions.dart';
import 'package:spotiflac_android/utils/clickable_metadata.dart';
class TrackCollectionQuickActions extends ConsumerWidget {
@@ -64,6 +66,9 @@ class _TrackOptionsSheet extends ConsumerWidget {
final isInWishlist = ref.watch(
libraryCollectionsProvider.select((state) => state.isInWishlist(track)),
);
final allowQualityVariants = ref.watch(
settingsProvider.select((settings) => settings.allowQualityVariants),
);
return SafeArea(
child: ConstrainedBox(
@@ -163,6 +168,25 @@ class _TrackOptionsSheet extends ConsumerWidget {
color: colorScheme.outlineVariant.withValues(alpha: 0.5),
),
if (allowQualityVariants)
_OptionTile(
icon: Icons.download_outlined,
title: context.l10n.trackOptionDownloadQualityVariant,
onTap: () {
final rootContext = Navigator.of(
context,
rootNavigator: true,
).context;
Navigator.pop(context);
downloadSingleTrack(
rootContext,
ref,
track,
forceQualityPicker: true,
);
},
),
_OptionTile(
icon: isLoved ? Icons.favorite : Icons.favorite_border,
iconColor: isLoved ? colorScheme.error : null,
+20 -15
View File
@@ -19,6 +19,7 @@ void downloadSingleTrack(
String? recommendedService,
String? playlistName,
int? playlistPosition,
bool forceQualityPicker = false,
}) {
final settings = ref.read(settingsProvider);
@@ -29,7 +30,7 @@ void downloadSingleTrack(
);
}
if (settings.askQualityBeforeDownload) {
if (settings.askQualityBeforeDownload || forceQualityPicker) {
DownloadServicePicker.show(
context,
trackName: track.name,
@@ -115,9 +116,7 @@ void showQueuedSnackbar(BuildContext context, int added, int skipped) {
final message = skipped > 0
? context.l10n.discographySkippedDownloaded(added, skipped)
: context.l10n.snackbarAddedTracksToQueue(added);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(message)));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
}
/// Shared batch "add to queue" flow for detail screens: skips tracks already
@@ -139,18 +138,24 @@ Future<void> queueTracksSkippingDownloaded(
}) async {
if (tracks.isEmpty) return;
final settings = ref.read(settingsProvider);
final skipExisting =
settings.deduplicateDownloads && !settings.allowQualityVariants;
final historyLookups = tracks
.map(historyLookupForTrack)
.toList(growable: false);
final existingHistoryKeys = await ref.read(
downloadHistoryBatchExistsProvider(
HistoryBatchLookupRequest(historyLookups),
).future,
);
final existingHistoryKeys = skipExisting
? await ref.read(
downloadHistoryBatchExistsProvider(
HistoryBatchLookupRequest(historyLookups),
).future,
)
: const <String>{};
if (!context.mounted) return;
final settings = ref.read(settingsProvider);
final localLibState =
(settings.localLibraryEnabled && settings.localLibraryShowDuplicates)
(skipExisting &&
settings.localLibraryEnabled &&
settings.localLibraryShowDuplicates)
? ref.read(localLibraryProvider)
: null;
final tracksToQueue = <Track>[];
@@ -158,9 +163,9 @@ Future<void> queueTracksSkippingDownloaded(
for (var i = 0; i < tracks.length; i++) {
final track = tracks[i];
final isInHistory = existingHistoryKeys.contains(
historyLookups[i].lookupKey,
);
final isInHistory =
skipExisting &&
existingHistoryKeys.contains(historyLookups[i].lookupKey);
final isInLocal =
localLibState?.existsInLibrary(
isrc: track.isrc,
@@ -187,7 +192,7 @@ Future<void> queueTracksSkippingDownloaded(
return;
}
if (settings.askQualityBeforeDownload) {
if (settings.askQualityBeforeDownload || settings.allowQualityVariants) {
DownloadServicePicker.show(
context,
trackName: '${tracksToQueue.length} tracks',