From c68d84318e6a3e5f4a34d30614d8ec60a836c54f Mon Sep 17 00:00:00 2001 From: Laney Pouzet Date: Mon, 2 Nov 2026 10:25:38 -0800 Subject: [PATCH 1/2] fix(channels): quiet automatic unread emphasis in muted DMs Co-authored-by: Codex Signed-off-by: Laney Pouzet --- docs/buzz-help.md | 2 +- docs/unread.md | 4 ++-- src/bundled/channels/ChannelSidebarItem.test.tsx | 6 +++--- src/bundled/channels/UnreadBadge.tsx | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/buzz-help.md b/docs/buzz-help.md index 44b1eeb6e1..035f714be6 100644 --- a/docs/buzz-help.md +++ b/docs/buzz-help.md @@ -72,7 +72,7 @@ the interface unless an available tool actually supports that action. grants access. - **Mute** is available from a channel or DM's sidebar context menu. Once confirmed, a crossed-out bell appears immediately after its name. New messages - do not make muted channel names bold; muted DM names still become bold. + do not make muted channel or DM names bold. Mute suppresses notifications for messages that do not mention you; mentions can still notify you. Unmute restores ordinary unread emphasis and dots. Manual **Mark as unread** can still make the name bold. Muted rows show no unread dots, including thread diff --git a/docs/unread.md b/docs/unread.md index d072e80114..753cd49f65 100644 --- a/docs/unread.md +++ b/docs/unread.md @@ -168,8 +168,8 @@ or local manual intent strengthens the channel label; protected attention alone retains its dot without bolding a caught-up, unmuted channel. Confirmed-muted channels suppress ordinary automatic unread styling and offscreen cues without clearing unread evidence; explicit manual unread can still strengthen the label. -Pending or failed mute changes do not suppress these cues. Muted DMs retain -automatic unread bolding, “N unread” offscreen counts and avatar previews. Muted +Pending or failed mute changes do not suppress these cues. Muted DMs also suppress +automatic unread bolding; “N unread” offscreen counts and avatar previews remain. Muted channel and DM sidebar rows show a crossed-out bell immediately after their names, even with no unread activity. They hide all unread dots, including thread activity dots. Thread activity remains available through the row's activity popover, diff --git a/src/bundled/channels/ChannelSidebarItem.test.tsx b/src/bundled/channels/ChannelSidebarItem.test.tsx index dcf632e4f6..3c2875a2b1 100644 --- a/src/bundled/channels/ChannelSidebarItem.test.tsx +++ b/src/bundled/channels/ChannelSidebarItem.test.tsx @@ -631,9 +631,9 @@ it.each([ act(() => state.unread(2)); expect(row()).toHaveAttribute("data-ordinary"); act(() => state.mute(true)); - expect(row()?.hasAttribute("data-ordinary")).toBe(channelType === "dm"); + expect(row()).not.toHaveAttribute("data-ordinary"); act(() => state.unread(3, 0)); - expect(row()?.hasAttribute("data-ordinary")).toBe(channelType === "dm"); + expect(row()).not.toHaveAttribute("data-ordinary"); expect( view.container.querySelectorAll("[data-channel-unread]"), ).toHaveLength(mutedIndicators); @@ -651,7 +651,7 @@ it.each([ ).toHaveLength(mutedIndicators); act(() => state.mute(true)); act(() => state.unread(4, 1)); - expect(row()?.hasAttribute("data-ordinary")).toBe(channelType === "dm"); + expect(row()).not.toHaveAttribute("data-ordinary"); expect(view.container.querySelector("[data-channel-priority]")).toBeNull(); expect( screen.getByRole("img", { name: /4 observed unread messages/ }), diff --git a/src/bundled/channels/UnreadBadge.tsx b/src/bundled/channels/UnreadBadge.tsx index 6a3e8b9a57..f5b06d9b13 100644 --- a/src/bundled/channels/UnreadBadge.tsx +++ b/src/bundled/channels/UnreadBadge.tsx @@ -20,7 +20,7 @@ export function ordinaryUnread( const count = snapshot.observedCount ?? 0; return ( snapshot.manual !== "none" || - (dm ? count > 0 : !muted && count > (snapshot.attentionCount ?? 0)) + (!muted && (dm ? count > 0 : count > (snapshot.attentionCount ?? 0))) ); } From 49afe73a9d919b23e4ce717c377790d0e4b596e4 Mon Sep 17 00:00:00 2001 From: Laney Pouzet Date: Mon, 2 Nov 2026 10:55:49 -0800 Subject: [PATCH 2/2] test(channels): cover muted DM indicators and Bestie promotion Clarify retained DM attention cues and notification suppression. Co-authored-by: Codex Signed-off-by: Laney Pouzet --- docs/notifications.md | 4 ++-- docs/unread.md | 2 +- src/app/shell/BestieNavigation.test.tsx | 10 ++-------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/notifications.md b/docs/notifications.md index 65dc58e064..feb980163e 100644 --- a/docs/notifications.md +++ b/docs/notifications.md @@ -84,8 +84,8 @@ checks, not that an OS banner was displayed or read. styling and offscreen cues without clearing unread evidence. Muted channel and DM sidebar rows show a crossed-out bell immediately after their names and hide unread dots, including thread dots. Manual unread can still emphasize - the name, and thread activity remains available. Muted DMs retain automatic - unread emphasis, offscreen unread counts and avatar previews. Solo chat labels + the name, and thread activity remains available. Muted DMs also suppress automatic + unread emphasis; offscreen unread counts and avatar previews remain. Solo chat labels retain unread emphasis. Unread thread cues are distinct from participating-thread alerts, which mute suppresses. Unknown or failed preference reads hold non-mention candidates until explicit retry; a confirmed diff --git a/docs/unread.md b/docs/unread.md index 753cd49f65..dcf2bde354 100644 --- a/docs/unread.md +++ b/docs/unread.md @@ -175,7 +175,7 @@ even with no unread activity. They hide all unread dots, including thread activity dots. Thread activity remains available through the row's activity popover, and its unread count remains accessible to assistive technology. Unmute restores the dots from retained unread evidence. The promoted Bestie DM also hides muted -unread dots; its label keeps ordinary DM unread emphasis. +unread dots; its label follows the same mute rule. Solo chat labels strengthen for any observed unread message, including mentions, broadcasts and relevant replies, even when muted, so Solo rows omit the attention dot. Ordinary unread renders no row marker. Unmuted DMs, mentions, broadcasts, and diff --git a/src/app/shell/BestieNavigation.test.tsx b/src/app/shell/BestieNavigation.test.tsx index f2660e9d64..f62c3d86d4 100644 --- a/src/app/shell/BestieNavigation.test.tsx +++ b/src/app/shell/BestieNavigation.test.tsx @@ -422,10 +422,7 @@ it("honors the promoted DM's mute and unread state through reads and Bestie repl within(row()).getByRole("img", { name: /1 observed unread messages/ }), ).toBeInTheDocument(); expect(row().querySelector("[data-channel-priority]")).toBeNull(); - expect(row().querySelector("[data-bestie-unread]")).toHaveAttribute( - "data-bestie-unread", - "true", - ); + expect(row().querySelector("[data-bestie-unread]")).toBeNull(); expect(dmRow()).toBeNull(); await act(async () => { muted = false; @@ -440,10 +437,7 @@ it("honors the promoted DM's mute and unread state through reads and Bestie repl muted = true; await preferences.queries.refresh(); }); - expect(row().querySelector("[data-bestie-unread]")).toHaveAttribute( - "data-bestie-unread", - "true", - ); + expect(row().querySelector("[data-bestie-unread]")).toBeNull(); expect(row().querySelector("[data-channel-activity]")).toBeNull(); expect(row()).toHaveAccessibleName(/1 unread thread/); expect(dmRow()).toBeNull();