fix: de-duplicate involved-scope results across pages in single-instance overviews

The Issues and Pull Requests overviews fire one search request per
involvement flag and merge the results, so the same issue can resurface
on a later page (created on page 1, assigned on page 2). The merged
multi-instance overview already guards against this with a pagination
dedupe key, but the single-instance overview never set one, so loading
more appended duplicate rows with duplicate Identifiable ids.

Set the same dedupe key the merged overview uses, which also switches
hasMore to the contributed-new-items heuristic that fits combined
sources.
This commit is contained in:
systemblue 2026-06-05 22:00:59 -04:00
parent 2a679140e6
commit e1c92d25ad
2 changed files with 5 additions and 4 deletions

View file

@ -15,10 +15,10 @@ final class PaginationState<Item> {
let pageSize: Int
var cacheName: String?
/// Optional key extractor enabling cross-page de-duplication. Merged views set
/// this because they combine paginated results from several instances, where
/// the same item can resurface on a later page (overlapping involvement
/// queries) and the merged page size no longer matches `pageSize`.
/// Optional key extractor enabling cross-page de-duplication. Views that
/// combine several paginated sources set this (merged multi-instance lists,
/// or the per-flag involvement queries), because the same item can resurface
/// on a later page and the combined page size no longer matches `pageSize`.
@ObservationIgnored var dedupeKey: ((Item) -> AnyHashable)?
@ObservationIgnored private var seenKeys = Set<AnyHashable>()

View file

@ -59,6 +59,7 @@ struct SearchableOverviewView<Row: View, Detail: View, CreateView: View>: View {
let state = PaginationState<Issue>()
state.cacheName = issueType
state.dedupeKey = { $0.id }
state.loadFromCache()
_pagination = State(initialValue: state)
}