修复边拍边传自动上传范围,并避免上传状态被旧快照回退。
拍后传输下载的历史照片切换模式后不再自动补传;刷新相机文件仅同步本地。重试上传后刷新单张状态,并忽略乱序 pipeline 通知导致的已上传回退。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -17,6 +17,7 @@ final class CameraTransferPipeline {
|
||||
private var uploadSink: (any CameraAssetUploadSink)?
|
||||
private var uploadEnabled = true
|
||||
private var activeUploadAssetIDs: Set<String> = []
|
||||
private var autoUploadEligibleAssetIDs: Set<String> = []
|
||||
private var pendingDeferredNotifyTask: Task<Void, Never>?
|
||||
private var lastDeferredNotifyDate = Date.distantPast
|
||||
private var lastNotifiedProgressByAssetID: [String: Int] = [:]
|
||||
@ -67,12 +68,13 @@ final class CameraTransferPipeline {
|
||||
/// 重试所有失败的上传任务。
|
||||
func retryFailedUploads() async {
|
||||
guard uploadEnabled, uploadSink != nil else { return }
|
||||
let failedAssetIDs = tasks.filter { $0.status == .failed }.map(\.assetID)
|
||||
for index in tasks.indices where tasks[index].status == .failed {
|
||||
tasks[index].status = .downloaded
|
||||
tasks[index].errorMessage = nil
|
||||
}
|
||||
notify()
|
||||
processUploadQueue()
|
||||
await uploadAssets(withIDs: failedAssetIDs)
|
||||
}
|
||||
|
||||
/// 手动上传指定 asset 列表(拍完再传模式)。
|
||||
@ -150,6 +152,7 @@ final class CameraTransferPipeline {
|
||||
try? FileManager.default.removeItem(at: localURL)
|
||||
}
|
||||
tasks.removeAll()
|
||||
autoUploadEligibleAssetIDs.removeAll()
|
||||
notify()
|
||||
}
|
||||
|
||||
@ -167,10 +170,19 @@ final class CameraTransferPipeline {
|
||||
if inFlightAssetIDs.contains(asset.id) { return }
|
||||
if tasks.contains(where: { $0.assetID == asset.id && $0.status == .downloading }) { return }
|
||||
|
||||
let isKnownAsset = tasks.contains { $0.assetID == asset.id }
|
||||
let shouldAutoUpload = !skipIfExists
|
||||
&& uploadEnabled
|
||||
&& uploadSink != nil
|
||||
&& (!isKnownAsset || autoUploadEligibleAssetIDs.contains(asset.id))
|
||||
|
||||
inFlightAssetIDs.insert(asset.id)
|
||||
defer { inFlightAssetIDs.remove(asset.id) }
|
||||
|
||||
let assetID = asset.id
|
||||
if shouldAutoUpload {
|
||||
autoUploadEligibleAssetIDs.insert(assetID)
|
||||
}
|
||||
if let existingIndex = tasks.firstIndex(where: { $0.assetID == assetID }) {
|
||||
tasks[existingIndex].status = .downloading
|
||||
tasks[existingIndex].errorMessage = nil
|
||||
@ -187,8 +199,7 @@ final class CameraTransferPipeline {
|
||||
|
||||
await downloadAsset(assetID: assetID, asset: asset)
|
||||
|
||||
if uploadEnabled,
|
||||
uploadSink != nil,
|
||||
if shouldAutoUpload,
|
||||
tasks.first(where: { $0.assetID == assetID })?.status == .downloaded {
|
||||
processUploadQueue()
|
||||
}
|
||||
@ -237,12 +248,16 @@ final class CameraTransferPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
/// 并发上传已下载任务;边拍边传时限制并发数,避免网络与内存被打满。
|
||||
/// 并发上传边拍边传新照片;拍后传输留下的待上传任务只能由用户显式上传。
|
||||
private func processUploadQueue() {
|
||||
guard uploadEnabled, uploadSink != nil else { return }
|
||||
guard uploadSink != nil else { return }
|
||||
|
||||
while activeUploadAssetIDs.count < maxConcurrentUploads,
|
||||
let task = tasks.first(where: { $0.status == .downloaded && !activeUploadAssetIDs.contains($0.assetID) }) {
|
||||
let task = tasks.first(where: {
|
||||
$0.status == .downloaded
|
||||
&& !activeUploadAssetIDs.contains($0.assetID)
|
||||
&& autoUploadEligibleAssetIDs.contains($0.assetID)
|
||||
}) {
|
||||
startConcurrentUpload(assetID: task.assetID)
|
||||
}
|
||||
}
|
||||
@ -292,6 +307,7 @@ final class CameraTransferPipeline {
|
||||
tasks[taskIndex].status = .uploaded
|
||||
tasks[taskIndex].remoteURL = remoteURL
|
||||
tasks[taskIndex].progress = 100
|
||||
autoUploadEligibleAssetIDs.remove(assetID)
|
||||
lastNotifiedProgressByAssetID.removeValue(forKey: assetID)
|
||||
notify()
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user