use sync items query to update core data list

This commit is contained in:
Satindar Dhillon 2022-08-04 14:46:38 -07:00
parent 7bb1f92def
commit 16fa403201
5 changed files with 82 additions and 5 deletions

View file

@ -6,6 +6,8 @@ import Utils
import Views
@MainActor final class HomeFeedViewModel: NSObject, ObservableObject {
let dateFormatter = DateFormatter.formatterISO8601
var currentDetailViewModel: LinkItemDetailViewModel?
private var fetchedResultsController: NSFetchedResultsController<LinkedItem>?
@ -26,7 +28,11 @@ import Views
@Published var appliedFilter = LinkedItemFilter.inbox.rawValue
@Published var appliedSort = LinkedItemSort.newest.rawValue
@AppStorage(UserDefaultKey.lastSelectedLinkedItemFilter.rawValue)
// @AppStorage(UserDefaultKey.lastSelectedLinkedItemFilter.rawValue) // TODO: missing value here?
// TODO: delete this value when needed (logout, clear core data, new app version
@AppStorage(UserDefaultKey.lastItemSyncTime.rawValue) var lastItemSyncTime = Date(
timeIntervalSinceReferenceDate: 0
).toString()
var cursor: String?
@ -50,6 +56,11 @@ import Views
items.insert(item, at: 0)
}
func loadUpdatedItems(since _: Date, updatedCursor _: String?) {
isLoading = true
showLoadingBar = true
}
func loadItems(dataService: DataService, isRefresh: Bool) async {
let thisSearchIdx = searchIdx
searchIdx += 1
@ -62,6 +73,14 @@ import Views
Task { _ = try? await dataService.fetchViewer() }
}
// Sync items if necessary
let lastSyncDate = dateFormatter.date(from: lastItemSyncTime) ?? Date(timeIntervalSinceReferenceDate: 0)
let syncResult = try? await dataService.syncLinkedItems(since: lastSyncDate, cursor: nil)
if syncResult != nil {
lastItemSyncTime = Date().toString()
}
let queryResult = try? await dataService.loadLinkedItems(
limit: 10,
searchQuery: searchQuery,

View file

@ -154,4 +154,12 @@ public extension LinkedItem {
}
}
}
static func deleteItems(ids: [String], context: NSManagedObjectContext) {
for itemID in ids {
if let linkedItem = lookup(byID: itemID, inContext: context) {
linkedItem.remove(inContext: context)
}
}
}
}

View file

@ -3,6 +3,49 @@ import Foundation
import Models
public extension DataService {
/// Requests `LinkedItem`s updates from the server since a certain datae
/// and stores it in CoreData while deleting all the items with ids the server says
/// have been deleted.
/// - Parameters:
/// - limit: max count of items
/// - searchQuery: search terms and filters
/// - cursor: cursor when loading batch for infinite list
/// - Returns: `LinkedItemQueryResult` (managed object IDs and an optional cursor)
func syncLinkedItems(
since date: Date,
cursor: String?,
previousQueryResult: LinkedItemQueryResult? = nil
) async throws -> LinkedItemQueryResult {
if previousQueryResult == nil {
// Send offline changes to server before fetching items
// only on the first call of this function
try? await syncOfflineItemsWithServerIfNeeded()
}
let fetchResult = try await linkedItemUpdates(since: date, limit: 20, cursor: cursor)
LinkedItem.deleteItems(ids: fetchResult.deletedItemIDs, context: backgroundContext)
guard let itemIDs = fetchResult.items.persist(context: backgroundContext) else {
throw BasicError.message(messageText: "CoreData error")
}
let result = LinkedItemQueryResult(
itemIDs: itemIDs + (previousQueryResult?.itemIDs ?? []),
cursor: fetchResult.cursor
)
if fetchResult.hasMoreItems, (previousQueryResult?.itemIDs.count ?? 0) < 200 {
return try await syncLinkedItems(
since: date,
cursor: fetchResult.cursor,
previousQueryResult: result
)
}
return result
}
/// Requests `LinkedItem`s from the server and stores it in CoreData.
/// - Parameters:
/// - limit: max count of items

View file

@ -12,6 +12,7 @@ struct InternalLinkedItemUpdatesQueryResult {
let items: [InternalLinkedItem]
let deletedItemIDs: [String]
let cursor: String?
let hasMoreItems: Bool
}
private struct SyncItemEdge {
@ -23,13 +24,14 @@ private struct SyncItemEdge {
extension DataService {
// swiftlint:disable:next function_body_length
func linkedItemUpdates(
since: Date,
limit: Int,
cursor: String?,
since: Date?
cursor: String?
) async throws -> InternalLinkedItemUpdatesQueryResult {
struct QuerySuccessResult {
let edges: [SyncItemEdge]
let cursor: String?
let hasMoreItems: Bool
}
enum QueryResult {
case success(result: QuerySuccessResult)
@ -50,6 +52,9 @@ extension DataService {
edges: try $0.edges(selection: syncItemEdgeSelection.list),
cursor: try $0.pageInfo(selection: Selection.PageInfo {
try $0.endCursor()
}),
hasMoreItems: try $0.pageInfo(selection: Selection.PageInfo {
try $0.hasNextPage()
})
)
)
@ -61,7 +66,7 @@ extension DataService {
try $0.updatesSince(
after: OptionalArgument(cursor),
first: OptionalArgument(limit),
since: DateTime(from: since ?? Date(timeIntervalSinceReferenceDate: 0)),
since: DateTime(from: since),
selection: selection
)
}
@ -90,7 +95,8 @@ extension DataService {
returning: InternalLinkedItemUpdatesQueryResult(
items: items,
deletedItemIDs: deletedItemIDs,
cursor: result.cursor
cursor: result.cursor,
hasMoreItems: result.hasMoreItems
)
)
case let .error(error):

View file

@ -12,4 +12,5 @@ public enum UserDefaultKey: String {
case lastSelectedLinkedItemFilter
case lastUsedAppVersion
case lastUsedAppBuildNumber
case lastItemSyncTime
}