From 6dc723ae2c274269a94a7dd43e3fcccc1582209f Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Apr 2026 21:07:16 +0000 Subject: [PATCH] feat: auto-unpin deleted posts from NIP-51 pin list When a kind-5 deletion event arrives for a note that is currently pinned, rewrite the user's PinListEvent to drop the deleted entries and broadcast the new list. Mirrors the existing deletedNotes() pattern used by peopleLists, followLists, and labeledBookmarkLists in Account. Previously the Pinned Notes screen silently hid deleted posts via the FeedContentState deletion filter, leaving orphan entries in the pin list that the user had no way to clean up. --- .../vitorpamplona/amethyst/model/Account.kt | 8 ++++++++ .../amethyst/model/nip51Lists/PinListState.kt | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 025bf0ffc..441a1be26 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -2293,6 +2293,13 @@ class Account( } } + suspend fun removeDeletedPins(deletedNotes: Set) { + if (!isWriteable()) return + + val event = pinState.removeDeletedPins(deletedNotes) ?: return + sendMyPublicAndPrivateOutbox(event) + } + suspend fun createAddPinEvent(note: Note): Pair>? { if (!isWriteable() || note.isDraft()) return null @@ -2674,6 +2681,7 @@ class Account( peopleLists.deletedNotes(deletedNotes) followLists.deletedNotes(deletedNotes) labeledBookmarkLists.deletedNotes(deletedNotes) + removeDeletedPins(deletedNotes) } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip51Lists/PinListState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip51Lists/PinListState.kt index fbe711408..f19d84630 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip51Lists/PinListState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip51Lists/PinListState.kt @@ -127,4 +127,22 @@ class PinListState( signer = signer, ) } + + suspend fun removeDeletedPins(deletedNotes: Set): PinListEvent? { + val currentList = getPinList() ?: return null + val deletedIds = deletedNotes.mapTo(HashSet()) { it.idHex } + val pinsToRemove = currentList.pinnedEvents().filter { it.eventId in deletedIds } + if (pinsToRemove.isEmpty()) return null + + var working: PinListEvent = currentList + for (pin in pinsToRemove) { + working = + PinListEvent.remove( + earlierVersion = working, + pin = pin, + signer = signer, + ) + } + return working + } }