fix(notifications): handle the whole follow family, not just follow - #1708
Conversation
enotify's str_activity_type() emits follow, unfollow, ignore and blacklist over the websocket, and all four share ACTIVITY_MAIN_TYPE_FOLLOW. The client only knew about "follow", so the other three were mishandled at every gate: - getBody() had no branch, returning "", and the delivery path short-circuits on a falsy body, so the toast was dropped entirely - getLink() had no branch, so they fell to the default and produced no destination at all - getNotificationType() returned null, which the delivery gate reads as always-allowed, so turning the Follows toggle off did not silence them - WsFollowNotification.type was narrowed to "follow", so those branches could not be added without widening the union first blacklist also never reached its own component: notification-list-item routed only follow/unfollow/ignore to NotificationFollowType, so it hit the unknown type fallback and rendered the raw untranslated word "blacklist". ApiFollowNotification gains "blacklist" to match, since the API serializer now returns follower/following for it. New strings: notification.unfollowed, notification.ignored, notification.blacklisted and notifications.blacklisted-str. The push tables (push-notification-link.ts, firebase-messaging-sw.js) already route follow/unfollow/ignore to the source profile and are unchanged. blacklist is deliberately absent there because it has no push template server side. Specs pin the family across all three tables. Verified by mutation: dropping unfollow/ignore/blacklist from getNotificationType fails the new case.
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
PR Summary by QodoHandle all follow-family notification types
AI Description
Diagram
High-Level Assessment
Files changed (8)
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can describe a rule in plain language on the Rules page and Qodo drafts it for you |
|
Warning Review limit reachedNext included review available in 19 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (1)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (8)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe change adds ChangesFollow-family notification support
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This change enables all follow-family notifications to render, link correctly, and respect the existing Follows preference without altering deployment or persistent state. No actionable merge-blocking risk remains after normal checks and review. Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 7 files. (1 skipped: 1 unsupported.) ✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
.blacklist-label was rendered but never styled, so blacklist rows showed as plain inline text while the other three in the family rendered as pills. Uses blue-dark-grey rather than a brighter red: it is the darkest of the four, matching that blacklist is the family's harshest member, and it clears AA at 12px. red-040 (#ec3323) is only 4.15:1 against white, and red-030 is already ignore's.
|
Fixed in
On the colour: I went with
|
Part of the follow notification outage fix. Backend counterpart: ecency/enotify-py#20.
Problem
enotify'sstr_activity_type()emits four wire types for the follow family:follow,unfollow,ignoreandblacklist. They all shareACTIVITY_MAIN_TYPE_FOLLOWserver side. The client only knew about"follow", so the other three were mishandled at every gate:getBody()"", and the delivery path short-circuits on a falsy body, so the toast was dropped entirelygetLink()default, so no destination at allgetNotificationType()null, which the delivery gate reads as always-allowed, so turning the Follows toggle off did not silence themWsFollowNotification["type"]"follow", so those branches could not be added without widening the union firstblacklistnever reached its own component either:notification-list-itemrouted only follow/unfollow/ignore toNotificationFollowType, so it hit the unknown-type fallback and rendered the raw untranslated wordblacklist.This has been latent rather than visible, because the backend stopped producing any follow-family rows on 2026-06-26. It becomes visible the moment #20 ships.
Changes
notifications-ws-api.ts:unfollow/ignore/blacklistcases ingetBody,getLink(all four go to the actor's profile) andgetNotificationType(all four map toNotifyTypes.FOLLOW)ws-notifications.tsand the SDK'snotification.ts: widenWsFollowNotification["type"]to the four; add"blacklist"toApiFollowNotification["type"], matching the API serializer that now returnsfollower/followingfor itnotification-follow-type.tsx/notification-list-item.tsx: render blacklist through the follow component instead of the raw-word fallbacknotification.unfollowed,notification.ignored,notification.blacklisted,notifications.blacklisted-strNot changed
push-notification-link.tsandfirebase-messaging-sw.jsalready routefollow/unfollow/ignoreto the source profile.blacklistis deliberately absent from both: it has no push template server side, so it is never enqueued.Tests
Extended
notifications-ws-notify-type-mapping.spec.tsandnotifications-ws-link.spec.tsto pin the whole family across all three tables, including a case assertinggetBodyis non-empty for each, since an empty body is what silently drops a notification.Verified by mutation: dropping
unfollow/ignore/blacklistfromgetNotificationTypefails the new case.pnpm test3681 passed,pnpm typecheckclean,pnpm lintclean.Summary by CodeRabbit
New Features
Bug Fixes
Tests