mirror of
https://github.com/block/buzz.git
synced 2026-10-30 05:51:46 +00:00
fix(push-demo): preserve thread root for temporary replies
Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: Codex <noreply@openai.com> Ai-assisted: true
This commit is contained in:
@@ -456,10 +456,7 @@ public final class BuzzPushNotificationResolver: BuzzPushNotificationResolving {
|
||||
let conversation = channel.flatMap {
|
||||
communicationConversation(event: event, community: community, channel: $0)
|
||||
}
|
||||
let rootEventID =
|
||||
event.tags.first {
|
||||
$0.count >= 4 && $0[0] == "e" && $0[3] == "root" && !$0[1].isEmpty
|
||||
}?[1] ?? event.id
|
||||
let rootEventID = replyRootEventID(for: event)
|
||||
let replyKind = [45_001, 45_003].contains(event.kind) ? 45_003 : 9
|
||||
return BuzzPushResolution(
|
||||
title: profile?.displayName ?? shortPubkey(event.pubkey),
|
||||
@@ -491,6 +488,21 @@ public final class BuzzPushNotificationResolver: BuzzPushNotificationResolving {
|
||||
)
|
||||
}
|
||||
|
||||
/// Resolves the NIP-10 root carried by an incoming message. A direct reply
|
||||
/// to a root commonly carries only a `reply` marker, so that parent is also
|
||||
/// the thread root. Nested replies carry an explicit `root` marker, which
|
||||
/// remains authoritative.
|
||||
private static func replyRootEventID(for event: VerifiedNostrEvent) -> String {
|
||||
for marker in ["root", "reply"] {
|
||||
if let value = event.tags.first(where: {
|
||||
$0.count >= 4 && $0[0] == "e" && $0[3] == marker && !$0[1].isEmpty
|
||||
})?[1] {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return event.id
|
||||
}
|
||||
|
||||
private static func ephemeralProfile(
|
||||
event: VerifiedNostrEvent,
|
||||
communityID: String,
|
||||
|
||||
@@ -129,6 +129,43 @@ final class BuzzPushNotificationResolverTests: XCTestCase {
|
||||
XCTAssertEqual(result?.0.body, "lower ID")
|
||||
}
|
||||
|
||||
func testReplyContextUsesReplyMarkerAsRootForDirectReply() throws {
|
||||
let incoming = event(
|
||||
id: "incoming-reply",
|
||||
content: "Reply to the thread root",
|
||||
tags: [
|
||||
["h", Self.channelID],
|
||||
["e", "thread-root", "", "reply"],
|
||||
]
|
||||
)
|
||||
|
||||
let result = BuzzPushNotificationResolver.decodeResolution(
|
||||
events: [incoming],
|
||||
community: community()
|
||||
)
|
||||
|
||||
XCTAssertEqual(try XCTUnwrap(result?.0.replyContext).rootEventID, "thread-root")
|
||||
}
|
||||
|
||||
func testReplyContextPrefersExplicitRootForNestedReply() throws {
|
||||
let incoming = event(
|
||||
id: "incoming-nested-reply",
|
||||
content: "Nested reply",
|
||||
tags: [
|
||||
["h", Self.channelID],
|
||||
["e", "thread-root", "", "root"],
|
||||
["e", "immediate-parent", "", "reply"],
|
||||
]
|
||||
)
|
||||
|
||||
let result = BuzzPushNotificationResolver.decodeResolution(
|
||||
events: [incoming],
|
||||
community: community()
|
||||
)
|
||||
|
||||
XCTAssertEqual(try XCTUnwrap(result?.0.replyContext).rootEventID, "thread-root")
|
||||
}
|
||||
|
||||
func testResolveSucceedsAndMutatesGatewayContent() throws {
|
||||
let event = try JSONDecoder().decode(
|
||||
VerifiedNostrEvent.self,
|
||||
|
||||
Reference in New Issue
Block a user