convert save page publisher to async

This commit is contained in:
Satindar Dhillon 2022-05-31 12:34:11 -07:00
parent 6f35740272
commit 822a38a863
2 changed files with 79 additions and 60 deletions

View file

@ -45,49 +45,71 @@ final class ShareExtensionViewModel: ObservableObject {
backgroundTask = UIApplication.shared.beginBackgroundTask(withName: requestID)
PageScraper.scrape(extensionContext: extensionContext) { [weak self] result in
guard let self = self else { return }
switch result {
case let .success(payload):
self?.persist(pageScrapePayload: payload, requestId: self?.requestID ?? "")
Task {
await self.persist(pageScrapePayload: payload, requestId: self.requestID)
}
case let .failure(error):
if let backgroundTask = self?.backgroundTask {
if let backgroundTask = self.backgroundTask {
UIApplication.shared.endBackgroundTask(backgroundTask)
}
self?.debugText = error.message
self.debugText = error.message
}
}
}
private func persist(pageScrapePayload: PageScrapePayload, requestId: String) {
private func persist(pageScrapePayload: PageScrapePayload, requestId: String) async {
let services = Services()
Task {
do {
// Save locally, then attempt to sync to the server
let item = try await services.dataService.persistPageScrapePayload(pageScrapePayload, requestId: requestId)
// TODO: need to update this on the main thread and handle the result == false case here
if item != nil {
self.status = .saved
} else {
self.status = .failed(error: SaveArticleError.unknown(description: "Unable to save page"))
return
}
// Save locally first
let linkedItem = try? await services.dataService.persistPageScrapePayload(pageScrapePayload, requestId: requestId)
// force a server sync
if let item = item {
let syncResult = services.dataService.syncLocalCreatedLinkedItem(item: item)
print("RESULT", syncResult)
}
// self.status = .synced
// } else {
// self.status = .syncFailed(error: SaveArticleError.unknown(description: "Unable to sync page"))
// }
} catch {
print("ERROR SAVING PAGE", error)
}
if let linkedItem = linkedItem {
// Sync with server now that we saved the item locally
services.dataService.syncLocalCreatedLinkedItem(item: linkedItem)
updateStatus(newStatus: .saved)
} else {
updateStatus(newStatus: .failed(error: SaveArticleError.unknown(description: "Unable to save page")))
}
// First persist to Core Data
// services.dataService.persist(jsonArticle: article)
}
private func updateStatus(newStatus: ShareExtensionStatus) {
DispatchQueue.main.async {
self.status = newStatus
}
}
}
// Task {
// do {
// // Save locally, then attempt to sync to the server
// let item = try await services.dataService.persistPageScrapePayload(pageScrapePayload, requestId: requestId)
// // TODO: need to update this on the main thread and handle the result == false case here
// if item != nil {
// self.status = .saved
// } else {
// self.status = .failed(error: SaveArticleError.unknown(description: "Unable to save page"))
// return
// }
//
// // force a server sync
// if let item = item {
// let syncResult = services.dataService.syncLocalCreatedLinkedItem(item: item)
// print("RESULT", syncResult)
// }
//// self.status = .synced
//// } else {
//// self.status = .syncFailed(error: SaveArticleError.unknown(description: "Unable to sync page"))
//// }
//
// } catch {
// print("ERROR SAVING PAGE", error)
// }
// }
// // First persist to Core Data
// // services.dataService.persist(jsonArticle: article)
//
// guard services.authenticator.hasValidAuthToken else {
@ -137,8 +159,8 @@ final class ShareExtensionViewModel: ObservableObject {
// }
// }
// }
}
}
// }
// }
struct ShareExtensionView: View {
let extensionContext: NSExtensionContext?

View file

@ -1,11 +1,9 @@
import Combine
import Foundation
import Models
import SwiftGraphQL
public extension DataService {
// swiftlint:disable:next line_length
func savePagePublisher(pageScrapePayload: PageScrapePayload, html: String, title: String?, requestId: String) -> AnyPublisher<Void, SaveArticleError> {
func savePage(pageScrapePayload: PageScrapePayload, html: String, title: String?, requestId: String) async throws {
enum MutationResult {
case saved(requestId: String, url: String)
case error(errorCode: Enums.SaveErrorCode)
@ -35,38 +33,37 @@ public extension DataService {
let path = appEnvironment.graphqlPath
let headers = networker.defaultHeaders
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(.unknown(description: graphqlError.first.debugDescription)))
}
switch payload.data {
case .saved:
promise(.success(()))
case let .error(errorCode: errorCode):
switch errorCode {
case .unauthorized:
promise(.failure(.unauthorized))
default:
promise(.failure(.unknown(description: errorCode.rawValue)))
}
}
case let .failure(error):
promise(.failure(SaveError.make(from: error)))
return try await withCheckedThrowingContinuation { continuation in
send(mutation, to: path, headers: headers) { result in
switch result {
case let .success(payload):
if let graphqlError = payload.errors {
continuation.resume(
throwing: SaveArticleError.unknown(description: graphqlError.first.debugDescription)
)
return
}
switch payload.data {
case .saved:
continuation.resume()
case let .error(errorCode: errorCode):
switch errorCode {
case .unauthorized:
continuation.resume(throwing: SaveArticleError.unauthorized)
default:
continuation.resume(throwing: SaveArticleError.unknown(description: errorCode.rawValue))
}
}
case let .failure(error):
continuation.resume(throwing: SaveArticleError.make(from: error))
}
}
}
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}
private extension SaveError {
private extension SaveArticleError {
static func make(from httpError: HttpError) -> SaveArticleError {
switch httpError {
case .network, .timeout: