diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/SavePage.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/SavePage.swift index 57c2b3e79..f8b427b37 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/SavePage.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/SavePage.swift @@ -3,7 +3,7 @@ import Models import SwiftGraphQL public extension DataService { - func savePage(id: String, url: String, title: String, originalHtml: String) async throws { + func savePage(id: String, url: String, title: String, originalHtml: String) async throws -> String? { enum MutationResult { case saved(requestId: String, url: String) case error(errorCode: Enums.SaveErrorCode) @@ -20,7 +20,13 @@ public extension DataService { let selection = Selection { try $0.on( saveError: .init { .error(errorCode: (try? $0.errorCodes().first) ?? .unknown) }, - saveSuccess: .init { .saved(requestId: id, url: (try? $0.url()) ?? "") } + saveSuccess: .init { + if let requestId = try? $0.clientRequestId(), let url = try? $0.url() { + return .saved(requestId: requestId, url: url) + } else { + return .error(errorCode: .unknown) + } + } ) } @@ -42,8 +48,8 @@ public extension DataService { return } switch payload.data { - case .saved: - continuation.resume() + case let .saved(requestId: requestId, url: _): + continuation.resume(returning: requestId) case let .error(errorCode: errorCode): switch errorCode { case .unauthorized: diff --git a/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift b/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift index 4950b7c9d..d92ce1631 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift @@ -69,12 +69,14 @@ public extension DataService { func syncPage(id: String, originalHtml: String, title: String?, url: String) async throws { do { - try await savePage(id: id, url: url, title: title ?? url, originalHtml: originalHtml) + let newId = try await savePage(id: id, url: url, title: title ?? url, originalHtml: originalHtml) + print("NEW ID FOR ITEM", newId, "FROM OLD ID", id) try await updateLinkedItemStatus(id: id, status: .isNSync) try backgroundContext.performAndWait { try backgroundContext.save() } } catch { + print("ERROR SYNCING PAGE", error) backgroundContext.performAndWait { backgroundContext.rollback() } @@ -186,23 +188,4 @@ public extension DataService { } } } - - @objc - func locallyCreatedItemSynced(notification: NSNotification) { - print("SYNCED LOCALLY CREATED ITEM", notification) - if let objectId = notification.userInfo?["objectID"] as? String { - do { - try backgroundContext.performAndWait { - let fetchRequest: NSFetchRequest = LinkedItem.fetchRequest() - fetchRequest.predicate = NSPredicate(format: "id == %@", objectId) - if let existingItem = try? self.backgroundContext.fetch(fetchRequest).first { - existingItem.serverSyncStatus = Int64(ServerSyncStatus.isNSync.rawValue) - try self.backgroundContext.save() - } - } - } catch { - print("ERROR", error) - } - } - } } diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift b/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift index 89da84ecd..85fe53a79 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift @@ -332,6 +332,7 @@ extension DataService { serverSyncStatus = linkedItem.serverSyncStatus } + print("SERVER SYNC STATUS FOR LOADING ITEM", serverSyncStatus) if let id = id, let url = url, let title = title, let serverSyncStatus = serverSyncStatus, serverSyncStatus != ServerSyncStatus.isNSync.rawValue diff --git a/apple/OmnivoreKit/Sources/Views/FeedItem/GridCard.swift b/apple/OmnivoreKit/Sources/Views/FeedItem/GridCard.swift index fff4cc6d1..bb736984f 100644 --- a/apple/OmnivoreKit/Sources/Views/FeedItem/GridCard.swift +++ b/apple/OmnivoreKit/Sources/Views/FeedItem/GridCard.swift @@ -161,6 +161,10 @@ public struct GridCard: View { } .onTapGesture { tapHandler() } } + + if let status = item.serverSyncStatus, status != ServerSyncStatus.isNSync.rawValue { + SyncStatusIcon(status: ServerSyncStatus(rawValue: Int(status)) ?? ServerSyncStatus.isNSync) + } } .padding(.horizontal, 0) .padding(.top, 0) diff --git a/apple/OmnivoreKit/Sources/Views/FeedItem/HomeFeedCardView.swift b/apple/OmnivoreKit/Sources/Views/FeedItem/HomeFeedCardView.swift index 1a39ef7f7..fa62c73fa 100644 --- a/apple/OmnivoreKit/Sources/Views/FeedItem/HomeFeedCardView.swift +++ b/apple/OmnivoreKit/Sources/Views/FeedItem/HomeFeedCardView.swift @@ -66,7 +66,7 @@ public struct FeedCard: View { } } - if item.sortedLabels.count > 0 { + if item.hasLabels { // Category Labels ScrollView(.horizontal, showsIndicators: false) { HStack { @@ -93,5 +93,6 @@ public struct FeedCard: View { maxHeight: nil, alignment: .topLeading ) + .overlay(SyncStatusIcon(status: ServerSyncStatus(rawValue: Int(item.serverSyncStatus)) ?? ServerSyncStatus.isNSync), alignment: .bottomTrailing) } } diff --git a/apple/OmnivoreKit/Sources/Views/SyncingIcon.swift b/apple/OmnivoreKit/Sources/Views/SyncingIcon.swift index a234eb638..de0dda106 100644 --- a/apple/OmnivoreKit/Sources/Views/SyncingIcon.swift +++ b/apple/OmnivoreKit/Sources/Views/SyncingIcon.swift @@ -1,8 +1,50 @@ // // File.swift -// +// // // Created by Jackson Harper on 6/5/22. // import Foundation +import Models +import SwiftUI +import Utils + +public struct SyncStatusIcon: View { + let status: ServerSyncStatus + + init(status: ServerSyncStatus) { + self.status = status + } + + private var cloudIconName: String { + switch status { +// case .isNSync: +// return "checkmark.icloud" + case .isNSync: + return "exclamationmark.icloud" + case .isSyncing, .needsCreation, .needsDeletion, .needsUpdate: + return "icloud" + } + } + + private var cloudIconColor: Color { + switch status { +// case .isNSync: +// return .blue + case .isNSync: + return .red + case .isSyncing, .needsCreation, .needsDeletion, .needsUpdate: + return .appGrayText + } + } + + public var body: some View { + Image(systemName: cloudIconName) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 12, height: 12, alignment: .trailing) + .foregroundColor(cloudIconColor) + .padding(EdgeInsets(top: 0, leading: 0, bottom: 8, trailing: 8)) + } +}