同步相册云盘界面并完善相关交互
This commit is contained in:
@ -31,6 +31,7 @@ final class CloudTransferManager {
|
||||
private let photoSaver: any CloudPhotoSaving
|
||||
private let scenicIdProvider: () -> Int
|
||||
private var runningTasks: [String: Task<Void, Never>] = [:]
|
||||
private var operationGenerations: [String: Int] = [:]
|
||||
|
||||
/// 初始化传输管理器。
|
||||
init(
|
||||
@ -95,6 +96,7 @@ final class CloudTransferManager {
|
||||
func pauseUpload(id: String) {
|
||||
runningTasks[id]?.cancel()
|
||||
runningTasks[id] = nil
|
||||
invalidateOperation(id: id)
|
||||
updateUploadTask(id: id) { task in
|
||||
task.status = .paused
|
||||
task.updatedAt = Date().timeIntervalSince1970
|
||||
@ -110,6 +112,7 @@ final class CloudTransferManager {
|
||||
func cancelUpload(id: String) {
|
||||
runningTasks[id]?.cancel()
|
||||
runningTasks[id] = nil
|
||||
operationGenerations[id] = nil
|
||||
if let task = uploadTasks.first(where: { $0.id == id }), !task.localPath.isEmpty {
|
||||
try? FileManager.default.removeItem(atPath: task.localPath)
|
||||
}
|
||||
@ -121,6 +124,7 @@ final class CloudTransferManager {
|
||||
func pauseDownload(id: String) {
|
||||
runningTasks[id]?.cancel()
|
||||
runningTasks[id] = nil
|
||||
invalidateOperation(id: id)
|
||||
updateDownloadTask(id: id) { task in
|
||||
task.status = .paused
|
||||
task.updatedAt = Date().timeIntervalSince1970
|
||||
@ -136,6 +140,7 @@ final class CloudTransferManager {
|
||||
func cancelDownload(id: String) {
|
||||
runningTasks[id]?.cancel()
|
||||
runningTasks[id] = nil
|
||||
operationGenerations[id] = nil
|
||||
downloadTasks.removeAll { $0.id == id }
|
||||
persistAndNotify()
|
||||
}
|
||||
@ -149,6 +154,7 @@ final class CloudTransferManager {
|
||||
uploadTasks[index].progress = max(uploadTasks[index].progress, 1)
|
||||
uploadTasks[index].updatedAt = Date().timeIntervalSince1970
|
||||
let seed = uploadTasks[index]
|
||||
let generation = nextOperationGeneration(id: id)
|
||||
persistAndNotify()
|
||||
|
||||
runningTasks[id] = Task { [weak self] in
|
||||
@ -166,24 +172,30 @@ final class CloudTransferManager {
|
||||
scenicId: scenicIdProvider()
|
||||
) { [weak self] progress in
|
||||
Task { @MainActor in
|
||||
self?.updateUploadProgress(id: id, progress: progress)
|
||||
guard let self, self.isCurrentOperation(id: id, generation: generation) else { return }
|
||||
self.updateUploadProgress(id: id, progress: progress)
|
||||
}
|
||||
}
|
||||
try Task.checkCancellation()
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
try await api.uploadCloudFile(
|
||||
parentFolderId: seed.parentFolderId,
|
||||
fileUrl: uploadedURL,
|
||||
fileName: seed.fileName
|
||||
)
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
try? FileManager.default.removeItem(atPath: seed.localPath)
|
||||
runningTasks[id] = nil
|
||||
operationGenerations[id] = nil
|
||||
uploadTasks.removeAll { $0.id == id }
|
||||
persistAndNotify()
|
||||
onUploadCompleted?(seed.parentFolderId)
|
||||
} catch is CancellationError {
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
runningTasks[id] = nil
|
||||
markUploadPaused(id: id)
|
||||
} catch {
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
runningTasks[id] = nil
|
||||
markUploadFailed(id: id, message: error.localizedDescription)
|
||||
}
|
||||
@ -199,6 +211,7 @@ final class CloudTransferManager {
|
||||
downloadTasks[index].progress = max(downloadTasks[index].progress, 1)
|
||||
downloadTasks[index].updatedAt = Date().timeIntervalSince1970
|
||||
let seed = downloadTasks[index]
|
||||
let generation = nextOperationGeneration(id: id)
|
||||
persistAndNotify()
|
||||
|
||||
runningTasks[id] = Task { [weak self] in
|
||||
@ -209,22 +222,28 @@ final class CloudTransferManager {
|
||||
fileName: seed.fileName
|
||||
) { [weak self] progress in
|
||||
Task { @MainActor in
|
||||
self?.updateDownloadProgress(id: id, progress: progress)
|
||||
guard let self, self.isCurrentOperation(id: id, generation: generation) else { return }
|
||||
self.updateDownloadProgress(id: id, progress: progress)
|
||||
}
|
||||
}
|
||||
try Task.checkCancellation()
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
try await photoSaver.saveToPhotoLibrary(fileURL: localURL, fileType: seed.fileType)
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
try? FileManager.default.removeItem(at: localURL)
|
||||
runningTasks[id] = nil
|
||||
operationGenerations[id] = nil
|
||||
updateDownloadTask(id: id) { task in
|
||||
task.status = .completed
|
||||
task.progress = 100
|
||||
task.updatedAt = Date().timeIntervalSince1970
|
||||
}
|
||||
} catch is CancellationError {
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
runningTasks[id] = nil
|
||||
markDownloadPaused(id: id)
|
||||
} catch {
|
||||
guard isCurrentOperation(id: id, generation: generation) else { return }
|
||||
runningTasks[id] = nil
|
||||
markDownloadFailed(id: id, message: error.localizedDescription)
|
||||
}
|
||||
@ -291,6 +310,20 @@ final class CloudTransferManager {
|
||||
store.saveTasks(uploadTasks + downloadTasks)
|
||||
onTasksChange?()
|
||||
}
|
||||
|
||||
private func nextOperationGeneration(id: String) -> Int {
|
||||
let generation = (operationGenerations[id] ?? 0) + 1
|
||||
operationGenerations[id] = generation
|
||||
return generation
|
||||
}
|
||||
|
||||
private func invalidateOperation(id: String) {
|
||||
operationGenerations[id] = (operationGenerations[id] ?? 0) + 1
|
||||
}
|
||||
|
||||
private func isCurrentOperation(id: String, generation: Int) -> Bool {
|
||||
operationGenerations[id] == generation
|
||||
}
|
||||
}
|
||||
|
||||
private extension Comparable {
|
||||
|
||||
Reference in New Issue
Block a user