fix: search result always append to last issue

This commit is contained in:
CMK 2021-07-14 21:08:17 +08:00
parent d8af11a9bc
commit 2c041e70b2
2 changed files with 25 additions and 11 deletions

View File

@ -37,7 +37,8 @@ extension SearchResultViewModel.State {
let logger = Logger(subsystem: "SearchResultViewModel.State.Loading", category: "Logic") let logger = Logger(subsystem: "SearchResultViewModel.State.Loading", category: "Logic")
var previousSearchText = "" var previousSearchText = ""
var offset = 0 var offset: Int? = nil
var latestLoadingToken = UUID()
override func isValidNextState(_ stateClass: AnyClass) -> Bool { override func isValidNextState(_ stateClass: AnyClass) -> Bool {
guard let viewModel = self.viewModel else { return false } guard let viewModel = self.viewModel else { return false }
@ -77,15 +78,15 @@ extension SearchResultViewModel.State {
if searchText != previousSearchText { if searchText != previousSearchText {
previousSearchText = searchText previousSearchText = searchText
offset = nil
} }
// not set offset for all case // not set offset for all case
// and assert other cases the items are all the same type elements // and assert other cases the items are all the same type elements
let offset: Int? = { let _offset: Int? = {
switch searchType { switch searchType {
case .default: return nil case .default: return nil
default: default: return offset
return viewModel.items.value.isEmpty ? nil : viewModel.items.value.count
} }
}() }()
@ -98,10 +99,13 @@ extension SearchResultViewModel.State {
excludeUnreviewed: nil, excludeUnreviewed: nil,
resolve: nil, resolve: nil,
limit: nil, limit: nil,
offset: offset, offset: _offset,
following: nil following: nil
) )
let id = UUID()
latestLoadingToken = id
viewModel.context.apiService.search( viewModel.context.apiService.search(
domain: domain, domain: domain,
query: query, query: query,
@ -121,9 +125,12 @@ extension SearchResultViewModel.State {
// discard result when search text is outdated // discard result when search text is outdated
guard searchText == self.previousSearchText else { return } guard searchText == self.previousSearchText else { return }
// discard result when request not the latest one
guard id == self.latestLoadingToken else { return }
// discard result when state is not Loading
guard stateMachine.currentState is Loading else { return } guard stateMachine.currentState is Loading else { return }
let oldItems = offset == nil ? [] : viewModel.items.value let oldItems = _offset == nil ? [] : viewModel.items.value
var newItems: [SearchResultItem] = [] var newItems: [SearchResultItem] = []
for account in response.value.accounts { for account in response.value.accounts {
@ -136,17 +143,18 @@ extension SearchResultViewModel.State {
guard !oldItems.contains(item) else { continue } guard !oldItems.contains(item) else { continue }
newItems.append(item) newItems.append(item)
} }
if searchType == .default {
newItems.sort(by: { ($0.sortKey ?? "") < ($1.sortKey ?? "")})
}
var newStatusIDs = offset == nil ? [] : viewModel.statusFetchedResultsController.statusIDs.value var newStatusIDs = _offset == nil ? [] : viewModel.statusFetchedResultsController.statusIDs.value
for status in response.value.statuses { for status in response.value.statuses {
guard !newStatusIDs.contains(status.id) else { continue } guard !newStatusIDs.contains(status.id) else { continue }
newStatusIDs.append(status.id) newStatusIDs.append(status.id)
} }
stateMachine.enter(Idle.self) if viewModel.searchScope == .all {
stateMachine.enter(NoMore.self)
} else {
stateMachine.enter(Idle.self)
}
viewModel.items.value = oldItems + newItems viewModel.items.value = oldItems + newItems
viewModel.statusFetchedResultsController.statusIDs.value = newStatusIDs viewModel.statusFetchedResultsController.statusIDs.value = newStatusIDs
} }

View File

@ -65,6 +65,12 @@ final class SearchResultViewModel {
snapshot.appendSections([.main]) snapshot.appendSections([.main])
// append account & hashtag items // append account & hashtag items
var items = items
if self.searchScope == .all {
// all search scope not paging. it's safe sort on whole dataset
items.sort(by: { ($0.sortKey ?? "") < ($1.sortKey ?? "")})
}
snapshot.appendItems(items, toSection: .main) snapshot.appendItems(items, toSection: .main)
var oldSnapshotAttributeDict: [NSManagedObjectID : Item.StatusAttribute] = [:] var oldSnapshotAttributeDict: [NSManagedObjectID : Item.StatusAttribute] = [:]