From e1c92d25adfbffe25cef2b812a1f4057f4bf6d91 Mon Sep 17 00:00:00 2001 From: systemblue Date: Fri, 5 Jun 2026 22:00:59 -0400 Subject: [PATCH] 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. --- Forji/Forji/Helpers/PaginationState.swift | 8 ++++---- Forji/Forji/Views/SearchableOverviewView.swift | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Forji/Forji/Helpers/PaginationState.swift b/Forji/Forji/Helpers/PaginationState.swift index af74840..3653449 100644 --- a/Forji/Forji/Helpers/PaginationState.swift +++ b/Forji/Forji/Helpers/PaginationState.swift @@ -15,10 +15,10 @@ final class PaginationState { 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() diff --git a/Forji/Forji/Views/SearchableOverviewView.swift b/Forji/Forji/Views/SearchableOverviewView.swift index e912f30..f746bc3 100644 --- a/Forji/Forji/Views/SearchableOverviewView.swift +++ b/Forji/Forji/Views/SearchableOverviewView.swift @@ -59,6 +59,7 @@ struct SearchableOverviewView: View { let state = PaginationState() state.cacheName = issueType + state.dedupeKey = { $0.id } state.loadFromCache() _pagination = State(initialValue: state) }