为旅拍 OTG 上传增加 client_photo_id,并按服务端已登记 ID 同步本地上传状态。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -77,6 +77,7 @@ final class WiredCameraTransferViewModel {
|
||||
private let storage: TravelAlbumOTGPhotoStore
|
||||
private let repository: TravelAlbumOTGPhotoRepository
|
||||
private let uploader: any TravelAlbumOTGUploading
|
||||
private let api: any TravelAlbumServing
|
||||
private let appStore: AppStore
|
||||
private let userDefaults: UserDefaults
|
||||
|
||||
@ -85,6 +86,7 @@ final class WiredCameraTransferViewModel {
|
||||
private var isUploading = false
|
||||
private var queuedAutoUploadPhotoIds: Set<String> = []
|
||||
private var suppressSelectedTimeSlotNotification = false
|
||||
private var serverStatusSyncTask: Task<Void, Never>?
|
||||
|
||||
@MainActor
|
||||
init(
|
||||
@ -95,6 +97,7 @@ final class WiredCameraTransferViewModel {
|
||||
connectionManager: (any WiredCameraConnectionManaging)? = nil,
|
||||
storage: TravelAlbumOTGPhotoStore = TravelAlbumOTGPhotoStore(),
|
||||
uploader: (any TravelAlbumOTGUploading)? = nil,
|
||||
api: (any TravelAlbumServing)? = nil,
|
||||
appStore: AppStore = .shared,
|
||||
userDefaults: UserDefaults = .standard
|
||||
) {
|
||||
@ -106,6 +109,7 @@ final class WiredCameraTransferViewModel {
|
||||
self.storage = storage
|
||||
self.repository = TravelAlbumOTGPhotoRepository(storage: storage)
|
||||
self.uploader = uploader ?? TravelAlbumOTGUploader()
|
||||
self.api = api ?? NetworkServices.shared.travelAlbumAPI
|
||||
self.appStore = appStore
|
||||
self.userDefaults = userDefaults
|
||||
self.transferMode = Self.persistedTransferMode(in: userDefaults)
|
||||
@ -225,11 +229,14 @@ final class WiredCameraTransferViewModel {
|
||||
connectionManager.delegate = self
|
||||
syncFromConnectionManager()
|
||||
loadPersistedPhotos()
|
||||
syncServerUploadStatuses()
|
||||
connectionManager.start()
|
||||
}
|
||||
|
||||
/// 页面消失时解绑 UI delegate,并暂停边拍边传轮询,保留底层设备缓存。
|
||||
func stop() {
|
||||
serverStatusSyncTask?.cancel()
|
||||
serverStatusSyncTask = nil
|
||||
connectionManager.unbindDelegate()
|
||||
connectionManager.suspendLiveTransfer()
|
||||
}
|
||||
@ -483,6 +490,39 @@ final class WiredCameraTransferViewModel {
|
||||
applyMergedPhotos()
|
||||
}
|
||||
|
||||
private func syncServerUploadStatuses() {
|
||||
serverStatusSyncTask?.cancel()
|
||||
guard albumId > 0 else { return }
|
||||
let baseline = persistedRecordsById
|
||||
serverStatusSyncTask = Task { [weak self] in
|
||||
guard let self else { return }
|
||||
do {
|
||||
let response = try await api.materialClientPhotoIds(userEquityTravelId: albumId)
|
||||
try Task.checkCancellation()
|
||||
let activeIds = Set(persistedRecordsById.values.compactMap { record in
|
||||
record.status == .transferring || record.status == .uploading ? record.id : nil
|
||||
})
|
||||
let reconciled = TravelAlbumOTGServerStatusPolicy.reconcile(
|
||||
records: Array(persistedRecordsById.values),
|
||||
baselineRecordsById: baseline,
|
||||
activePhotoIds: activeIds,
|
||||
serverClientPhotoIds: response.clientPhotoIds,
|
||||
now: Int64(Date().timeIntervalSince1970 * 1000)
|
||||
)
|
||||
let reconciledById = Dictionary(uniqueKeysWithValues: reconciled.map { ($0.id, $0) })
|
||||
guard reconciledById != persistedRecordsById else { return }
|
||||
persistedRecordsById = reconciledById
|
||||
storage.save(reconciled, albumId: albumId)
|
||||
applyMergedPhotos()
|
||||
selectedPhotoIds = selectedPhotoIds.intersection(selectableVisiblePhotoIds)
|
||||
} catch is CancellationError {
|
||||
return
|
||||
} catch {
|
||||
OTGLog.error(.connection, "sync server upload statuses failed: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func applyMergedPhotos() {
|
||||
let persistedItems = persistedRecordsById.values
|
||||
.map { $0.toPhotoItem(storage: storage, albumId: albumId) }
|
||||
|
||||
Reference in New Issue
Block a user