Merge pull request #2513 from vitorpamplona/claude/fix-whitenoise-reactions-EWq2j
Filter non-displayable messages from Marmot group chat feed
This commit is contained in:
@@ -914,6 +914,20 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is ChatEvent -> {
|
||||
// Amethyst's own kind:9 replies carry the parent as a NIP-18
|
||||
// `q` tag (see ChatEvent.replyingTo), but the broader Marmot
|
||||
// ecosystem — WhiteNoise in particular — threads kind:9 chats
|
||||
// with a plain NIP-10 `e` tag. Accept both so inbound replies
|
||||
// from either client show their quote bubble in the feed.
|
||||
val eTagTargets =
|
||||
event.tags
|
||||
.filter { it.size > 1 && it[0] == "e" }
|
||||
.map { it[1] }
|
||||
val qTagTargets = event.quotedEvents().map { it.eventId }
|
||||
(eTagTargets + qTagTargets).mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
else -> {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
+25
@@ -47,6 +47,7 @@ class MarmotGroupList(
|
||||
nostrGroupId: HexKey,
|
||||
msg: Note,
|
||||
) {
|
||||
if (!isDisplayableFeedMessage(msg)) return
|
||||
val chatroom = getOrCreateGroup(nostrGroupId)
|
||||
val isSelfAuthored = msg.author?.pubkeyHex == ownerPubKey
|
||||
// Use the quiet path for our own messages so the relay round-trip
|
||||
@@ -74,6 +75,7 @@ class MarmotGroupList(
|
||||
nostrGroupId: HexKey,
|
||||
msg: Note,
|
||||
) {
|
||||
if (!isDisplayableFeedMessage(msg)) return
|
||||
val chatroom = getOrCreateGroup(nostrGroupId)
|
||||
if (chatroom.restoreMessageSync(msg)) {
|
||||
noteToGroupIndex.getOrCreate(msg.idHex) { nostrGroupId }
|
||||
@@ -135,4 +137,27 @@ class MarmotGroupList(
|
||||
rooms.forEach { key, _ -> result.add(key) }
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this inner event should appear as its own bubble in the group
|
||||
* chat feed. Side-channel kinds (reactions, deletions) must still be
|
||||
* consumed into LocalCache — they drive the reaction row on the target
|
||||
* note and, for kind:5, revoke a prior reaction — but they must NOT show
|
||||
* up as standalone messages.
|
||||
*
|
||||
* Needed because WhiteNoise emits plain kind:7 reactions (emoji content +
|
||||
* `e` tag) and kind:5 unreacts inside kind:445, and the Marmot pipeline
|
||||
* blindly routed every inner event into the chatroom. The reaction then
|
||||
* rendered as a chat bubble containing just the emoji, with a quoted
|
||||
* citation of the target message — which reads exactly like a reply.
|
||||
*/
|
||||
private fun isDisplayableFeedMessage(msg: Note): Boolean {
|
||||
val kind = msg.event?.kind ?: return true
|
||||
return kind != MARMOT_INNER_KIND_REACTION && kind != MARMOT_INNER_KIND_DELETION
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MARMOT_INNER_KIND_DELETION = 5
|
||||
private const val MARMOT_INNER_KIND_REACTION = 7
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,7 +776,11 @@ test_09_reply_react_unreact() {
|
||||
fi
|
||||
|
||||
step "B replies to the anchor"
|
||||
wn_b messages send "$gid" "replying via wn" --reply_to "$msg_id" >/dev/null 2>&1 || true
|
||||
# clap v4 converts snake_case fields to kebab-case flags by default, so the
|
||||
# `reply_to: Option<String>` field on `wn messages send` exposes as
|
||||
# `--reply-to`. Passing `--reply_to` is silently rejected (the script's
|
||||
# `|| true` hides the error) and the reply is never actually published.
|
||||
wn_b messages send "$gid" "replying via wn" --reply-to "$msg_id" >/dev/null 2>&1 || true
|
||||
sleep 3
|
||||
if confirm "Does Amethyst show 'replying via wn' as a threaded reply to the anchor?"; then
|
||||
record_result "09 reply/react" pass
|
||||
|
||||
Reference in New Issue
Block a user