Skip to content

Commit 0f2bccd

Browse files
Bartnpub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w
authored andcommitted
fix(mobile): recognize kind:9005 deletions in timeline
Bring mobile to parity with desktop's kind:9005 handling. Agents emit kind:9005 deletes via the CLI; without this, mobile keeps rendering agent-deleted messages until manual refresh. Two narrow mobile changes: 1. Add EventKind.nip29DeleteEvent (9005) to nostr_models.dart and include it in channelEventKinds so the channel subscription and history fetch both pick it up. 2. Teach formatTimeline's deletion walker to treat kind:9005 the same as kind:5 — collect e-tag targets from both. Tag shape is identical between the two builders so the walker is unmodified beyond the kind check. No mobile DM-notification path was found that mirrors desktop's handleDmEvent → AppShell.handleDmNotification flow, so no DM kind-gating fix is needed on mobile today. Tests: timeline_message_test.dart adds a kind:9005 deletion case mirroring the existing kind:5 test. Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
1 parent 5f9a426 commit 0f2bccd

3 files changed

Lines changed: 40 additions & 2 deletions

File tree

mobile/lib/features/channels/timeline_message.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,14 @@ List<TimelineMessage> formatTimeline(
211211
List<NostrEvent> events, {
212212
String? currentPubkey,
213213
}) {
214-
// 1. Collect deletion targets.
214+
// 1. Collect deletion targets. Both kind:5 (NIP-09) and kind:9005
215+
// (Sprout-native) are deletion markers; mirror desktop's behavior.
215216
final deletedIds = <String>{};
216217
for (final event in events) {
217-
if (event.kind != EventKind.deletion) continue;
218+
if (event.kind != EventKind.deletion &&
219+
event.kind != EventKind.nip29DeleteEvent) {
220+
continue;
221+
}
218222
for (final tag in event.tags) {
219223
if (tag.length >= 2 && tag[0] == 'e') {
220224
deletedIds.add(tag[1]);

mobile/lib/shared/relay/nostr_models.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ abstract final class EventKind {
1111
static const deletion = 5;
1212
static const reaction = 7;
1313
static const streamMessage = 9;
14+
static const nip29DeleteEvent = 9005;
1415
static const presenceUpdate = 20001;
1516
static const typingIndicator = 20002;
1617
static const auth = 22242;
@@ -37,6 +38,7 @@ abstract final class EventKind {
3738
static const channelEventKinds = [
3839
deletion, // 5
3940
reaction, // 7
41+
nip29DeleteEvent, // 9005 — Sprout-native deletion
4042
...channelMessageEventKinds,
4143
40001, // legacy pre-migration stream messages
4244
streamMessageEdit, // 40003

mobile/test/features/channels/timeline_message_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ NostrEvent _deletion({
8888
sig: '',
8989
);
9090

91+
NostrEvent _nip29Deletion({
92+
required String id,
93+
required List<String> targets,
94+
int createdAt = 2000,
95+
}) => NostrEvent(
96+
id: id,
97+
pubkey: 'alice',
98+
createdAt: createdAt,
99+
kind: EventKind.nip29DeleteEvent,
100+
tags: [
101+
['h', 'ch1'],
102+
for (final t in targets) ['e', t],
103+
],
104+
content: '',
105+
sig: '',
106+
);
107+
91108
NostrEvent _edit({
92109
required String id,
93110
required String targetId,
@@ -311,6 +328,21 @@ void main() {
311328
expect(result[0].content, 'keep');
312329
});
313330

331+
test('filters messages deleted via kind:9005 (Sprout-native)', () {
332+
// Agents emit kind:9005 deletes via the CLI. Mobile must mirror desktop
333+
// and treat 9005 as a deletion marker, otherwise agent-deleted messages
334+
// stay rendered until manual refresh.
335+
final events = [
336+
_textMsg(id: 'a', content: 'keep'),
337+
_textMsg(id: 'b', content: 'delete', createdAt: 1100),
338+
_nip29Deletion(id: 'd1', targets: ['b']),
339+
];
340+
341+
final result = formatTimeline(events);
342+
expect(result, hasLength(1));
343+
expect(result[0].content, 'keep');
344+
});
345+
314346
test('applies edits', () {
315347
final events = [
316348
_textMsg(id: 'a', content: 'original'),

0 commit comments

Comments
 (0)