Skip to content

fix(home): suppress deleted messages in inbox thread context#2311

Open
snarsinh wants to merge 1 commit into
block:mainfrom
snarsinh:bumble/fix-inbox-deleted-messages
Open

fix(home): suppress deleted messages in inbox thread context#2311
snarsinh wants to merge 1 commit into
block:mainfrom
snarsinh:bumble/fix-inbox-deleted-messages

Conversation

@snarsinh

Copy link
Copy Markdown

Problem

Messages the user had already deleted still rendered in the Home inbox detail pane, even though the channel view correctly hid them and the relay soft-deletes them on every read path. (Reported by @shams with a screenshot: deleted replies visible only via the inbox.)

Root cause (client-side)

desktop/src/features/home/useInboxThreadContext.ts fetches thread descendants with content kinds only (HOME_MENTION_EVENT_KINDS) and hydrates reactions — but never fetches the kind:5 / kind:9005 deletion markers. A deleted message can still reach events via the latched feed item or the local channel-window cache, and formatTimelineMessages only suppresses a row when a matching deletion marker is present in its input. With no markers fetched, the suppression pass had nothing to act on, so the deleted rows survived.

The channel timeline is immune because it backfills structural markers by #e via buildChannelStructuralAuxFilter. The inbox context path skipped that step.

The server is correct — every read path (feed queries, query_events, get_event_by_id) already filters deleted_at IS NULL, and the NIP-09 handler soft-deletes properly. This is purely a client hydration gap.

Fix

Mirror the channel timeline's structural-aux backfill for the inbox:

  • useInboxThreadContext.ts — fetch structural aux markers (deletions + edits, kinds 5/9005/40003) by #e over the context event ids via buildChannelStructuralAuxFilter, and expose them as a new deletionEvents field, mirroring the existing reaction hydration. Using the structural filter (rather than deletion-only) also picks up edit overlays for free.
  • HomeView.tsx — merge deletionEvents into the formatTimelineMessages(...) input array (and its useMemo deps) so the existing suppression pass drops deleted rows.

Test

Adds an e2e regression test to tests/e2e/inbox-live-update.spec.ts: "deleted thread reply is suppressed in the inbox detail pane." It seeds a thread root (mentions the current user → inbox item), a reply to delete, a surviving reply, and a kind:9005 deletion marker referencing the deleted reply; then asserts the surviving reply renders and the deleted reply does not.

Confirmed red-green: fails without the source fix, passes with it.

Validation

  • tsc --noEmit clean
  • biome check on the three files clean
  • inbox-live-update.spec.ts — 8/8 pass (incl. the new test)

The Home inbox detail pane rendered messages the user had already deleted, even though the channel view correctly hid them and the relay soft-deletes them on every read path.

Root cause is client-side. `useInboxThreadContext` fetches thread descendants with content kinds only (HOME_MENTION_EVENT_KINDS) and hydrates reactions, but never fetches the kind:5/9005 deletion markers. A deleted message can still reach `events` via the latched feed item or the local channel-window cache, and `formatTimelineMessages` only suppresses a row when a matching deletion marker is present in its input — so with no markers fetched, the deleted rows survived.

The channel timeline is immune because it backfills structural markers by #e via buildChannelStructuralAuxFilter. This mirrors that behavior for the inbox:

- useInboxThreadContext: fetch structural aux markers (deletions + edits, kinds 5/9005/40003) by #e over the context event ids and expose them as a new `deletionEvents` field, mirroring the existing reaction hydration.
- HomeView: merge `deletionEvents` into the formatTimelineMessages input (and its useMemo deps) so the existing suppression pass drops deleted rows.
- Add an e2e regression test that seeds a deletion marker for a thread reply and asserts the deleted reply is not rendered while a surviving reply is. Confirmed red-green: fails without the source fix, passes with it.

Co-authored-by: Shams Narsinh <shams@squareup.com>
Signed-off-by: Shams Narsinh <shams@squareup.com>
@snarsinh
snarsinh requested a review from a team as a code owner July 22, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant