diff --git a/frontend/src/Activity/Queue/Queue.js b/frontend/src/Activity/Queue/Queue.js index c42c384c6..26c52a285 100644 --- a/frontend/src/Activity/Queue/Queue.js +++ b/frontend/src/Activity/Queue/Queue.js @@ -282,6 +282,17 @@ class Queue extends Component { return !!(item && item.movieId); }) )} + allPending={isConfirmRemoveModalOpen && ( + selectedIds.every((id) => { + const item = items.find((i) => i.id === id); + + if (!item) { + return false; + } + + return item.status === 'delay' || item.status === 'downloadClientUnavailable'; + }) + )} onRemovePress={this.onRemoveSelectedConfirmed} onModalClose={this.onConfirmRemoveModalClose} /> diff --git a/frontend/src/Activity/Queue/QueueRow.js b/frontend/src/Activity/Queue/QueueRow.js index ea4a8aab7..70a5b15ad 100644 --- a/frontend/src/Activity/Queue/QueueRow.js +++ b/frontend/src/Activity/Queue/QueueRow.js @@ -332,6 +332,7 @@ class QueueRow extends Component { isOpen={isRemoveQueueItemModalOpen} sourceTitle={title} canIgnore={!!movie} + isPending={isPending} onRemovePress={this.onRemoveQueueItemModalConfirmed} onModalClose={this.onRemoveQueueItemModalClose} /> diff --git a/frontend/src/Activity/Queue/RemoveQueueItemModal.js b/frontend/src/Activity/Queue/RemoveQueueItemModal.js index fb039eb8e..2a150520d 100644 --- a/frontend/src/Activity/Queue/RemoveQueueItemModal.js +++ b/frontend/src/Activity/Queue/RemoveQueueItemModal.js @@ -66,7 +66,8 @@ class RemoveQueueItemModal extends Component { const { isOpen, sourceTitle, - canIgnore + canIgnore, + isPending } = this.props; const { remove, blocklist } = this.state; @@ -89,18 +90,22 @@ class RemoveQueueItemModal extends Component { {translate('RemoveFromQueueText', [sourceTitle])} - - {translate('RemoveFromDownloadClient')} + { + isPending ? + null : + + {translate('RemoveFromDownloadClient')} - - + + + } {translate('BlocklistRelease')} @@ -137,6 +142,7 @@ RemoveQueueItemModal.propTypes = { isOpen: PropTypes.bool.isRequired, sourceTitle: PropTypes.string.isRequired, canIgnore: PropTypes.bool.isRequired, + isPending: PropTypes.bool.isRequired, onRemovePress: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired }; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js index e75456f4c..073e00f04 100644 --- a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js +++ b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js @@ -67,7 +67,8 @@ class RemoveQueueItemsModal extends Component { const { isOpen, selectedCount, - canIgnore + canIgnore, + allPending } = this.props; const { remove, blocklist } = this.state; @@ -90,18 +91,22 @@ class RemoveQueueItemsModal extends Component { {translate('AreYouSureYouWantToRemoveSelectedItemsFromQueue', [selectedCount, selectedCount > 1 ? 's' : ''])} - - {translate('RemoveFromDownloadClient')} + { + allPending ? + null : + + {translate('RemoveFromDownloadClient')} - - + + + } @@ -141,6 +146,7 @@ RemoveQueueItemsModal.propTypes = { isOpen: PropTypes.bool.isRequired, selectedCount: PropTypes.number.isRequired, canIgnore: PropTypes.bool.isRequired, + allPending: PropTypes.bool.isRequired, onRemovePress: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired }; diff --git a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs index 0a32b2bfe..c22c94a3c 100644 --- a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs +++ b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs @@ -17,6 +17,7 @@ public interface IBlocklistService bool Blocklisted(int movieId, ReleaseInfo release); PagingSpec Paged(PagingSpec pagingSpec); List GetByMovieId(int movieId); + void Block(RemoteMovie remoteMovie, string message); void Delete(int id); void Delete(List ids); } @@ -72,6 +73,29 @@ public List GetByMovieId(int movieId) return _blocklistRepository.BlocklistedByMovie(movieId); } + public void Block(RemoteMovie remoteMovie, string message) + { + var blocklist = new Blocklist + { + MovieId = remoteMovie.Movie.Id, + SourceTitle = remoteMovie.Release.Title, + Quality = remoteMovie.ParsedMovieInfo.Quality, + Date = DateTime.UtcNow, + PublishedDate = remoteMovie.Release.PublishDate, + Size = remoteMovie.Release.Size, + Indexer = remoteMovie.Release.Indexer, + Protocol = remoteMovie.Release.DownloadProtocol, + Message = message + }; + + if (remoteMovie.Release is TorrentInfo torrentRelease) + { + blocklist.TorrentInfoHash = torrentRelease.InfoHash; + } + + _blocklistRepository.Insert(blocklist); + } + public void Delete(int id) { _blocklistRepository.Delete(id); diff --git a/src/Radarr.Api.V3/Queue/QueueController.cs b/src/Radarr.Api.V3/Queue/QueueController.cs index 0d5544249..0fbfec6e9 100644 --- a/src/Radarr.Api.V3/Queue/QueueController.cs +++ b/src/Radarr.Api.V3/Queue/QueueController.cs @@ -3,6 +3,7 @@ using System.Linq; using Microsoft.AspNetCore.Mvc; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Blocklisting; using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.Download; @@ -33,6 +34,7 @@ public class QueueController : RestControllerWithSignalR