diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index cf6c9e24..fb6d384f 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -3074,6 +3074,30 @@ abstract class AppLocalizations { /// **'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'** String get settingsDownloadNetworkSubtitle; + /// Setting title - how many tracks download at the same time + /// + /// In en, this message translates to: + /// **'Concurrent downloads'** + String get settingsConcurrentDownloads; + + /// Subtitle explaining the concurrent downloads picker + /// + /// In en, this message translates to: + /// **'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'** + String get settingsConcurrentDownloadsSubtitle; + + /// Concurrent downloads option - sequential + /// + /// In en, this message translates to: + /// **'1 track at a time'** + String get concurrentDownloadsOne; + + /// Concurrent downloads option - parallel + /// + /// In en, this message translates to: + /// **'Up to {count} tracks at once'** + String concurrentDownloadsCount(int count); + /// Album folder option /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_ar.dart b/lib/l10n/app_localizations_ar.dart index 6ed4a9c2..b48f479f 100644 --- a/lib/l10n/app_localizations_ar.dart +++ b/lib/l10n/app_localizations_ar.dart @@ -1658,6 +1658,21 @@ class AppLocalizationsAr extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 9e8362e0..5cf13fea 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -1683,6 +1683,21 @@ class AppLocalizationsDe extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Wähle aus, welches Netzwerk für Downloads verwendet werden soll. Wenn nur WLAN aktiviert wird, werden Downloads auf mobilen Daten angehalten.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Künstler/Album'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 48cf7463..baa78d81 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1658,6 +1658,21 @@ class AppLocalizationsEn extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 353bb1aa..bc9af73e 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -1658,6 +1658,21 @@ class AppLocalizationsEs extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index e6a8ad3b..3c27b45d 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -1706,6 +1706,21 @@ class AppLocalizationsFr extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choisissez le réseau à utiliser pour les téléchargements. Si vous sélectionnez « Wi-Fi uniquement », les téléchargements seront interrompus lorsque vous utilisez les données mobiles.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artiste / Album'; diff --git a/lib/l10n/app_localizations_hi.dart b/lib/l10n/app_localizations_hi.dart index 4200b1f8..50eca464 100644 --- a/lib/l10n/app_localizations_hi.dart +++ b/lib/l10n/app_localizations_hi.dart @@ -1658,6 +1658,21 @@ class AppLocalizationsHi extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/app_localizations_id.dart b/lib/l10n/app_localizations_id.dart index 79039cff..8a255c85 100644 --- a/lib/l10n/app_localizations_id.dart +++ b/lib/l10n/app_localizations_id.dart @@ -1664,6 +1664,21 @@ class AppLocalizationsId extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Pilih jaringan mana yang akan digunakan untuk mengunduh. Jika diatur ke Hanya WiFi, unduhan akan berhenti sementara dan menggunakan data seluler.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artis / Album'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 39f1eab2..51110a4f 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -1646,6 +1646,21 @@ class AppLocalizationsJa extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'アーティスト / アルバム'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 6394315b..47a26a22 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -1643,6 +1643,21 @@ class AppLocalizationsKo extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 038d26f2..bed1c885 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -1658,6 +1658,21 @@ class AppLocalizationsNl extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 0e2dcdfd..f4b4d29d 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -1658,6 +1658,21 @@ class AppLocalizationsPt extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index b421bf75..47490bc0 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -1681,6 +1681,21 @@ class AppLocalizationsRu extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Выберите, какую сеть использовать для скачивания. Когда установлено значение только WiFi — скачивания через мобильную сеть будут приостановлены.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Исполнитель / Альбом'; diff --git a/lib/l10n/app_localizations_tr.dart b/lib/l10n/app_localizations_tr.dart index 3614bee6..4d8ba404 100644 --- a/lib/l10n/app_localizations_tr.dart +++ b/lib/l10n/app_localizations_tr.dart @@ -1677,6 +1677,21 @@ class AppLocalizationsTr extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'İndirmeler için hangi ağın kullanılacağını seçin. Yalnızca WiFi olarak ayarlandığında, mobil veriye geçildiğinde indirmeler duraklatılır.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Sanatçı / Albüm'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index 15b78e16..4f8fcd15 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -1684,6 +1684,21 @@ class AppLocalizationsUk extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Вибрати мережу для завантажень. Якщо встановлено значення «Тільки Wi-Fi», завантаження призупиняться через мобільні дані.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Артист / Альбом'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 7aca1bda..a62d4389 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -1658,6 +1658,21 @@ class AppLocalizationsZh extends AppLocalizations { String get settingsDownloadNetworkSubtitle => 'Choose which network to use for downloads. When set to WiFi Only, downloads will pause on mobile data.'; + @override + String get settingsConcurrentDownloads => 'Concurrent downloads'; + + @override + String get settingsConcurrentDownloadsSubtitle => + 'Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.'; + + @override + String get concurrentDownloadsOne => '1 track at a time'; + + @override + String concurrentDownloadsCount(int count) { + return 'Up to $count tracks at once'; + } + @override String get albumFolderArtistAlbum => 'Artist / Album'; diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 6f913b8a..4ba721f4 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -2175,6 +2175,27 @@ "@settingsDownloadNetworkSubtitle": { "description": "Subtitle explaining network preference" }, + "settingsConcurrentDownloads": "Concurrent downloads", + "@settingsConcurrentDownloads": { + "description": "Setting title - how many tracks download at the same time" + }, + "settingsConcurrentDownloadsSubtitle": "Downloading several tracks at once is faster, but some providers may rate-limit parallel requests.", + "@settingsConcurrentDownloadsSubtitle": { + "description": "Subtitle explaining the concurrent downloads picker" + }, + "concurrentDownloadsOne": "1 track at a time", + "@concurrentDownloadsOne": { + "description": "Concurrent downloads option - sequential" + }, + "concurrentDownloadsCount": "Up to {count} tracks at once", + "@concurrentDownloadsCount": { + "description": "Concurrent downloads option - parallel", + "placeholders": { + "count": { + "type": "int" + } + } + }, "albumFolderArtistAlbum": "Artist / Album", "@albumFolderArtistAlbum": { "description": "Album folder option" diff --git a/lib/models/settings.dart b/lib/models/settings.dart index eb386a2e..e505bad6 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -62,6 +62,8 @@ class AppSettings { songLinkRegion; // SongLink userCountry region code used for platform lookup final bool nativeDownloadWorkerEnabled; // Experimental Android service-owned worker + final int + concurrentDownloads; // Max simultaneous downloads in the Dart queue (1-3) final bool localLibraryEnabled; final String localLibraryPath; @@ -140,6 +142,7 @@ class AppSettings { this.allowLocalNetwork = false, this.songLinkRegion = 'US', this.nativeDownloadWorkerEnabled = false, + this.concurrentDownloads = 1, this.localLibraryEnabled = false, this.localLibraryPath = '', this.localLibraryBookmark = '', @@ -208,6 +211,7 @@ class AppSettings { bool? allowLocalNetwork, String? songLinkRegion, bool? nativeDownloadWorkerEnabled, + int? concurrentDownloads, bool? localLibraryEnabled, String? localLibraryPath, String? localLibraryBookmark, @@ -289,6 +293,7 @@ class AppSettings { songLinkRegion: songLinkRegion ?? this.songLinkRegion, nativeDownloadWorkerEnabled: nativeDownloadWorkerEnabled ?? this.nativeDownloadWorkerEnabled, + concurrentDownloads: concurrentDownloads ?? this.concurrentDownloads, localLibraryEnabled: localLibraryEnabled ?? this.localLibraryEnabled, localLibraryPath: localLibraryPath ?? this.localLibraryPath, localLibraryBookmark: localLibraryBookmark ?? this.localLibraryBookmark, diff --git a/lib/models/settings.g.dart b/lib/models/settings.g.dart index 293787dd..9ac1f0d8 100644 --- a/lib/models/settings.g.dart +++ b/lib/models/settings.g.dart @@ -62,6 +62,7 @@ AppSettings _$AppSettingsFromJson(Map json) => AppSettings( songLinkRegion: json['songLinkRegion'] as String? ?? 'US', nativeDownloadWorkerEnabled: json['nativeDownloadWorkerEnabled'] as bool? ?? false, + concurrentDownloads: (json['concurrentDownloads'] as num?)?.toInt() ?? 1, localLibraryEnabled: json['localLibraryEnabled'] as bool? ?? false, localLibraryPath: json['localLibraryPath'] as String? ?? '', localLibraryBookmark: json['localLibraryBookmark'] as String? ?? '', @@ -138,6 +139,7 @@ Map _$AppSettingsToJson( 'allowLocalNetwork': instance.allowLocalNetwork, 'songLinkRegion': instance.songLinkRegion, 'nativeDownloadWorkerEnabled': instance.nativeDownloadWorkerEnabled, + 'concurrentDownloads': instance.concurrentDownloads, 'localLibraryEnabled': instance.localLibraryEnabled, 'localLibraryPath': instance.localLibraryPath, 'localLibraryBookmark': instance.localLibraryBookmark, diff --git a/lib/providers/download_queue_provider.dart b/lib/providers/download_queue_provider.dart index f6b4734b..6b5acd33 100644 --- a/lib/providers/download_queue_provider.dart +++ b/lib/providers/download_queue_provider.dart @@ -3742,6 +3742,12 @@ class DownloadQueueNotifier extends Notifier { if (!Platform.isAndroid || !settings.nativeDownloadWorkerEnabled) { return false; } + if (settings.concurrentDownloads > 1) { + // The experimental native worker downloads strictly sequentially, so + // prefer the Dart queue when the user enabled concurrent downloads. + _log.i('Concurrent downloads enabled; skipping native worker'); + return false; + } if (!settings.useExtensionProviders) { return false; } @@ -5470,7 +5476,7 @@ class DownloadQueueNotifier extends Notifier { } try { - await _processQueueSequential(); + await _runQueueLoop(); } finally { if (iosDownloadBookmarkActive) { await PlatformBridge.stopAccessingIosBookmark(); @@ -5550,7 +5556,7 @@ class DownloadQueueNotifier extends Notifier { } } - Future _processQueueSequential() async { + Future _runQueueLoop() async { final activeDownloads = >{}; _startMultiProgressPolling(); @@ -5582,9 +5588,11 @@ class DownloadQueueNotifier extends Notifier { break; } - // One download at a time: only start the next item once the current - // download has finished, to stay within the API's single-request limit. - if (activeDownloads.isEmpty && + final maxConcurrent = ref + .read(settingsProvider) + .concurrentDownloads + .clamp(1, 3); + while (activeDownloads.length < maxConcurrent && queuedItems.isNotEmpty && !state.isPaused) { final item = queuedItems.removeAt(0); diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index a9b717c9..720502ab 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -613,6 +613,11 @@ class SettingsNotifier extends Notifier { _saveSettings(); } + void setConcurrentDownloads(int count) { + state = state.copyWith(concurrentDownloads: count.clamp(1, 3)); + _saveSettings(); + } + void setNetworkCompatibilityMode(bool enabled) { state = state.copyWith(networkCompatibilityMode: enabled); _saveSettings(); diff --git a/lib/screens/settings/download_settings_page.dart b/lib/screens/settings/download_settings_page.dart index c4a34081..af6c98e0 100644 --- a/lib/screens/settings/download_settings_page.dart +++ b/lib/screens/settings/download_settings_page.dart @@ -195,6 +195,20 @@ class _DownloadSettingsPageState extends ConsumerState { settings.downloadNetworkMode, ), ), + SettingsItem( + icon: Icons.dynamic_feed_outlined, + title: context.l10n.settingsConcurrentDownloads, + subtitle: settings.concurrentDownloads <= 1 + ? context.l10n.concurrentDownloadsOne + : context.l10n.concurrentDownloadsCount( + settings.concurrentDownloads, + ), + onTap: () => _showConcurrentDownloadsPicker( + context, + ref, + settings.concurrentDownloads, + ), + ), if (Platform.isAndroid) SettingsSwitchItem( icon: Icons.downloading_outlined, @@ -598,6 +612,73 @@ class _DownloadSettingsPageState extends ConsumerState { ); } + void _showConcurrentDownloadsPicker( + BuildContext context, + WidgetRef ref, + int current, + ) { + final colorScheme = Theme.of(context).colorScheme; + showModalBottomSheet( + context: context, + useRootNavigator: true, + backgroundColor: colorScheme.surfaceContainerHigh, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(28)), + ), + builder: (context) => SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(24, 24, 24, 8), + child: Text( + context.l10n.settingsConcurrentDownloads, + style: Theme.of( + context, + ).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(24, 0, 24, 16), + child: Text( + context.l10n.settingsConcurrentDownloadsSubtitle, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: colorScheme.onSurfaceVariant, + ), + ), + ), + for (final count in const [1, 2, 3]) + ListTile( + leading: Icon( + count == 1 + ? Icons.looks_one_outlined + : count == 2 + ? Icons.looks_two_outlined + : Icons.looks_3_outlined, + ), + title: Text( + count == 1 + ? context.l10n.concurrentDownloadsOne + : context.l10n.concurrentDownloadsCount(count), + ), + trailing: current == count + ? Icon(Icons.check, color: colorScheme.primary) + : null, + onTap: () { + ref + .read(settingsProvider.notifier) + .setConcurrentDownloads(count); + Navigator.pop(context); + }, + ), + const SizedBox(height: 16), + ], + ), + ), + ); + } + void _showSongLinkRegionPicker( BuildContext context, WidgetRef ref,