diff --git a/Sources/Firelink/ContentView.swift b/Sources/Firelink/ContentView.swift index 4261706..f0f3f26 100644 --- a/Sources/Firelink/ContentView.swift +++ b/Sources/Firelink/ContentView.swift @@ -84,6 +84,15 @@ struct ContentView: View { } } + ToolbarItem { + Button { + controller.pauseActiveDownloads(queueID: queueID) + } label: { + Label("Stop Downloads", systemImage: "stop.fill") + } + .disabled(!hasActiveDownloads(in: queueID)) + } + ToolbarItemGroup { if !selectedItems.isEmpty { if selectedItems.contains(where: { $0.status == .downloading }) { @@ -173,6 +182,14 @@ struct ContentView: View { selection = Set(items.map { $0.id }) } + private func hasActiveDownloads(in queueID: UUID?) -> Bool { + if let queueID { + return controller.downloads.contains { $0.status == .downloading && $0.queueID == queueID } + } + + return controller.activeCount > 0 + } + private func filteredDownloads(for filter: DownloadSidebarFilter) -> [DownloadItem] { switch filter { case .all: diff --git a/Sources/Firelink/DownloadController.swift b/Sources/Firelink/DownloadController.swift index af58f54..e71e3fc 100644 --- a/Sources/Firelink/DownloadController.swift +++ b/Sources/Firelink/DownloadController.swift @@ -189,6 +189,31 @@ final class DownloadController: ObservableObject { pumpQueue() } + func pauseActiveDownloads(queueID: UUID? = nil) { + let targetQueueID = queueID.map(normalizedQueueID) + let activeItems = downloads.filter { item in + item.status == .downloading && (targetQueueID == nil || item.queueID == targetQueueID) + } + + guard !activeItems.isEmpty else { return } + + for item in activeItems { + activeHandles[item.id]?.cancel() + activeHandles[item.id] = nil + update(item.id) { + $0.status = .paused + $0.message = "Paused. Resume will continue from the partial file." + $0.autoResumeOnLaunch = false + } + automaticRetryCounts[item.id] = nil + } + + engineMessage = "Paused \(activeItems.count) active download\(activeItems.count == 1 ? "" : "s")." + saveDownloads() + updateSleepActivity() + pumpQueue() + } + func queue(_ item: DownloadItem) { activeHandles[item.id]?.cancel() activeHandles[item.id] = nil diff --git a/Sources/Firelink/FirelinkApp.swift b/Sources/Firelink/FirelinkApp.swift index cfab8de..e5f518d 100644 --- a/Sources/Firelink/FirelinkApp.swift +++ b/Sources/Firelink/FirelinkApp.swift @@ -63,6 +63,11 @@ struct FirelinkApp: App { controller.startQueue() } .keyboardShortcut("r", modifiers: [.command]) + + Button("Stop Downloads") { + controller.pauseActiveDownloads() + } + .disabled(controller.activeCount == 0) } }