Skip to content

refactor(desktop): consolidate notification helpers and add channel names to toasts#1286

Merged
wpfleger96 merged 1 commit into
mainfrom
duncan/shared-notification-helpers
Jun 25, 2026
Merged

refactor(desktop): consolidate notification helpers and add channel names to toasts#1286
wpfleger96 merged 1 commit into
mainfrom
duncan/shared-notification-helpers

Conversation

@wpfleger96

Copy link
Copy Markdown
Collaborator

What

Extracts three shared helpers into a new notificationFormat.ts module and wires all desktop notification paths through them, fixing missing channel names in thread reply and reminder toasts.

New file: desktop/src/features/notifications/lib/notificationFormat.ts

  • resolveNotificationChannelLabel(channelId, channels) — returns "#channelName" or null (null-safe: returns null when the channels query hasn't resolved yet, so the toast still fires with just the prefix)
  • truncateNotificationBody(content, fallback) — consistent 140-char truncation with ... suffix
  • formatNotificationTitle({ prefix, channelLabel }) — produces "prefix in #channel" or just "prefix"

Why

Thread reply toasts fell back to "Reply in Thread" when the channels array was empty at WebSocket event time (race condition: the channels query hadn't resolved yet). Reminder toasts had no channel context at all. Each of the four toast paths had its own inline body truncation logic with slightly different behavior.

Changes per path

Path Before After
Feed (mentions/needs_action) Own notificationTitle() + inline truncation Delegates to formatNotificationTitle() + truncateNotificationBody(); behavior unchanged
Thread replies Inline channels.find()"Reply in Thread" on miss channels.find()"Reply in #channelName" or "Reply" on miss
DMs Inline truncation Uses truncateNotificationBody(); title unchanged (participants are the title)
Reminders Hardcoded "Reminder due" "Reminder due in #channelName" for single-reminder toasts with a target channel

Notes

  • The race condition fallback is intentional: returning null from resolveNotificationChannelLabel when the channel isn't in the list means the toast fires with just the prefix rather than being blocked. This is better UX than a silent miss.
  • Multiple due reminders omit channel context (they may span different channels); the body count "N reminders are due" is the signal.
  • useChannelsQuery() in AppShell.tsx is moved 13 lines earlier so channels is available before useReminderNotifications is called. Hook call order is preserved.

…ames to toasts

Thread reply toasts fell back to "Reply in Thread" when the channels
query hadn't resolved yet — the inline channels.find() returned
undefined on an empty array. Reminder toasts had no channel context
at all.

Extract three shared helpers into notificationFormat.ts:
resolveNotificationChannelLabel, truncateNotificationBody, and
formatNotificationTitle. Wire all affected paths through them so
channel name resolution and body truncation are consistent across
every toast type.

Thread replies now show "Reply in #channelName" (null-safe: falls
back to "Reply" when the channel isn't loaded yet). Reminder toasts
now show "Reminder due in #channelName" for single-reminder toasts
with a target channel. Feed path behavior is unchanged — it already
had correct formatting and now delegates body truncation to the shared
helper. DM path title is unchanged (participants are the title).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96 wpfleger96 merged commit dd5592e into main Jun 25, 2026
45 of 47 checks passed
@wpfleger96 wpfleger96 deleted the duncan/shared-notification-helpers branch June 25, 2026 17:07
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