mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
use sync items query to update core data list
This commit is contained in:
parent
7bb1f92def
commit
16fa403201
5 changed files with 82 additions and 5 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -12,4 +12,5 @@ public enum UserDefaultKey: String {
|
|||
case lastSelectedLinkedItemFilter
|
||||
case lastUsedAppVersion
|
||||
case lastUsedAppBuildNumber
|
||||
case lastItemSyncTime
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue