Originally created by: kristofferR
Two bugs in the row-driven notification fallback, both visible in a single group banner:
<img> elements inside the preview span, so scraping the row with textContent dropped them. "Kim: π’" notified as "Kim:", and an emoji-only message produced an empty body β which the fallback reads as an unhydrated row, so it never notified at all.alt β no per-sender identity anywhere in the row. The first image (alphabetically first member) was used for every sender.Emoji β conversationNodeText() (new, in lib/conversation-row.ts) walks a row node and restores the glyph from the sprite's alt, from aria-label for background-image emoji, and from a bare-emoji alt when features/emoji-images.ts has deferred the src. It skips the System emoji feature's injected glyph spans so nothing doubles, and emojiGlyph() now keeps keycap sequences (1οΈβ£, #οΈβ£) that its numeric-label guard used to reject. The same text now feeds the unread-weight check, and the row's own image pick skips emoji sprites.
Group sender avatars β Messenger does pair a name with a face wherever it renders people: each message row carries an h3 short name plus an avatar whose alt is the full name, and the conversation-info chat-member list is shaped the same way. SenderAvatarStore (new lib/sender-avatars.ts) harvests those pairings as they render β throttled to once per 5s inside the existing scan β into a bounded (120-entry, LRU) cache persisted so the auto-refresh reload doesn't empty it. A group fallback notification parses the "Kim:" prefix and looks it up: exact match, or a unique full-name match; an ambiguous "Kim" and an expired avatar URL both fall back to the row's own image, so a wrong face is never preferred over the group photo.
Coverage note: a group's senders resolve once that thread (or its member list) has rendered at least once β before that, the thread picture is used, i.e. today's behaviour.
Dev tooling β two sanitized probes in the dev-only MCP bridge, documented in AGENTS.md: __carrier_mcp_notification_row_probe__ (row/message-row shape) and __carrier_mcp_sender_avatar_probe__ (what the harvest would take, what it cached, and how each visible group preview resolves). Both report classifications and counts only β never message text, contact names, or image URLs.
Unit tests for the new logic (conversationNodeText, SenderAvatarStore, groupPreviewSender, keycap glyphs), plus live checks against real Messenger DOM in a --features mcp debug build:
exact β its next notification shows the sender rather than the group photo.cargo fmt / clippy -D warnings / cargo test --lib, and Biome + tsc + bun test with the inject bundles regenerated.
Ref [#135]
Originally posted by: kristofferR
@codex review
Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: coderabbitai[bot]
π Walkthrough
## Walkthrough Messenger notification handling now reconstructs emoji-aware row text, harvests and persists sender avatars for group fallback icons, and exposes privacy-safe notification diagnostics through MCP probes. Tests cover parsing, keycaps, sender-avatar persistence, and group sender extraction. ### Changes **Notification inspection and fallback flow** |Layer / File(s)|Summary| |---|---| |**Emoji-aware conversation text parsing**`inject/src/messenger/lib/emoji.ts`, `inject/src/messenger/lib/conversation-row.ts`, `inject/src/messenger/features/system-emoji.ts`, `src-tauri/inject/messenger.js`, `inject/src/messenger/lib/*test.ts`|Shared emoji constants and keycap handling support DOM text reconstruction while excluding Carrier system-emoji glyphs; related tests cover the new parsing cases.| |**Thread-scoped sender-avatar storage**
`inject/src/messenger/lib/sender-avatars.ts`, `inject/src/messenger/lib/sender-avatars.test.ts`|A bounded persistent store tracks thread-specific avatar mappings, ambiguity, group threads, photo identities, eviction, and resolution statistics.| |**Sender-avatar harvesting and fallback icons**
`inject/src/messenger/features/notifications.ts`, `inject/src/messenger/lib/notification-fallback.ts`, `src-tauri/inject/messenger.js`, `inject/src/types.d.ts`, `inject/src/messenger/lib/*test.ts`|Throttled UI harvesting, group sender parsing, richer row classification, persisted notification-version updates, and sender-specific fallback icons were added and tested.| |**Privacy-safe notification probes**
`src-tauri/inject/mcp-bridge.js`, `AGENTS.md`|MCP handlers inspect notification rows and sender-avatar resolution while returning sanitized classifications, counts, and masked metadata.| **Estimated code review effort:** 4 (Complex) | ~45 minutes ### Sequence Diagram(s) :::mermaid sequenceDiagram participant MessengerDOM participant scanUnreadConversations participant SenderAvatarStore participant scheduleFallback participant NativeNotification MessengerDOM->>scanUnreadConversations: visible rows and avatar candidates scanUnreadConversations->>SenderAvatarStore: remember sender/avatar mappings scanUnreadConversations->>scheduleFallback: group conversation preview scheduleFallback->>SenderAvatarStore: lookup sender avatar scheduleFallback->>NativeNotification: selected notification icon **Possibly related PRs** - [[kristofferR/Carrier#99](https://github.com/kristofferR/Carrier/issues/99)](https://github.com/kristofferR/Carrier/pull/99): Modifies the persisted notification fallback and unread-scanning flow. - [[kristofferR/Carrier#137](https://github.com/kristofferR/Carrier/issues/137)](https://github.com/kristofferR/Carrier/pull/137): Touches conversation-row parsing and Messenger notification routing paths. - [[kristofferR/Carrier#164](https://github.com/kristofferR/Carrier/issues/164)](https://github.com/kristofferR/Carrier/pull/164): Touches notification reconciliation and persisted notification matching paths.
π₯ Pre-merge checks | β 4 | β 1
### β Failed checks (1 warning) | Check name | Status | Explanation | Resolution | | :----------------: | :--------- | :------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------- | | Docstring Coverage | β οΈ Warning | Docstring coverage is 47.17% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |β Passed checks (4 passed)
| Check name | Status | Explanation | | :------------------------: | :------- | :------------------------------------------------------------------------------------------------------------------ | | Description Check | β Passed | Check skipped - CodeRabbitβs high-level summary is enabled. | | Title check | β Passed | The title matches the main changes: restoring emoji handling and using the group senderβs avatar for notifications. | | Linked Issues check | β Passed | Check skipped because no linked issues were found for this pull request. | | Out of Scope Changes check | β Passed | Check skipped because no linked issues were found for this pull request. |β¨ Finishing Touches
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests - [ ] Commit unit tests in branch `fix/notification-emoji-and-group-sender-avatars`Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
β€οΈ Share
- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)Comment
@coderabbitai helpto get the list of available commands.Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: kristofferR
@coderabbitai review
Originally posted by: kristofferR
@codex review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: kristofferR
@codex review
Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: kristofferR
@codex review
Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: kristofferR
@codex review
Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: kristofferR
@codex review
Originally posted by: kristofferR
@coderabbitai review
Originally posted by: coderabbitai[bot]
β Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.