When opening library items that were created locally, make sure they are synced

This commit is contained in:
Jackson Harper 2022-06-01 20:22:45 -07:00
parent e773ea7e2b
commit 1386cc250a
3 changed files with 108 additions and 68 deletions

View file

@ -20,28 +20,6 @@ public final class Networker: NSObject, URLSessionTaskDelegate {
self.appEnvironment = appEnvironment
self.urlSession = .shared
}
public func createBackgroundSession() -> URLSession {
let sessionConfig = URLSessionConfiguration.background(withIdentifier: "app.omnivoreapp.BackgroundSessionConfig-")
sessionConfig.sharedContainerIdentifier = "group.app.omnivoreapp"
return URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
}
public func urlSession(_: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
print("finished upload on original request", task.originalRequest, "error", error)
if let httpResponse = task.response as? HTTPURLResponse {
if 200 ... 299 ~= httpResponse.statusCode {
// success
if let requestId = task.originalRequest?.value(forHTTPHeaderField: "clientRequestId") {
print("COMPLETED UPLOADED REQUEST ID", requestId)
DispatchQueue.main.async {
NotificationCenter.default.post(name: NSNotification.LocallyCreatedItemSynced, object: nil, userInfo: ["objectID": requestId])
}
}
}
print("DONE")
}
}
}
extension Networker {

View file

@ -35,61 +35,81 @@ public extension DataService {
}
}
// func syncPdf(item: LinkedItem, usingSession session: URLSession) async throws -> Bool {
// try backgroundContext.performAndWait {
// item.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
// try self.backgroundContext.save()
// }
//
// let id = item.unwrappedID
// let localPdfURL = item.localPdfURL
// let url = item.unwrappedPageURLString
// let uploadRequestUrl = try await uploadFileRequest(id: id, url: url)
// return await try uploadFile(id: id, localPdfURL: localPdfURL, url: uploadRequestUrl, usingSession: session)
// }
private func updateLinkedItemStatus(id: String, status: ServerSyncStatus) async throws {
try backgroundContext.performAndWait {
let fetchRequest: NSFetchRequest<Models.LinkedItem> = LinkedItem.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "id == %@", id)
guard let linkedItem = (try? backgroundContext.fetch(fetchRequest))?.first else { return }
linkedItem.serverSyncStatus = Int64(status.rawValue)
}
}
func syncPdf(id: String, localPdfURL: URL, url: String) async throws {
// try backgroundContext.performAndWait {
// item.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
// try self.backgroundContext.save()
// }
do {
let uploadRequest = try await uploadFileRequest(id: id, url: url)
if let urlString = uploadRequest.urlString, let uploadUrl = URL(string: urlString) {
try await uploadFile(id: id, localPdfURL: localPdfURL, url: uploadUrl)
// try await services.dataService.saveFilePublisher(requestId: requestId, uploadFileId: uploadFileID, url: url)
} else {
throw SaveArticleError.badData
}
let uploadRequest = try await uploadFileRequest(id: id, url: url)
if let urlString = uploadRequest.urlString, let uploadUrl = URL(string: urlString) {
try await uploadFile(id: id, localPdfURL: localPdfURL, url: uploadUrl)
// try await services.dataService.saveFilePublisher(requestId: requestId, uploadFileId: uploadFileID, url: url)
} else {
throw SaveArticleError.badData
try await updateLinkedItemStatus(id: id, status: .isNSync)
try backgroundContext.performAndWait {
try backgroundContext.save()
}
} catch {
backgroundContext.rollback()
throw error
}
}
func syncPage(id: String, originalHtml: String, title: String?, url: String) async throws {
// try backgroundContext.performAndWait {
// item.serverSyncStatus = Int64(ServerSyncStatus.isSyncing.rawValue)
// try self.backgroundContext.save()
// }
try await savePage(id: id, url: url, title: title ?? url, originalHtml: originalHtml)
do {
try await savePage(id: id, url: url, title: title ?? url, originalHtml: originalHtml)
try await updateLinkedItemStatus(id: id, status: .isNSync)
try backgroundContext.performAndWait {
try backgroundContext.save()
}
} catch {
backgroundContext.performAndWait {
backgroundContext.rollback()
}
throw error
}
}
func syncUrl(id: String, url: String) async throws {
try await saveURL(id: id, url: url)
do {
try await updateLinkedItemStatus(id: id, status: .isSyncing)
try await saveURL(id: id, url: url)
try backgroundContext.performAndWait {
try backgroundContext.save()
}
} catch {
backgroundContext.performAndWait {
backgroundContext.rollback()
}
throw error
}
}
func syncLocalCreatedLinkedItem(item: LinkedItem) {
switch item.contentReader {
case "PDF":
// let id = item.unwrappedID
// let localPdfURL = item.localPdfURL
// let url = item.unwrappedPageURLString
// Task {
// let uploadRequestUrl = try await uploadFileRequest(id: id, url: url)
// uploadFile(id: id, localPdfURL: localPdfURL, url: uploadRequestUrl)
// try await backgroundContext.perform {
// item.serverSyncStatus = Int64(ServerSyncStatus.isNSync.rawValue)
// try self.backgroundContext.save()
// }
// }
break
let id = item.unwrappedID
let localPdfURL = item.localPdfURL
let url = item.unwrappedPageURLString
if let pdfUrlStr = localPdfURL, let localPdfURL = URL(string: pdfUrlStr) {
Task {
try await syncPdf(id: id, localPdfURL: localPdfURL, url: url)
}
} else {
// TODO: This is an invalid object, we should have a way of reflecting that with an error state
// updateLinkedItemStatus(id: id, status: .)
}
case "WEB":
let id = item.unwrappedID
let url = item.unwrappedPageURLString
@ -98,13 +118,9 @@ public extension DataService {
Task {
if let originalHtml = originalHtml {
try await savePage(id: id, url: url, title: title, originalHtml: originalHtml)
try await syncPage(id: id, originalHtml: originalHtml, title: title, url: url)
} else {
try await saveURL(id: id, url: url)
}
try await backgroundContext.perform {
item.serverSyncStatus = Int64(ServerSyncStatus.isNSync.rawValue)
try self.backgroundContext.save()
try await syncUrl(id: id, url: url)
}
}
default:

View file

@ -85,6 +85,9 @@ extension DataService {
return cachedContent
}
// If the page was locally created, make sure they are synced before we pull content
await syncUnsyncedArticleContent(itemID: itemID)
enum QueryResult {
case success(result: ArticleProps)
case error(error: String)
@ -304,6 +307,49 @@ extension DataService {
)
}
}
func syncUnsyncedArticleContent(itemID: String) async {
let linkedItemFetchRequest: NSFetchRequest<Models.LinkedItem> = LinkedItem.fetchRequest()
linkedItemFetchRequest.predicate = NSPredicate(
format: "id == %@", itemID
)
let context = backgroundContext
var id: String?
var url: String?
var title: String?
var originalHtml: String?
var serverSyncStatus: Int64?
backgroundContext.performAndWait {
guard let linkedItem = try? context.fetch(linkedItemFetchRequest).first else { return }
id = linkedItem.unwrappedID
url = linkedItem.unwrappedPageURLString
title = linkedItem.unwrappedTitle
originalHtml = linkedItem.originalHtml
serverSyncStatus = linkedItem.serverSyncStatus
}
if let id = id, let url = url, let title = title,
let serverSyncStatus = serverSyncStatus,
serverSyncStatus != ServerSyncStatus.isNSync.rawValue
{
do {
if let originalHtml = originalHtml {
try await savePage(id: id, url: url, title: title, originalHtml: originalHtml)
} else {
try await saveURL(id: id, url: url)
}
try backgroundContext.performAndWait {
try backgroundContext.save()
}
} catch {
// We don't propogate these errors, we just let it pass through so
// the user can attempt to fetch content again.
}
}
}
}
private extension ArticleContentStatus {