From 5174c8e5a396804d13e8b05afcc8dd62642009f5 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 28 Jul 2026 17:09:31 +0000 Subject: [PATCH] fix: dedupe Discover apps by coordinate to avoid duplicate LazyGrid keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Browser home "Discover nsites/napplets" sections render each followed manifest in a LazyVerticalGrid keyed by "ns:"/"np:" + coordinate. The observed store (NoteListMatchingFilter, backed by a ConcurrentSkipListSet ordered by created-at/id) can surface the same addressable note twice when a replaceable manifest gets a new version — mutating the note's sort key inside the set breaks dedup. Both copies map to the same coordinate, producing a duplicate grid key and crashing with IllegalArgumentException. Collapse the mapped list by coordinate so each app appears once and grid keys stay unique. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01P9TomvuP9YnPUDCZuiQae6 --- .../amethyst/ui/screen/loggedIn/browser/BrowserScreen.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/browser/BrowserScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/browser/BrowserScreen.kt index 4e0f47f509..0090803983 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/browser/BrowserScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/browser/BrowserScreen.kt @@ -619,6 +619,10 @@ private fun List.toDiscoverApps( matchAuthor(author) }.mapNotNull { it.toDiscoverNostrApp() } .filter { it.app.coordinate !in excludeCoordinates } + // The observed store can surface the same addressable manifest twice (a replaceable note whose + // new version mutates its sort key inside the backing set), so collapse by coordinate to keep the + // grid keys unique — otherwise LazyVerticalGrid throws on the duplicate "ns:"/"np:" key. + .distinctBy { it.app.coordinate } .take(DISCOVER_NOSTR_LIMIT) .toList()