diff --git a/WordPress/Classes/ViewRelated/Aztec/Media/MediaUploadBackgroundTracker.swift b/WordPress/Classes/ViewRelated/Aztec/Media/MediaUploadBackgroundTracker.swift index 30b30e8d4227..b45f12696f6b 100644 --- a/WordPress/Classes/ViewRelated/Aztec/Media/MediaUploadBackgroundTracker.swift +++ b/WordPress/Classes/ViewRelated/Aztec/Media/MediaUploadBackgroundTracker.swift @@ -6,7 +6,7 @@ import WordPressShared // This protocol is used to hide the `@available(iOS 26.0, *)` check. protocol MediaUploadBackgroundTracker { - func track(progress: Progress, media: TaggedManagedObjectID) async + func track(progress: Progress, media: TaggedManagedObjectID) } @@ -19,8 +19,9 @@ func mediaUploadBackgroundTracker() -> MediaUploadBackgroundTracker? { } @available(iOS 26.0, *) +@MainActor /// Utilize `BGContinuedProcessingTask` to show the uploading media activity. -private actor ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker { +private final class ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker { struct Item { // Please note: all media query needs to be done in the main context, due to the current upload media implementation. var media: TaggedManagedObjectID @@ -72,15 +73,13 @@ private actor ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker wpAssertionFailure("Unexpected task instance") return } - - Task { - await self?.taskCreated(task) + Task { @MainActor in + self?.taskCreated(task) } } - } - func track(progress: Progress, media: TaggedManagedObjectID) async { + func track(progress: Progress, media: TaggedManagedObjectID) { observeCoreDataChanges() let item = Item(media: media, progress: progress) @@ -125,9 +124,7 @@ private actor ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker } if !mediaObjectIDs.isEmpty { - Task { - await self?.handleMediaObjectsUpdates(updated: mediaObjectIDs) - } + self?.handleMediaObjectsUpdates(updated: mediaObjectIDs) } } } @@ -135,8 +132,8 @@ private actor ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker private func taskCreated(_ task: BGContinuedProcessingTask) { task.progress.totalUnitCount = 100 task.expirationHandler = { [weak self] in - Task { - await self?.handleExpiration() + Task { @MainActor in + self?.handleExpiration() } } @@ -157,22 +154,16 @@ private actor ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker accepted.items.append(item) let progress = item.progress.publisher(for: \.fractionCompleted).sink { [weak self] _ in - Task { - await self?.handleProgressUpdates() - } + self?.handleProgressUpdates() } accepted.observers.append(progress) - Task { @MainActor in - guard let media = try? ContextManager.shared.mainContext.existingObject(with: item.media) else { return } + guard let media = try? ContextManager.shared.mainContext.existingObject(with: item.media) else { return } - let completion = media.publisher(for: \.remoteStatusNumber).sink { [weak self] _ in - Task { - await self?.handleStatusUpdates() - } - } - await self.addObserver(completion) + let completion = media.publisher(for: \.remoteStatusNumber).sink { [weak self] _ in + self?.handleStatusUpdates() } + self.addObserver(completion) } private func addObserver(_ cancellable: AnyCancellable) { @@ -183,55 +174,49 @@ private actor ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker private func handleExpiration() { if case let .accepted(accepted) = state { - Task { @MainActor in - let context = ContextManager.shared.mainContext - for item in accepted.items { - guard let media = try? context.existingObject(with: item.media) else { continue } - MediaCoordinator.shared.cancelUpload(of: media) - } + let context = ContextManager.shared.mainContext + for item in accepted.items { + guard let media = try? context.existingObject(with: item.media) else { continue } + MediaCoordinator.shared.cancelUpload(of: media) } } setTaskCompleted(success: false) } - private func handleProgressUpdates() async { + private func handleProgressUpdates() { guard case let .accepted(accepted) = state else { return } - let progresses = await MainActor.run { - let context = ContextManager.shared.mainContext - return accepted.items - .filter { item in - (try? context.existingObject(with: item.media)) != nil - } - .map(\.progress) - } + let context = ContextManager.shared.mainContext + let progresses = accepted.items + .filter { item in + (try? context.existingObject(with: item.media)) != nil + } + .map(\.progress) let fractionCompleted = progresses.map(\.fractionCompleted).reduce(0, +) / Double(progresses.count) accepted.task.progress.completedUnitCount = Int64(fractionCompleted * Double(accepted.task.progress.totalUnitCount)) } - private func handleMediaObjectsUpdates(updated: Set>) async { + private func handleMediaObjectsUpdates(updated: Set>) { guard case let .accepted(accepted) = state else { return } let needsUpdate = accepted.items.contains(where: { updated.contains($0.media) }) if needsUpdate { - await handleStatusUpdates() + handleStatusUpdates() } } - private func handleStatusUpdates() async { - await updateMessaging() - await updateResult() + private func handleStatusUpdates() { + updateMessaging() + updateResult() } - private func updateMessaging() async { + private func updateMessaging() { guard case let .accepted(accepted) = self.state else { return } - let statuses = await MainActor.run { - let context = ContextManager.shared.mainContext - return accepted.items.compactMap { try? context.existingObject(with: $0.media).uploadStatus } - } + let context = ContextManager.shared.mainContext + let statuses = accepted.items.compactMap { try? context.existingObject(with: $0.media).uploadStatus } let failed = statuses.count { $0 == .failure } let success = statuses.count { $0 == .success} @@ -251,13 +236,11 @@ private actor ConcreteMediaUploadBackgroundTracker: MediaUploadBackgroundTracker accepted.task.updateTitle(Strings.uploadingMediaTitle, subtitle: ListFormatter.localizedString(byJoining: subtitle)) } - private func updateResult() async { + private func updateResult() { guard case let .accepted(accepted) = self.state else { return } - let mediaStatuses = await MainActor.run { - let context = ContextManager.shared.mainContext - return accepted.items.compactMap { try? context.existingObject(with: $0.media).uploadStatus } - } + let context = ContextManager.shared.mainContext + let mediaStatuses = accepted.items.compactMap { try? context.existingObject(with: $0.media).uploadStatus } let completed = mediaStatuses.allSatisfy { $0 == .success || $0 == .failure } guard completed else {