修复 OTG 列表删除照片后边拍边传仍会带回已删项的问题。
删除时同步清理管道任务并维护 excludedAssetIDs,避免 notify 将无本地文件的旧任务重新展示为仅文件名的待上传项。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -27,6 +27,8 @@ final class CameraTransferPipeline {
|
||||
private let deferredNotifyInterval: TimeInterval = 0.15
|
||||
private let maxConcurrentUploads = 3
|
||||
private var isUIAttached = false
|
||||
/// 用户已从列表删除、不应再同步或展示的 asset ID。
|
||||
private(set) var excludedAssetIDs: Set<String> = []
|
||||
|
||||
/// 初始化传输管道,并注入相机服务。
|
||||
init(cameraService: any CameraServiceProtocol) {
|
||||
@ -224,7 +226,24 @@ final class CameraTransferPipeline {
|
||||
tasks.first { $0.assetID == assetID }
|
||||
}
|
||||
|
||||
/// 同步用户已删除的 asset ID,防止 sync/notify 再次带回。
|
||||
func setExcludedAssetIDs(_ ids: Set<String>) {
|
||||
excludedAssetIDs = ids
|
||||
}
|
||||
|
||||
/// 从管道移除 asset,并阻止后续自动同步。
|
||||
func removeAsset(assetID: String) {
|
||||
guard !assetID.isEmpty else { return }
|
||||
excludedAssetIDs.insert(assetID)
|
||||
tasks.removeAll { $0.assetID == assetID }
|
||||
autoUploadEligibleAssetIDs.remove(assetID)
|
||||
activeUploadAssetIDs.remove(assetID)
|
||||
inFlightAssetIDs.remove(assetID)
|
||||
lastNotifiedProgressByAssetID.removeValue(forKey: assetID)
|
||||
}
|
||||
|
||||
private func handleNewAsset(_ asset: CameraAsset, skipIfExists: Bool) async {
|
||||
if excludedAssetIDs.contains(asset.id) { return }
|
||||
if skipIfExists,
|
||||
let existing = tasks.first(where: { $0.assetID == asset.id }),
|
||||
existing.status == .uploaded || existing.status == .downloaded {
|
||||
|
||||
@ -449,6 +449,7 @@ final class WiredCameraTransferViewModel: ObservableObject {
|
||||
private var persistedRecordsByID: [String: WiredTransferPhotoRecord] = [:]
|
||||
private var lastAppliedPipelineSignatures: [String: PipelineTaskSignature] = [:]
|
||||
private var lastProgressPersistDates: [String: Date] = [:]
|
||||
private var deletedPhotoIDs: Set<String> = []
|
||||
private var wasConnected = false
|
||||
private var disconnectAlertTask: Task<Void, Never>?
|
||||
private var isTearingDownCamera = false
|
||||
@ -799,9 +800,12 @@ final class WiredCameraTransferViewModel: ObservableObject {
|
||||
/// 删除本地照片记录。
|
||||
func deletePhoto(id: String) {
|
||||
photoStore?.remove(albumID: context.albumId, photoID: id)
|
||||
deletedPhotoIDs.insert(id)
|
||||
pipeline.removeAsset(assetID: id)
|
||||
persistedRecordsByID.removeValue(forKey: id)
|
||||
lastAppliedPipelineSignatures.removeValue(forKey: id)
|
||||
lastProgressPersistDates.removeValue(forKey: id)
|
||||
sessionNewPhotoIDs.remove(id)
|
||||
setPhotos(photos.filter { $0.id != id }, rebuildGroups: true)
|
||||
}
|
||||
|
||||
@ -984,6 +988,8 @@ final class WiredCameraTransferViewModel: ObservableObject {
|
||||
|
||||
private func loadPersistedPhotos() {
|
||||
guard context.albumId > 0, let photoStore else { return }
|
||||
deletedPhotoIDs = photoStore.loadDeletedIDs(albumID: context.albumId)
|
||||
pipeline.setExcludedAssetIDs(deletedPhotoIDs)
|
||||
let records = photoStore.load(albumID: context.albumId)
|
||||
persistedRecordsByID = Dictionary(uniqueKeysWithValues: records.map { ($0.id, $0) })
|
||||
setPhotos(records.map { $0.toPhotoItem() }.sortedByCaptureTimeDescending(), rebuildGroups: true)
|
||||
@ -1001,6 +1007,7 @@ final class WiredCameraTransferViewModel: ObservableObject {
|
||||
)
|
||||
|
||||
for task in tasks {
|
||||
guard !deletedPhotoIDs.contains(task.assetID) else { continue }
|
||||
guard !enforceAlbumBinding || belongsToCurrentAlbum(task.assetID) else { continue }
|
||||
|
||||
let signature = PipelineTaskSignature(task: task)
|
||||
|
||||
Reference in New Issue
Block a user