Better separation of sync and search

This commit is contained in:
Jackson Harper
2023-12-26 14:23:39 +08:00
parent 701d6a6be1
commit 3362a5b016
7 changed files with 48 additions and 22 deletions

View File

@ -16,6 +16,7 @@ import Views
@AppStorage(UserDefaultKey.lastSelectedFeaturedItemFilter.rawValue) var featureFilter = FeaturedItemFilter.continueReading.rawValue
var limit = 10
var cursor: String?
var totalCount: Int?
@ -55,11 +56,17 @@ import Views
return
}
let queryResult = try? await dataService.loadLinkedItems(
limit: 10,
searchQuery: searchQuery(filterState),
cursor: isRefresh ? nil : loadCursor ?? cursor
)
var queryResult: LinkedItemQueryResult?
do {
queryResult = try await dataService.loadLinkedItems(
limit: limit,
searchQuery: searchQuery(filterState),
cursor: isRefresh ? nil : loadCursor ?? cursor
)
} catch {
print("ERROR loading library items: ", error)
}
if let appliedFilter = filterState.appliedFilter, let queryResult = queryResult {
let newItems: [Models.LibraryItem] = {
@ -70,6 +77,9 @@ import Views
return itemObjects
}()
print("LOAD CURSOR: ", loadCursor, " new cursor: ", queryResult.cursor)
print("NEW ITEMS: ", newItems.count, newItems.map { "\($0.title)\n" })
if filterState.searchTerm.replacingOccurrences(of: " ", with: "").isEmpty, appliedFilter.allowLocalFetch {
updateFetchController(dataService: dataService, filterState: filterState)
} else {
@ -82,6 +92,8 @@ import Views
}
receivedIdx = thisSearchIdx
limit = 20 // Once we have one successful fetch with 10 items we increase to 20 per fetch
cursor = queryResult.cursor
totalCount = queryResult.totalCount
@ -117,7 +129,7 @@ import Views
func loadMoreItems(dataService: DataService, filterState: FetcherFilterState, loadCursor: String? = nil) async {
if let appliedFilter = filterState.appliedFilter, appliedFilter.shouldRemoteSearch {
let idx = max(items.count - 1, 0)
let idx = max(items.count, 0)
await loadSearchQuery(
dataService: dataService,
filterState: filterState,
@ -187,7 +199,6 @@ import Views
sectionNameKeyPath: nil,
cacheName: nil
)
guard let fetchedResultsController = fetchedResultsController else {
return
}

View File

@ -683,7 +683,7 @@ struct AnimatingCellHeight: AnimatableModifier {
.onAppear {
if idx >= viewModel.fetcher.items.count - 5 {
Task {
await viewModel.loadMore(dataService: dataService, loadCursor: idx.description)
await viewModel.loadMore(dataService: dataService)
}
}
}
@ -1031,7 +1031,7 @@ struct BottomView: View {
}
var innerBody: some View {
if viewModel.fetcher.items.count < 5 {
if viewModel.fetcher.items.count < 3 {
AnyView(Color.clear)
} else {
AnyView(HStack {

View File

@ -73,7 +73,7 @@ public struct LibrarySplitView: View {
}
.onReceive(NSNotification.performSyncPublisher) { _ in
Task {
await syncManager.syncItems(dataService: dataService)
await syncManager.syncUpdates(dataService: dataService)
}
}
}

View File

@ -123,7 +123,7 @@ struct LibraryTabView: View {
.navigationBarHidden(true)
.onReceive(NSNotification.performSyncPublisher) { _ in
Task {
await syncManager.syncItems(dataService: dataService)
await syncManager.syncUpdates(dataService: dataService)
}
}
.onOpenURL { url in

View File

@ -19,13 +19,21 @@ public struct LinkedItemSyncResult {
public let cursor: String?
public let hasMore: Bool
public let mostRecentUpdatedAt: Date?
public let oldestUpdatedAt: Date?
public let isEmpty: Bool
public init(updatedItemIDs: [String], cursor: String?, hasMore: Bool, mostRecentUpdatedAt: Date?, isEmpty: Bool) {
public init(updatedItemIDs: [String],
cursor: String?,
hasMore: Bool,
mostRecentUpdatedAt: Date?,
oldestUpdatedAt: Date?,
isEmpty: Bool)
{
self.updatedItemIDs = updatedItemIDs
self.cursor = cursor
self.hasMore = hasMore
self.mostRecentUpdatedAt = mostRecentUpdatedAt
self.oldestUpdatedAt = oldestUpdatedAt
self.isEmpty = isEmpty
}
}

View File

@ -15,17 +15,22 @@ public extension DataService {
LibraryItem.deleteItems(ids: fetchResult.deletedItemIDs, context: backgroundContext)
if fetchResult.items.persist(context: backgroundContext) == nil {
throw BasicError.message(messageText: "CoreData error")
if !fetchResult.updatedItems.isEmpty {
if fetchResult.updatedItems.persist(context: backgroundContext) == nil {
throw BasicError.message(messageText: "CoreData error")
}
}
let newestChange = fetchResult.items.max { $0.updatedAt < $1.updatedAt }
let newestChange = fetchResult.updatedItems.max { $0.updatedAt < $1.updatedAt }
let oldestChange = fetchResult.updatedItems.min { $0.updatedAt < $1.updatedAt }
let result = LinkedItemSyncResult(
updatedItemIDs: fetchResult.items.map(\.id),
updatedItemIDs: fetchResult.updatedItems.map(\.id),
cursor: fetchResult.cursor,
hasMore: fetchResult.hasMoreItems,
mostRecentUpdatedAt: newestChange?.updatedAt,
isEmpty: fetchResult.deletedItemIDs.isEmpty && fetchResult.items.isEmpty
oldestUpdatedAt: oldestChange?.updatedAt,
isEmpty: fetchResult.deletedItemIDs.isEmpty && fetchResult.updatedItems.isEmpty
)
return result

View File

@ -10,8 +10,8 @@ struct InternalLinkedItemQueryResult {
}
struct InternalLinkedItemUpdatesQueryResult {
let items: [InternalLibraryItem]
let deletedItemIDs: [String]
let updatedItems: [InternalLibraryItem]
let cursor: String?
let hasMoreItems: Bool
let totalCount: Int
@ -20,6 +20,7 @@ struct InternalLinkedItemUpdatesQueryResult {
private struct SyncItemEdge {
let itemID: String
let isDeletedItem: Bool
let isUpdatedItem: Bool
let item: InternalLibraryItem?
}
@ -91,21 +92,21 @@ extension DataService {
switch payload.data {
case let .success(result: result):
var items = [InternalLibraryItem]()
var updatedItems = [InternalLibraryItem]()
var deletedItemIDs = [String]()
for edge in result.edges {
if edge.isDeletedItem {
deletedItemIDs.append(edge.itemID)
} else if let item = edge.item {
items.append(item)
} else if let item = edge.item, edge.isUpdatedItem {
updatedItems.append(item)
}
}
continuation.resume(
returning: InternalLinkedItemUpdatesQueryResult(
items: items,
deletedItemIDs: deletedItemIDs,
updatedItems: updatedItems,
cursor: result.cursor,
hasMoreItems: result.hasMoreItems,
totalCount: result.totalCount
@ -292,6 +293,7 @@ private let syncItemEdgeSelection = Selection.SyncUpdatedItemEdge {
SyncItemEdge(
itemID: try $0.itemId(),
isDeletedItem: try $0.updateReason() == .deleted,
isUpdatedItem: try $0.updateReason() == .updated,
item: try $0.node(selection: searchItemSelection.nullable)
)
}