diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index ed589607..efe0fee1 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -6220,6 +6220,12 @@ abstract class AppLocalizations { /// **'Finalizing download'** String get queueFinalizingDownload; + /// Tooltip on a queued download row; moves the item to the front of the queue so the next free slot downloads it + /// + /// In en, this message translates to: + /// **'Download next'** + String get queueDownloadNext; + /// Accessibility label when a downloaded file is missing from disk /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_ar.dart b/lib/l10n/app_localizations_ar.dart index 9b70a5fc..421d24a6 100644 --- a/lib/l10n/app_localizations_ar.dart +++ b/lib/l10n/app_localizations_ar.dart @@ -3739,6 +3739,9 @@ class AppLocalizationsAr extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index d9ef00f9..29818e79 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -3785,6 +3785,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get queueFinalizingDownload => 'Download wird abgeschlossen'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Heruntergeladene Datei fehlt'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index c0110ccc..60276f4d 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -3739,6 +3739,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 77bf9c6f..1b91ff23 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -3733,6 +3733,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index a719fac8..afd89e3a 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -3839,6 +3839,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get queueFinalizingDownload => 'Téléchargement en cours'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Fichier téléchargé manquant'; diff --git a/lib/l10n/app_localizations_hi.dart b/lib/l10n/app_localizations_hi.dart index 225479f2..c538b0d4 100644 --- a/lib/l10n/app_localizations_hi.dart +++ b/lib/l10n/app_localizations_hi.dart @@ -3739,6 +3739,9 @@ class AppLocalizationsHi extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_id.dart b/lib/l10n/app_localizations_id.dart index 687692f0..6680a237 100644 --- a/lib/l10n/app_localizations_id.dart +++ b/lib/l10n/app_localizations_id.dart @@ -3742,6 +3742,9 @@ class AppLocalizationsId extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 105eb39f..b4a6cc18 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -3728,6 +3728,9 @@ class AppLocalizationsJa extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 642f7099..f93ff46e 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -3630,6 +3630,9 @@ class AppLocalizationsKo extends AppLocalizations { @override String get queueFinalizingDownload => '다운로드를 마무리하는 중'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => '다운로드한 파일이 없음'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index f3e2f081..6426b901 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -3739,6 +3739,9 @@ class AppLocalizationsNl extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 359f286d..c00a0dfe 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -3733,6 +3733,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index 7a3cc7c1..1c0759aa 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -3770,6 +3770,9 @@ class AppLocalizationsRu extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_tr.dart b/lib/l10n/app_localizations_tr.dart index 7c7e553d..dd8a7636 100644 --- a/lib/l10n/app_localizations_tr.dart +++ b/lib/l10n/app_localizations_tr.dart @@ -3769,6 +3769,9 @@ class AppLocalizationsTr extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index e1f67601..d7d012c2 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -3787,6 +3787,9 @@ class AppLocalizationsUk extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 487305c9..bff28bbc 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -3733,6 +3733,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get queueFinalizingDownload => 'Finalizing download'; + @override + String get queueDownloadNext => 'Download next'; + @override String get queueDownloadedFileMissing => 'Downloaded file missing'; diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index a22b9cb9..a843e79b 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -4845,6 +4845,10 @@ "@queueFinalizingDownload": { "description": "Accessibility label for a queue item that is finalizing" }, + "queueDownloadNext": "Download next", + "@queueDownloadNext": { + "description": "Tooltip on a queued download row; moves the item to the front of the queue so the next free slot downloads it" + }, "queueDownloadedFileMissing": "Downloaded file missing", "@queueDownloadedFileMissing": { "description": "Accessibility label when a downloaded file is missing from disk" diff --git a/lib/providers/download_queue_provider.dart b/lib/providers/download_queue_provider.dart index ddda39e7..8b8112f9 100644 --- a/lib/providers/download_queue_provider.dart +++ b/lib/providers/download_queue_provider.dart @@ -1670,6 +1670,26 @@ class DownloadQueueNotifier extends Notifier { } } + /// Reinserts a queued item ahead of all other queued items so the next + /// free download slot picks it up. During an active native worker run the + /// current batch keeps its order; the new order applies from the next run. + void downloadNext(String id) { + final items = state.items; + final index = items.indexWhere((item) => item.id == id); + if (index == -1) return; + final item = items[index]; + if (item.status != DownloadStatus.queued) return; + final firstQueuedIndex = items.indexWhere( + (candidate) => candidate.status == DownloadStatus.queued, + ); + if (firstQueuedIndex == index) return; + final reordered = List.from(items) + ..removeAt(index) + ..insert(firstQueuedIndex, item); + state = state.copyWith(items: reordered); + _saveQueueToStorage(); + } + void removeItem(String id) { final removedItem = state.items.where((item) => item.id == id).firstOrNull; _locallyCancelledItemIds.remove(id); diff --git a/lib/screens/queue_tab_item_widgets.dart b/lib/screens/queue_tab_item_widgets.dart index 8e66cd10..6b3f6a3e 100644 --- a/lib/screens/queue_tab_item_widgets.dart +++ b/lib/screens/queue_tab_item_widgets.dart @@ -486,14 +486,34 @@ extension _QueueTabItemWidgets on _QueueTabState { ) { switch (item.status) { case DownloadStatus.queued: - return IconButton( - onPressed: () => - ref.read(downloadQueueProvider.notifier).cancelItem(item.id), - icon: Icon(Icons.close, color: colorScheme.error), - tooltip: context.l10n.dialogCancel, - style: IconButton.styleFrom( - backgroundColor: colorScheme.errorContainer.withValues(alpha: 0.3), - ), + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: () => ref + .read(downloadQueueProvider.notifier) + .downloadNext(item.id), + icon: Icon(Icons.skip_next, color: colorScheme.primary), + tooltip: context.l10n.queueDownloadNext, + style: IconButton.styleFrom( + backgroundColor: colorScheme.primaryContainer.withValues( + alpha: 0.3, + ), + ), + ), + const SizedBox(width: 4), + IconButton( + onPressed: () => + ref.read(downloadQueueProvider.notifier).cancelItem(item.id), + icon: Icon(Icons.close, color: colorScheme.error), + tooltip: context.l10n.dialogCancel, + style: IconButton.styleFrom( + backgroundColor: colorScheme.errorContainer.withValues( + alpha: 0.3, + ), + ), + ), + ], ); case DownloadStatus.downloading: return IconButton(