diff --git a/Ruddarr/Models/Queue/QueueItem.swift b/Ruddarr/Models/Queue/QueueItem.swift index 44417445..97ef94af 100644 --- a/Ruddarr/Models/Queue/QueueItem.swift +++ b/Ruddarr/Models/Queue/QueueItem.swift @@ -153,8 +153,17 @@ struct QueueItem: Codable, Identifiable, Equatable { } var progressLabel: String { - guard sizeleft > 0 else { return 100.formatted(.percent) } - return ((size - sizeleft) / size).formatted(.percent.precision(.fractionLength(1))) + progressFraction.formatted(.percent.precision(.fractionLength(1))) + } + + var progressFraction: Float { + guard size > 0 else { return sizeleft <= 0 ? 1 : 0 } + return min(max((size - sizeleft) / size, 0), 1) + } + + var isActivelyDownloading: Bool { + status == "downloading" || + trackedDownloadState == .downloading } var remainingLabel: String? { diff --git a/Ruddarr/Views/Activity/ActivityView+Toolbar.swift b/Ruddarr/Views/Activity/ActivityView+Toolbar.swift index 98754f8f..e94e1bf2 100644 --- a/Ruddarr/Views/Activity/ActivityView+Toolbar.swift +++ b/Ruddarr/Views/Activity/ActivityView+Toolbar.swift @@ -21,7 +21,7 @@ extension ActivityView { func updateSortDirection() { switch sort.option { - case .byAdded: + case .byAdded, .byProgress: sort.isAscending = false default: sort.isAscending = true diff --git a/Ruddarr/Views/Activity/QueueSort.swift b/Ruddarr/Views/Activity/QueueSort.swift index 8a042e9f..28a877df 100644 --- a/Ruddarr/Views/Activity/QueueSort.swift +++ b/Ruddarr/Views/Activity/QueueSort.swift @@ -15,11 +15,13 @@ struct QueueSort: Equatable { case byTitle case byAdded + case byProgress var label: some View { switch self { case .byTitle: Label("Title", systemImage: "textformat.abc") case .byAdded: Label("Added", systemImage: "calendar.badge.plus") + case .byProgress: Label("Progress", systemImage: "gauge") } } @@ -29,10 +31,33 @@ struct QueueSort: Equatable { lhs.titleLabel < rhs.titleLabel case .byAdded: lhs.added ?? Date.distantPast < rhs.added ?? Date.distantPast + case .byProgress: + lhs.progressFraction < rhs.progressFraction } } } + func isOrderedBefore(_ lhs: QueueItem, _ rhs: QueueItem) -> Bool { + switch option { + case .byProgress: + isProgressOrderedBefore(lhs, rhs) + default: + isAscending ? option.isOrderedBefore(lhs, rhs) : option.isOrderedBefore(rhs, lhs) + } + } + + private func isProgressOrderedBefore(_ lhs: QueueItem, _ rhs: QueueItem) -> Bool { + if lhs.isActivelyDownloading != rhs.isActivelyDownloading { + return lhs.isActivelyDownloading + } + + if lhs.progressFraction != rhs.progressFraction { + return isAscending ? lhs.progressFraction < rhs.progressFraction : lhs.progressFraction > rhs.progressFraction + } + + return lhs.titleLabel < rhs.titleLabel + } + var hasFilter: Bool { instance != .all || type != .all || diff --git a/Ruddarr/Views/ActivityView.swift b/Ruddarr/Views/ActivityView.swift index 8ac93bf9..7f6369c8 100644 --- a/Ruddarr/Views/ActivityView.swift +++ b/Ruddarr/Views/ActivityView.swift @@ -129,7 +129,7 @@ struct ActivityView: View { var items: [QueueItem] = grouped .flatMap { $0.value } - .sorted(by: sort.option.isOrderedBefore) + .sorted(by: sort.isOrderedBefore) if sort.instance != .all { items = items.filter { @@ -149,10 +149,6 @@ struct ActivityView: View { items = items.filter { $0.trackedDownloadStatus != .ok || $0.status == "warning" } } - if !sort.isAscending { - items = items.reversed() - } - withAnimation { self.items = items }