diff --git a/desktop/src/features/sidebar/ui/SidebarSection.tsx b/desktop/src/features/sidebar/ui/SidebarSection.tsx index 0c99eaf16d1..c4c459aeffb 100644 --- a/desktop/src/features/sidebar/ui/SidebarSection.tsx +++ b/desktop/src/features/sidebar/ui/SidebarSection.tsx @@ -294,6 +294,14 @@ export function ChannelMenuButton({ (hasSidebarUnreadProjections ? unreadThreadChannelIds.has(channel.id) : hasUnread); + const showsUnreadCount = + !isActive && channel.channelType !== "dm" && unreadCount > 0; + const showsEphemeralBadge = + Boolean(ephemeralDisplay) && + !activeWorking && + !isMuted && + !showsUnreadCount && + !hasThreadUnread; const inactiveContentOpacity = cn( !isActive && !hasTopLevelUnread && !isMuted && "opacity-80", !isActive && @@ -334,7 +342,7 @@ export function ChannelMenuButton({ > {resolvedLabel} - {ephemeralDisplay ? ( + {showsEphemeralBadge && ephemeralDisplay ? ( ) : null} - {!isActive && channel.channelType !== "dm" && unreadCount > 0 ? ( + {showsUnreadCount ? ( { @@ -1581,12 +1583,78 @@ test("create ephemeral stream shows sidebar and header affordances", async ({ /Ephemeral channel\. Cleans up in 14 days\./, ); + const channelRow = page.getByTestId(`channel-${channelName}`); + const channelId = await channelRow.getAttribute("data-channel-id"); + if (!channelId) { + throw new Error("Created ephemeral channel is missing its channel id."); + } + + await waitForMockLiveSubscription(page, channelName); + await page.getByTestId("channel-general").click(); + await page.evaluate( + ({ agentPubkey, channelId: activeChannelId }) => { + (window as MockFeedWindow).__BUZZ_E2E_SEED_ACTIVE_TURNS__?.({ + agentPubkey, + channelId: activeChannelId, + turnId: "ephemeral-sidebar-status", + }); + }, + { agentPubkey: OWNED_RELAY_AGENT_PUBKEY, channelId }, + ); + + await expect( + page.getByTestId(`channel-working-${channelName}`), + ).toBeVisible(); + await expect( + page.getByTestId(`channel-ephemeral-${channelName}`), + ).toHaveCount(0); + + await page.evaluate( + ({ agentPubkey, channelId: activeChannelId }) => { + (window as MockFeedWindow).__BUZZ_E2E_SEED_ACTIVE_TURNS__?.({ + agentPubkey, + channelId: activeChannelId, + turnId: "ephemeral-sidebar-status", + kind: "turn_completed", + }); + }, + { agentPubkey: OWNED_RELAY_AGENT_PUBKEY, channelId }, + ); + await expect( + page.getByTestId(`channel-ephemeral-${channelName}`), + ).toBeVisible(); + await page .getByRole("button", { name: "Toggle Sidebar", exact: true }) .click(); await expect( page.getByTestId(`channel-ephemeral-${channelName}`), ).toBeVisible(); + await page + .getByRole("button", { name: "Toggle Sidebar", exact: true }) + .click(); + + await page.evaluate( + ({ channelName: targetChannelName, mentionPubkey, senderPubkey }) => { + (window as MockFeedWindow).__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({ + channelName: targetChannelName, + content: "Unread mention in an ephemeral channel", + kind: 40002, + mentionPubkeys: [mentionPubkey], + pubkey: senderPubkey, + }); + }, + { + channelName, + mentionPubkey: MOCK_IDENTITY_PUBKEY, + senderPubkey: TEST_IDENTITIES.alice.pubkey, + }, + ); + + await expect(page.getByTestId(`channel-unread-${channelName}`)).toBeVisible(); + await expect( + page.getByTestId(`channel-ephemeral-${channelName}`), + ).toHaveCount(0); }); test("ephemeral countdown refreshes when switching channels after a clock jump", async ({