diff --git a/lib/screens/queue_tab.dart b/lib/screens/queue_tab.dart index a6aa4113..d8e83d0c 100644 --- a/lib/screens/queue_tab.dart +++ b/lib/screens/queue_tab.dart @@ -4200,28 +4200,9 @@ class _QueueTabState extends ConsumerState { final filteredGroupedAlbums = filterData.filteredGroupedAlbums; final filteredGroupedLocalAlbums = filterData.filteredGroupedLocalAlbums; final unifiedItems = filterData.unifiedItems; - final filteredUnifiedItems = filterData.filteredUnifiedItems; + final allFilteredUnifiedItems = filterData.filteredUnifiedItems; final totalTrackCount = filterData.totalTrackCount; final totalAlbumCount = filterData.totalAlbumCount; - final downloadedNavigationItems = []; - final downloadedNavigationIndexByUnifiedId = {}; - final localNavigationItems = []; - final localNavigationIndexByUnifiedId = {}; - - for (final item in filteredUnifiedItems) { - final historyItem = item.historyItem; - if (historyItem != null) { - downloadedNavigationIndexByUnifiedId[item.id] = - downloadedNavigationItems.length; - downloadedNavigationItems.add(historyItem); - } - - final localItem = item.localItem; - if (localItem != null) { - localNavigationIndexByUnifiedId[item.id] = localNavigationItems.length; - localNavigationItems.add(localItem); - } - } final activeDownloadIds = filterMode == 'albums' ? const [] @@ -4243,18 +4224,29 @@ class _QueueTabState extends ConsumerState { .reversed .toList(growable: false); - final libIdSet = {for (final item in filteredUnifiedItems) item.id}; + final libIdSet = { + for (final item in allFilteredUnifiedItems) item.id, + }; List bridgeIds = const []; if (filterMode != 'albums' && _completionBridge.isNotEmpty) { final now = DateTime.now(); final stale = []; final pending = []; + final hasActiveDownloads = activeDownloadIds.isNotEmpty; _completionBridge.forEach((id, _) { final landed = libIdSet.contains('dl_$id'); final addedAt = _completionBridgeAt[id]; final expired = addedAt == null || now.difference(addedAt).inSeconds >= 6; - if (landed || expired || activeDownloadIds.contains(id)) { + if (activeDownloadIds.contains(id)) { + // Re-queued (retry) — the live row takes over from the bridge. + stale.add(id); + } else if (hasActiveDownloads) { + // Keep just-completed tracks pinned in the lead zone while the + // rest of the batch is still downloading, so they don't jump + // below the remaining queue the moment they finish. + pending.add(id); + } else if (landed || expired) { stale.add(id); } else { pending.add(id); @@ -4313,6 +4305,36 @@ class _QueueTabState extends ConsumerState { } } + // Tracks pinned as completion-bridge cells render in the lead zone; + // hide their history rows so they don't appear twice. + List filteredUnifiedItems = allFilteredUnifiedItems; + if (bridgeIds.isNotEmpty) { + final pinnedHistoryIds = {for (final id in bridgeIds) 'dl_$id'}; + filteredUnifiedItems = allFilteredUnifiedItems + .where((item) => !pinnedHistoryIds.contains(item.id)) + .toList(growable: false); + } + + final downloadedNavigationItems = []; + final downloadedNavigationIndexByUnifiedId = {}; + final localNavigationItems = []; + final localNavigationIndexByUnifiedId = {}; + + for (final item in filteredUnifiedItems) { + final historyItem = item.historyItem; + if (historyItem != null) { + downloadedNavigationIndexByUnifiedId[item.id] = + downloadedNavigationItems.length; + downloadedNavigationItems.add(historyItem); + } + + final localItem = item.localItem; + if (localItem != null) { + localNavigationIndexByUnifiedId[item.id] = localNavigationItems.length; + localNavigationItems.add(localItem); + } + } + final leadCount = activeDownloadIds.length + bridgeIds.length; final collectionEntries = filterMode == 'all' ? _getVisibleCollectionEntries(collectionState)