diff --git a/src/app/components/unread-badge/UnreadBadge.tsx b/src/app/components/unread-badge/UnreadBadge.tsx index f8bfefa3c0..a80763da12 100644 --- a/src/app/components/unread-badge/UnreadBadge.tsx +++ b/src/app/components/unread-badge/UnreadBadge.tsx @@ -1,6 +1,8 @@ import React, { CSSProperties, ReactNode } from 'react'; import { Box, Badge, toRem, Text } from 'folds'; import { millify } from '../../plugins/millify'; +import { useSetting } from '../../state/hooks/settings'; +import { settingsAtom } from '../../state/settings'; type UnreadBadgeProps = { highlight?: boolean; @@ -18,6 +20,11 @@ export function UnreadBadgeCenter({ children }: { children: ReactNode }) { } export function UnreadBadge({ highlight, count }: UnreadBadgeProps) { + const [hideUnreadActivityDots] = useSetting(settingsAtom, 'hideUnreadActivityDots'); + + // Suppress the dot-only indicator (no count, not a highlight) when hidden by user. + if (hideUnreadActivityDots && count <= 0 && !highlight) return null; + return ( { window.Notification.requestPermission(); @@ -145,6 +149,20 @@ export function SystemNotification() { after={} /> + + + } + /> + { const items = Array.from(directs).sort(factoryRoomIdByActivity(mx)); if (closedCategories.has(DEFAULT_CATEGORY_ID)) { - return items.filter((rId) => roomToUnread.has(rId) || rId === selectedRoomId); + return items.filter((rId) => { + const u = roomToUnread.get(rId); + const isUnread = hideActivityDots + ? u !== undefined && (u.total > 0 || u.highlight > 0) + : roomToUnread.has(rId); + return isUnread || rId === selectedRoomId; + }); } return items; - }, [mx, directs, closedCategories, roomToUnread, selectedRoomId]); + }, [mx, directs, closedCategories, roomToUnread, selectedRoomId, hideActivityDots]); const virtualizer = useVirtualizer({ count: sortedDirects.length, diff --git a/src/app/pages/client/home/Home.tsx b/src/app/pages/client/home/Home.tsx index d87db963df..0b7c78d3cc 100644 --- a/src/app/pages/client/home/Home.tsx +++ b/src/app/pages/client/home/Home.tsx @@ -208,6 +208,7 @@ export function Home() { const searchSelected = useHomeSearchSelected(); const noRoomToDisplay = rooms.length === 0; const [closedCategories, setClosedCategories] = useAtom(useClosedNavCategoriesAtom()); + const [hideActivityDots] = useSetting(settingsAtom, 'hideUnreadActivityDots'); const sortedRooms = useMemo(() => { const items = Array.from(rooms).sort( @@ -216,10 +217,16 @@ export function Home() { : factoryRoomIdByAtoZ(mx) ); if (closedCategories.has(DEFAULT_CATEGORY_ID)) { - return items.filter((rId) => roomToUnread.has(rId) || rId === selectedRoomId); + return items.filter((rId) => { + const u = roomToUnread.get(rId); + const isUnread = hideActivityDots + ? u !== undefined && (u.total > 0 || u.highlight > 0) + : roomToUnread.has(rId); + return isUnread || rId === selectedRoomId; + }); } return items; - }, [mx, rooms, closedCategories, roomToUnread, selectedRoomId]); + }, [mx, rooms, closedCategories, roomToUnread, selectedRoomId, hideActivityDots]); const virtualizer = useVirtualizer({ count: sortedRooms.length, diff --git a/src/app/pages/client/space/Space.tsx b/src/app/pages/client/space/Space.tsx index 2a7c619939..c491a644fe 100644 --- a/src/app/pages/client/space/Space.tsx +++ b/src/app/pages/client/space/Space.tsx @@ -383,6 +383,7 @@ export function Space() { const scrollRef = useRef(null); const mDirects = useAtomValue(mDirectAtom); const roomToUnread = useAtomValue(roomToUnreadAtom); + const [hideActivityDots] = useSetting(settingsAtom, 'hideUnreadActivityDots'); const allRooms = useAtomValue(allRoomsAtom); const allJoinedRooms = useMemo(() => new Set(allRooms), [allRooms]); const notificationPreferences = useRoomsNotificationPreferencesContext(); @@ -413,11 +414,14 @@ export function Space() { if (!closedCategories.has(makeNavCategoryId(space.roomId, parentId))) { return false; } - const showRoomAnyway = - roomToUnread.has(roomId) || roomId === selectedRoomId || callEmbed?.roomId === roomId; + const u = roomToUnread.get(roomId); + const isUnread = hideActivityDots + ? u !== undefined && (u.total > 0 || u.highlight > 0) + : roomToUnread.has(roomId); + const showRoomAnyway = isUnread || roomId === selectedRoomId || callEmbed?.roomId === roomId; return !showRoomAnyway; }, - [space.roomId, closedCategories, roomToUnread, selectedRoomId, callEmbed] + [space.roomId, closedCategories, roomToUnread, selectedRoomId, callEmbed, hideActivityDots] ), useCallback( (sId) => closedCategories.has(makeNavCategoryId(space.roomId, sId)), diff --git a/src/app/state/settings.ts b/src/app/state/settings.ts index 9fbad4ff0f..03847201f0 100644 --- a/src/app/state/settings.ts +++ b/src/app/state/settings.ts @@ -42,6 +42,7 @@ export interface Settings { showNotifications: boolean; isNotificationSounds: boolean; + hideUnreadActivityDots: boolean; hour24Clock: boolean; dateFormatString: string; @@ -76,6 +77,7 @@ const defaultSettings: Settings = { showNotifications: true, isNotificationSounds: true, + hideUnreadActivityDots: false, hour24Clock: false, dateFormatString: 'D MMM YYYY',