mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
convert email creation to async
This commit is contained in:
parent
7cbfc96b87
commit
090c1acbfd
3 changed files with 46 additions and 42 deletions
|
|
@ -4,8 +4,7 @@ import Services
|
|||
import SwiftUI
|
||||
import Views
|
||||
|
||||
final class NewsletterEmailsViewModel: ObservableObject {
|
||||
private var hasLoadedInitialEmails = false
|
||||
@MainActor final class NewsletterEmailsViewModel: ObservableObject {
|
||||
@Published var isLoading = false
|
||||
@Published var emails = [NewsletterEmail]()
|
||||
|
||||
|
|
@ -21,29 +20,23 @@ final class NewsletterEmailsViewModel: ObservableObject {
|
|||
dataService.viewContext.perform {
|
||||
self?.emails = objectIDs.compactMap { dataService.viewContext.object(with: $0) as? NewsletterEmail }
|
||||
}
|
||||
self?.hasLoadedInitialEmails = true
|
||||
}
|
||||
)
|
||||
.store(in: &subscriptions)
|
||||
}
|
||||
|
||||
func createEmail(dataService: DataService) {
|
||||
func createEmail(dataService: DataService) async {
|
||||
isLoading = true
|
||||
|
||||
dataService.createNewsletterEmailPublisher().sink(
|
||||
receiveCompletion: { [weak self] _ in
|
||||
self?.isLoading = false
|
||||
},
|
||||
receiveValue: { [weak self] objectID in
|
||||
self?.isLoading = false
|
||||
dataService.viewContext.perform {
|
||||
if let item = dataService.viewContext.object(with: objectID) as? NewsletterEmail {
|
||||
self?.emails.insert(item, at: 0)
|
||||
}
|
||||
if let objectID = try? await dataService.createNewsletter() {
|
||||
await dataService.viewContext.perform { [weak self] in
|
||||
if let item = dataService.viewContext.object(with: objectID) as? NewsletterEmail {
|
||||
self?.emails.insert(item, at: 0)
|
||||
}
|
||||
}
|
||||
)
|
||||
.store(in: &subscriptions)
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +58,7 @@ struct NewsletterEmailsView: View {
|
|||
.listStyle(InsetListStyle())
|
||||
#endif
|
||||
}
|
||||
.onAppear { viewModel.loadEmails(dataService: dataService) }
|
||||
.task { viewModel.loadEmails(dataService: dataService) }
|
||||
}
|
||||
|
||||
private var innerBody: some View {
|
||||
|
|
@ -73,7 +66,7 @@ struct NewsletterEmailsView: View {
|
|||
Section(footer: Text(footerText)) {
|
||||
Button(
|
||||
action: {
|
||||
viewModel.createEmail(dataService: dataService)
|
||||
Task { await viewModel.createEmail(dataService: dataService) }
|
||||
},
|
||||
label: {
|
||||
HStack {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import Models
|
|||
import SwiftGraphQL
|
||||
|
||||
public extension DataService {
|
||||
func createNewsletterEmailPublisher() -> AnyPublisher<NSManagedObjectID, BasicError> {
|
||||
func createNewsletter() async throws -> NSManagedObjectID {
|
||||
enum MutationResult {
|
||||
case saved(newsletterEmail: InternalNewsletterEmail)
|
||||
case error(errorCode: Enums.CreateNewsletterEmailErrorCode)
|
||||
|
|
@ -34,32 +34,24 @@ 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(.message(messageText: "graphql error: \(graphqlError)")))
|
||||
}
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
send(mutation, to: path, headers: headers) { [weak self] queryResult in
|
||||
guard let payload = try? queryResult.get(), let self = self else {
|
||||
continuation.resume(throwing: BasicError.message(messageText: "network error"))
|
||||
return
|
||||
}
|
||||
|
||||
switch payload.data {
|
||||
case let .saved(newsletterEmail: newsletterEmail):
|
||||
if let newsletterEmailObjectID = newsletterEmail.persist(context: self.backgroundContext) {
|
||||
promise(.success(newsletterEmailObjectID))
|
||||
} else {
|
||||
promise(.failure(.message(messageText: "coredata error")))
|
||||
}
|
||||
case let .error(errorCode: errorCode):
|
||||
promise(.failure(.message(messageText: errorCode.rawValue)))
|
||||
}
|
||||
case .failure:
|
||||
promise(.failure(.message(messageText: "graphql error")))
|
||||
switch payload.data {
|
||||
case let .saved(newsletterEmail: newsletterEmail):
|
||||
if let newsletterEmailObjectID = newsletterEmail.persist(context: self.backgroundContext) {
|
||||
continuation.resume(returning: newsletterEmailObjectID)
|
||||
} else {
|
||||
continuation.resume(throwing: BasicError.message(messageText: "CoreData error"))
|
||||
}
|
||||
case let .error(errorCode: errorCode):
|
||||
continuation.resume(throwing: BasicError.message(messageText: errorCode.rawValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
.receive(on: DispatchQueue.main)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ struct InternalNewsletterEmail {
|
|||
}
|
||||
|
||||
func asManagedObject(inContext context: NSManagedObjectContext) -> NewsletterEmail {
|
||||
let newsletterEmail = NewsletterEmail(entity: NewsletterEmail.entity(), insertInto: context)
|
||||
let existingEmail = NewsletterEmail.lookup(byID: emailId, inContext: context)
|
||||
let newsletterEmail = existingEmail ?? NewsletterEmail(entity: NewsletterEmail.entity(), insertInto: context)
|
||||
|
||||
newsletterEmail.emailId = emailId
|
||||
newsletterEmail.email = email
|
||||
newsletterEmail.confirmationCode = confirmationCode
|
||||
|
|
@ -54,3 +56,20 @@ extension Sequence where Element == InternalNewsletterEmail {
|
|||
return result
|
||||
}
|
||||
}
|
||||
|
||||
extension NewsletterEmail {
|
||||
static func lookup(byID emailID: String, inContext context: NSManagedObjectContext) -> NewsletterEmail? {
|
||||
let fetchRequest: NSFetchRequest<Models.NewsletterEmail> = NewsletterEmail.fetchRequest()
|
||||
fetchRequest.predicate = NSPredicate(
|
||||
format: "%K == %@", #keyPath(NewsletterEmail.emailId), emailID
|
||||
)
|
||||
|
||||
var email: NewsletterEmail?
|
||||
|
||||
context.performAndWait {
|
||||
email = (try? context.fetch(fetchRequest))?.first
|
||||
}
|
||||
|
||||
return email
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue