diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 9db2db1a6..9e31848d7 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -48,7 +48,7 @@ import Views loadItems(isRefresh: true) } .sheet(item: $viewModel.itemUnderLabelEdit) { item in - ApplyLabelsView(mode: .item(item)) { _ in } + ApplyLabelsView(mode: .item(item)) } } .navigationTitle("Home") @@ -111,9 +111,7 @@ import Views } .padding(.horizontal) .sheet(isPresented: $showLabelsSheet) { - ApplyLabelsView(mode: .list(viewModel.selectedLabels)) { labels in - viewModel.selectedLabels = labels - } + ApplyLabelsView(mode: .list(viewModel.selectedLabels)) } } if prefersListLayout { diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift index 0a13fc566..73742ae8f 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift @@ -28,7 +28,6 @@ struct ApplyLabelsView: View { } let mode: Mode - let commitLabelChanges: ([LinkedItemLabel]) -> Void @EnvironmentObject var dataService: DataService @Environment(\.presentationMode) private var presentationMode @@ -100,14 +99,11 @@ struct ApplyLabelsView: View { action: { switch mode { case let .item(feedItem): - viewModel.saveItemLabelChanges(itemID: feedItem.unwrappedID, dataService: dataService) { labels in - commitLabelChanges(labels) - presentationMode.wrappedValue.dismiss() - } + viewModel.saveItemLabelChanges(itemID: feedItem.unwrappedID, dataService: dataService) case .list: - commitLabelChanges(viewModel.selectedLabels) - presentationMode.wrappedValue.dismiss() + break } + presentationMode.wrappedValue.dismiss() }, label: { Text(mode.confirmButtonText).foregroundColor(.appGrayTextContrast) } ) diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift index eb4ba0001..fdb8a2e75 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift @@ -74,23 +74,8 @@ import Views .store(in: &subscriptions) } - func saveItemLabelChanges( - itemID: String, - dataService: DataService, - onComplete: @escaping ([LinkedItemLabel]) -> Void - ) { - isLoading = true - dataService.updateArticleLabelsPublisher(itemID: itemID, labelIDs: selectedLabels.map(\.unwrappedID)).sink( - receiveCompletion: { [weak self] _ in - self?.isLoading = false - }, - receiveValue: { labelIDs in - onComplete( - labelIDs.compactMap { dataService.viewContext.object(with: $0) as? LinkedItemLabel } - ) - } - ) - .store(in: &subscriptions) + func saveItemLabelChanges(itemID: String, dataService: DataService) { + dataService.updateItemLabels(itemID: itemID, labelNames: selectedLabels.map(\.unwrappedName)) } func addLabelToItem(_ label: LinkedItemLabel) { diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift index 12af0de3c..af944c004 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift @@ -1,15 +1,33 @@ -import Combine import CoreData import Foundation import Models import SwiftGraphQL -public extension DataService { - // swiftlint:disable:next function_body_length - func updateArticleLabelsPublisher( - itemID: String, - labelIDs: [String] - ) -> AnyPublisher<[NSManagedObjectID], BasicError> { +extension DataService { + public func updateItemLabels(itemID: String, labelNames: [String]) { + backgroundContext.perform { [weak self] in + guard let self = self else { return } + guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: self.backgroundContext) else { return } + + if let existingLabels = linkedItem.labels { + linkedItem.removeFromLabels(existingLabels) + } + + var labelIDs = [String]() + + for labelName in labelNames { + if let labelObject = LinkedItemLabel.lookup(byName: labelName, inContext: self.backgroundContext) { + linkedItem.addToLabels(labelObject) + labelIDs.append(labelObject.unwrappedID) + } + } + + // Send update to server + self.syncLabelUpdates(itemID: itemID, labelIDs: labelIDs) + } + } + + func syncLabelUpdates(itemID: String, labelIDs: [String]) { enum MutationResult { case saved(feedItem: [InternalLinkedItemLabel]) case error(errorCode: Enums.SetLabelsErrorCode) @@ -34,54 +52,24 @@ public extension DataService { let path = appEnvironment.graphqlPath let headers = networker.defaultHeaders + let context = backgroundContext - return Deferred { - Future { promise in - send(mutation, to: path, headers: headers) { result in - switch result { - case let .success(payload): - if let graphqlError = payload.errors { - promise(.failure(.message(messageText: graphqlError.first.debugDescription))) - } + send(mutation, to: path, headers: headers) { result in + let data = try? result.get() + let syncStatus: ServerSyncStatus = data == nil ? .needsUpdate : .isNSync - switch payload.data { - case let .saved(labels): - self.backgroundContext.perform { - guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: self.backgroundContext) else { - promise(.failure(.message(messageText: "failed to set labels"))) - return - } + context.perform { + guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: context) else { return } + linkedItem.serverSyncStatus = Int64(syncStatus.rawValue) - if let existingLabels = linkedItem.labels { - linkedItem.removeFromLabels(existingLabels) - } - for label in labels { - if let labelObject = LinkedItemLabel.lookup(byName: label.name, inContext: self.backgroundContext) { - linkedItem.addToLabels(labelObject) - } - } - - do { - try self.backgroundContext.save() - logger.debug("Item labels updated") - let labelObjects = linkedItem.labels.asArray(of: LinkedItemLabel.self) - promise(.success(labelObjects.map(\.objectID))) - } catch { - self.backgroundContext.rollback() - logger.debug("Failed to update item labels: \(error.localizedDescription)") - promise(.failure(.message(messageText: "failed to set labels"))) - } - } - case .error: - promise(.failure(.message(messageText: "failed to set labels"))) - } - case .failure: - promise(.failure(.message(messageText: "failed to set labels"))) - } + do { + try context.save() + logger.debug("Item labels updated succesfully") + } catch { + context.rollback() + logger.debug("Failed to update item labels: \(error.localizedDescription)") } } } - .receive(on: DispatchQueue.main) - .eraseToAnyPublisher() } }