Add bolder coloring for mentions in rollups and always use bold on DMs

This commit is contained in:
Jack Kingsman
2026-03-09 11:57:30 -07:00
parent 811c7e7349
commit 463a0c9084
3 changed files with 59 additions and 11 deletions

View File

@@ -138,11 +138,11 @@ export function ChatHeader({
{conversation.type === 'channel' ? conversation.id.toLowerCase() : conversation.id}
</span>
)}
{conversation.type === 'channel' && activeChannel?.flood_scope_override && (
<span className="basis-full sm:basis-auto text-[11px] text-amber-700 dark:text-amber-300 truncate">
Regional override active: {activeChannel.flood_scope_override}
</span>
)}
{conversation.type === 'channel' && activeChannel?.flood_scope_override && (
<span className="basis-full sm:basis-auto text-[11px] text-amber-700 dark:text-amber-300 truncate">
Regional override active: {activeChannel.flood_scope_override}
</span>
)}
{conversation.type === 'contact' &&
(() => {
const contact = contacts.find((c) => c.public_key === conversation.id);

View File

@@ -485,6 +485,8 @@ export function Sidebar({
const getSectionUnreadCount = (rows: ConversationRow[]): number =>
rows.reduce((total, row) => total + row.unreadCount, 0);
const sectionHasMention = (rows: ConversationRow[]): boolean => rows.some((row) => row.isMention);
const favoriteRows = favoriteItems.map((item) =>
item.type === 'channel'
? buildChannelRow(item.channel, 'fav-chan')
@@ -498,6 +500,8 @@ export function Sidebar({
const channelsUnreadCount = getSectionUnreadCount(channelRows);
const contactsUnreadCount = getSectionUnreadCount(contactRows);
const repeatersUnreadCount = getSectionUnreadCount(repeaterRows);
const favoritesHasMention = sectionHasMention(favoriteRows);
const channelsHasMention = sectionHasMention(channelRows);
const toolRows = !query
? [
renderSidebarActionRow({
@@ -575,7 +579,8 @@ export function Sidebar({
collapsed: boolean,
onToggle: () => void,
showSortToggle = false,
unreadCount = 0
unreadCount = 0,
highlightUnread = false
) => {
const effectiveCollapsed = isSearching ? false : collapsed;
@@ -611,7 +616,12 @@ export function Sidebar({
)}
{unreadCount > 0 && (
<span
className="text-[10px] font-medium px-1.5 py-0.5 rounded-full bg-secondary text-muted-foreground"
className={cn(
'text-[10px] font-medium px-1.5 py-0.5 rounded-full',
highlightUnread
? 'bg-badge-mention text-badge-mention-foreground'
: 'bg-secondary text-muted-foreground'
)}
aria-label={`${unreadCount} unread`}
>
{unreadCount}
@@ -701,7 +711,8 @@ export function Sidebar({
favoritesCollapsed,
() => setFavoritesCollapsed((prev) => !prev),
false,
favoritesUnreadCount
favoritesUnreadCount,
favoritesHasMention
)}
{(isSearching || !favoritesCollapsed) &&
favoriteRows.map((row) => renderConversationRow(row))}
@@ -716,7 +727,8 @@ export function Sidebar({
channelsCollapsed,
() => setChannelsCollapsed((prev) => !prev),
true,
channelsUnreadCount
channelsUnreadCount,
channelsHasMention
)}
{(isSearching || !channelsCollapsed) &&
channelRows.map((row) => renderConversationRow(row))}
@@ -731,7 +743,8 @@ export function Sidebar({
contactsCollapsed,
() => setContactsCollapsed((prev) => !prev),
true,
contactsUnreadCount
contactsUnreadCount,
contactsUnreadCount > 0
)}
{(isSearching || !contactsCollapsed) &&
contactRows.map((row) => renderConversationRow(row))}

View File

@@ -37,6 +37,7 @@ function makeContact(public_key: string, name: string, type = 1): Contact {
function renderSidebar(overrides?: {
unreadCounts?: Record<string, number>;
mentions?: Record<string, boolean>;
favorites?: Favorite[];
lastMessageTimes?: ConversationTimes;
channels?: Channel[];
@@ -67,7 +68,7 @@ function renderSidebar(overrides?: {
onNewMessage={vi.fn()}
lastMessageTimes={overrides?.lastMessageTimes ?? {}}
unreadCounts={unreadCounts}
mentions={{}}
mentions={overrides?.mentions ?? {}}
showCracker={false}
crackerRunning={false}
onToggleCracker={vi.fn()}
@@ -102,6 +103,40 @@ describe('Sidebar section summaries', () => {
expect(within(getSectionHeaderContainer('Repeaters')).getByText('4')).toBeInTheDocument();
});
it('turns favorites and channels rollups red when they contain a mention', () => {
renderSidebar({
mentions: {
[getStateKey('channel', 'BB'.repeat(16))]: true,
[getStateKey('channel', 'CC'.repeat(16))]: true,
},
});
expect(within(getSectionHeaderContainer('Favorites')).getByText('2')).toHaveClass(
'bg-badge-mention',
'text-badge-mention-foreground'
);
expect(within(getSectionHeaderContainer('Channels')).getByText('1')).toHaveClass(
'bg-badge-mention',
'text-badge-mention-foreground'
);
});
it('keeps contact row badges normal while the contacts rollup is always red', () => {
const { aliceName } = renderSidebar();
expect(within(getSectionHeaderContainer('Contacts')).getByText('3')).toHaveClass(
'bg-badge-mention',
'text-badge-mention-foreground'
);
const aliceRow = screen.getByText(aliceName).closest('div');
if (!aliceRow) throw new Error('Missing Alice row');
expect(within(aliceRow).getByText('3')).toHaveClass(
'bg-badge-unread/90',
'text-badge-unread-foreground'
);
});
it('expands collapsed sections during search and restores collapse state after clearing search', async () => {
const { opsChannel, aliceName } = renderSidebar();