From f20dd652dfc6b2e62e73532cf0774bb73570c1e4 Mon Sep 17 00:00:00 2001 From: Shea Duma Date: Sun, 17 May 2026 06:38:11 +0300 Subject: [PATCH 1/6] added settings for hiding rooms --- .../common-settings/appearance/Appearance.tsx | 44 ++++++++++++++++--- .../features/room-settings/RoomSettings.tsx | 10 +++++ .../features/settings/cosmetics/Themes.tsx | 12 +++++ src/app/state/roomSettings.ts | 1 + src/app/state/settings.ts | 7 +++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/app/features/common-settings/appearance/Appearance.tsx b/src/app/features/common-settings/appearance/Appearance.tsx index b7bc803e0..ee4715720 100644 --- a/src/app/features/common-settings/appearance/Appearance.tsx +++ b/src/app/features/common-settings/appearance/Appearance.tsx @@ -12,6 +12,7 @@ import { MenuItem, PopOut, type RectCords, + Switch, } from 'folds'; import { Page, PageContent, PageHeader } from '$components/page'; import { SequenceCard } from '$components/sequence-card'; @@ -98,11 +99,35 @@ export function SelectShowPerRoomRoomIcon({ roomId }: { roomId: string }) { ); } +export function SelectHideRoom({ roomId, isSpace }: { roomId: string; isSpace?: boolean }) { + const [hideRoom, setHideRoom] = useSetting( + settingsAtom, + isSpace ? 'hiddenSpaces' : 'hiddenRooms' + ); + const isHidden = hideRoom.includes(roomId); + + function handleHideRoom() { + const newHideRoomList = !isHidden + ? [...hideRoom, roomId] + : hideRoom.filter((roomItem) => roomItem !== roomId); + setHideRoom(newHideRoomList); + } + + return ( + } + /> + ); +} + type AppearanceProps = { requestClose: () => void; }; export function Appearance({ requestClose }: AppearanceProps) { const room = useRoom(); + const isSpace = room.isSpaceRoom(); return ( @@ -126,16 +151,25 @@ export function Appearance({ requestClose }: AppearanceProps) { Visual Tweaks + {isSpace && ( + + } + /> + + )} - } - /> + diff --git a/src/app/features/room-settings/RoomSettings.tsx b/src/app/features/room-settings/RoomSettings.tsx index f960460fd..228e757b3 100644 --- a/src/app/features/room-settings/RoomSettings.tsx +++ b/src/app/features/room-settings/RoomSettings.tsx @@ -23,6 +23,7 @@ import { useSetting } from '$state/hooks/settings'; import { Permissions } from './permissions'; import { General } from './general'; import { RoomAbbreviations } from './abbreviations/RoomAbbreviations'; +import { Appearance } from '$features/common-settings/appearance/Appearance'; type RoomSettingsMenuItem = { page: RoomSettingsPage; @@ -70,6 +71,12 @@ const useRoomSettingsMenuItems = (): RoomSettingsMenuItem[] => name: 'Developer Tools', icon: Icons.Terminal, }, + { + page: RoomSettingsPage.AppearancePage, + name: 'Appearance', + icon: Icons.Alphabet, + activeIcon: Icons.AlphabetUnderline, + }, ], [] ); @@ -209,6 +216,9 @@ export function RoomSettings({ initialPage, requestClose }: RoomSettingsProps) { {activePage === RoomSettingsPage.AbbreviationsPage && ( )} + {activePage === RoomSettingsPage.AppearancePage && ( + + )} ); diff --git a/src/app/features/settings/cosmetics/Themes.tsx b/src/app/features/settings/cosmetics/Themes.tsx index fa93a3890..1e9d41f60 100644 --- a/src/app/features/settings/cosmetics/Themes.tsx +++ b/src/app/features/settings/cosmetics/Themes.tsx @@ -787,6 +787,7 @@ export function Appearance({ const [twitterEmoji, setTwitterEmoji] = useSetting(settingsAtom, 'twitterEmoji'); const [customDMCards, setCustomDMCards] = useSetting(settingsAtom, 'customDMCards'); const [showEasterEggs, setShowEasterEggs] = useSetting(settingsAtom, 'showEasterEggs'); + const [isHidingRooms, setIsHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); const [themeBrowserOpen, setThemeBrowserOpen] = useState(false); const [closeFoldersByDefault, setCloseFoldersByDefault] = useSetting( settingsAtom, @@ -855,6 +856,17 @@ export function Appearance({ /> + + + } + /> + + } /> diff --git a/src/app/state/roomSettings.ts b/src/app/state/roomSettings.ts index 64bc0ef99..2b93307b9 100644 --- a/src/app/state/roomSettings.ts +++ b/src/app/state/roomSettings.ts @@ -9,6 +9,7 @@ export enum RoomSettingsPage { // Sable pages CosmeticsPage, AbbreviationsPage, + AppearancePage, } export type RoomSettingsState = { diff --git a/src/app/state/settings.ts b/src/app/state/settings.ts index aab58f600..e0e18e945 100644 --- a/src/app/state/settings.ts +++ b/src/app/state/settings.ts @@ -175,6 +175,9 @@ export interface Settings { threadRootHeight: number; vcmsgSidebarWidth: number; widgetSidebarWidth: number; + hiddenSpaces: string[]; + hiddenRooms: string[]; + isHidingRooms: boolean; // furry stuff renderAnimals: boolean; @@ -308,6 +311,10 @@ export const defaultSettings: Settings = { threadRootHeight: 220, vcmsgSidebarWidth: 399, widgetSidebarWidth: 420, + hiddenSpaces: [], + hiddenRooms: [], + isHidingRooms: false, + // furry stuff renderAnimals: true, From 1537c3621748f792d29be4970b203e1fe215481c Mon Sep 17 00:00:00 2001 From: Shea Duma Date: Sun, 17 May 2026 07:19:43 +0300 Subject: [PATCH 2/6] filter rooms --- src/app/pages/client/space/Space.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/pages/client/space/Space.tsx b/src/app/pages/client/space/Space.tsx index e30634310..4c977c654 100644 --- a/src/app/pages/client/space/Space.tsx +++ b/src/app/pages/client/space/Space.tsx @@ -518,6 +518,9 @@ export function Space() { const allJoinedRooms = useMemo(() => new Set(allRooms), [allRooms]); const notificationPreferences = useRoomsNotificationPreferencesContext(); + const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms'); + const [idHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const [roomSidebarWidth, setRoomSidebarWidth] = useSetting(settingsAtom, 'roomSidebarWidth'); const [curWidth, setCurWidth] = useState(roomSidebarWidth); useEffect(() => { @@ -780,7 +783,7 @@ export function Space() { ); }; - const hierarchy = useSpaceJoinedHierarchy( + const baseHierarchy = useSpaceJoinedHierarchy( space.roomId, getRoom, useCallback( @@ -814,6 +817,11 @@ export function Space() { [getInClosedCategories, space.roomId] ) ); + const hierarchy = idHidingRooms + ? baseHierarchy.filter( + (item) => !hiddenRooms.includes(item.roomId) || item.roomId === selectedRoomId + ) + : baseHierarchy; const virtualizer = useVirtualizer({ count: hierarchy.length, From f486bacf641d019f329a5e3a4298fdced7eb612c Mon Sep 17 00:00:00 2001 From: Shea Duma Date: Sun, 17 May 2026 19:22:23 +0300 Subject: [PATCH 3/6] filter spaces --- src/app/pages/client/sidebar/SpaceTabs.tsx | 9 +++++++++ src/app/pages/client/space/Space.tsx | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/app/pages/client/sidebar/SpaceTabs.tsx b/src/app/pages/client/sidebar/SpaceTabs.tsx index e9e2a6e5a..7ab00e859 100644 --- a/src/app/pages/client/sidebar/SpaceTabs.tsx +++ b/src/app/pages/client/sidebar/SpaceTabs.tsx @@ -660,6 +660,7 @@ type ClosedSpaceFolderProps = { onDragging: (dragItem?: SidebarDraggable) => void; disabled?: boolean; onFolderContextMenu?: MouseEventHandler; + hiddenSpaces?: string[]; }; function ClosedSpaceFolder({ folder, @@ -668,6 +669,7 @@ function ClosedSpaceFolder({ onDragging, disabled, onFolderContextMenu, + hiddenSpaces, }: Readonly) { const mx = useMatrixClient(); const useAuthentication = useMediaAuthentication(); @@ -701,6 +703,7 @@ function ClosedSpaceFolder({ onContextMenu={onFolderContextMenu} > {folder.content.map((sId) => { + if (hiddenSpaces?.includes(sId)) return null; const space = mx.getRoom(sId); if (!space) return null; @@ -753,6 +756,9 @@ export function SpaceTabs({ scrollRef }: Readonly) { anchor: RectCords; }>(); const [renameTargetFolder, setRenameTargetFolder] = useState(); + const [baseHiddenSpaces] = useSetting(settingsAtom, 'hiddenSpaces'); + const [isHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const hiddenSpaces = isHidingRooms ? baseHiddenSpaces : undefined; const handleFolderContextMenu = useCallback( (folder: ISidebarFolder): MouseEventHandler => @@ -1009,6 +1015,7 @@ export function SpaceTabs({ scrollRef }: Readonly) { onFolderContextMenu={handleFolderContextMenu(item)} > {item.content.map((sId) => { + if (hiddenSpaces?.includes(sId)) return null; const space = mx.getRoom(sId); if (!space) return null; return ( @@ -1043,9 +1050,11 @@ export function SpaceTabs({ scrollRef }: Readonly) { disabled={ typeof draggingItem === 'object' ? draggingItem.folder.id === item.id : false } + hiddenSpaces={hiddenSpaces} /> ); } + if (hiddenSpaces?.includes(item)) return null; const space = mx.getRoom(item); if (!space) return null; diff --git a/src/app/pages/client/space/Space.tsx b/src/app/pages/client/space/Space.tsx index 4c977c654..93c94d054 100644 --- a/src/app/pages/client/space/Space.tsx +++ b/src/app/pages/client/space/Space.tsx @@ -519,7 +519,7 @@ export function Space() { const notificationPreferences = useRoomsNotificationPreferencesContext(); const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms'); - const [idHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const [isHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); const [roomSidebarWidth, setRoomSidebarWidth] = useSetting(settingsAtom, 'roomSidebarWidth'); const [curWidth, setCurWidth] = useState(roomSidebarWidth); @@ -817,7 +817,7 @@ export function Space() { [getInClosedCategories, space.roomId] ) ); - const hierarchy = idHidingRooms + const hierarchy = isHidingRooms ? baseHierarchy.filter( (item) => !hiddenRooms.includes(item.roomId) || item.roomId === selectedRoomId ) From 4d07d6c4036f7996811eaac3d880693694a88b4b Mon Sep 17 00:00:00 2001 From: Shea Duma Date: Mon, 18 May 2026 07:34:55 +0300 Subject: [PATCH 4/6] add options and shortcut --- .../components/GlobalKeyboardShortcuts.tsx | 15 +++++++++++ .../features/settings/cosmetics/Themes.tsx | 26 ++++++++++++++++++- .../keyboard-shortcuts/KeyboardShortcuts.tsx | 4 +++ src/app/features/settings/settingsLink.ts | 2 ++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/app/components/GlobalKeyboardShortcuts.tsx b/src/app/components/GlobalKeyboardShortcuts.tsx index 7246219a4..3f4e12559 100644 --- a/src/app/components/GlobalKeyboardShortcuts.tsx +++ b/src/app/components/GlobalKeyboardShortcuts.tsx @@ -22,6 +22,8 @@ import { getCanonicalAliasOrRoomId } from '$utils/matrix'; import { announce } from '$utils/announce'; import { roomIdToReplyDraftAtomFamily } from '$state/room/roomInputDrafts'; import type { Room } from '$types/matrix-sdk'; +import { useSetting } from '$state/hooks/settings'; +import { settingsAtom } from '$state/settings'; export function GlobalKeyboardShortcuts() { const navigate = useNavigate(); @@ -31,6 +33,7 @@ export function GlobalKeyboardShortcuts() { const mDirects = useAtomValue(mDirectAtom); const roomToUnread = useAtomValue(roomToUnreadAtom); const unreadIndexRef = useRef(0); + const [isHidingRooms, setIsHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); // Derive the current room ID from the URL so we know which room is active. const roomMatch = @@ -151,9 +154,21 @@ export function GlobalKeyboardShortcuts() { [currentRoom, replyDraft, setReplyDraft] ); + /** Alt+Shift+H: Toggle Hide Rooms. */ + const handleHideRoomsKeyDown = useCallback( + (evt: KeyboardEvent) => { + if (!isKeyHotkey('alt+shift+h', evt)) return; + evt.preventDefault(); + unreadIndexRef.current = 0; + setIsHidingRooms(!isHidingRooms); + }, + [setIsHidingRooms, isHidingRooms] + ); + useKeyDown(window, handleNextUnreadKeyDown); useKeyDown(window, handleUnreadNavKeyDown); useKeyDown(window, handleReplyKeyDown); + useKeyDown(window, handleHideRoomsKeyDown); return null; } diff --git a/src/app/features/settings/cosmetics/Themes.tsx b/src/app/features/settings/cosmetics/Themes.tsx index 1e9d41f60..606dc92cd 100644 --- a/src/app/features/settings/cosmetics/Themes.tsx +++ b/src/app/features/settings/cosmetics/Themes.tsx @@ -6,6 +6,7 @@ import { Chip, config, Icon, + IconButton, Icons, Input, Menu, @@ -788,6 +789,8 @@ export function Appearance({ const [customDMCards, setCustomDMCards] = useSetting(settingsAtom, 'customDMCards'); const [showEasterEggs, setShowEasterEggs] = useSetting(settingsAtom, 'showEasterEggs'); const [isHidingRooms, setIsHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const [hiddenSpaces, setHiddenSpaces] = useSetting(settingsAtom, 'hiddenSpaces'); + const [hiddenRooms, setHiddenRooms] = useSetting(settingsAtom, 'hiddenRooms'); const [themeBrowserOpen, setThemeBrowserOpen] = useState(false); const [closeFoldersByDefault, setCloseFoldersByDefault] = useSetting( settingsAtom, @@ -859,7 +862,7 @@ export function Appearance({ @@ -867,6 +870,27 @@ export function Appearance({ /> + + { + setHiddenRooms([]); + setHiddenSpaces([]); + }} + radii="300" + disabled={hiddenRooms.length === 0 && hiddenSpaces.length === 0} + > + + + } + /> + + } /> diff --git a/src/app/features/settings/keyboard-shortcuts/KeyboardShortcuts.tsx b/src/app/features/settings/keyboard-shortcuts/KeyboardShortcuts.tsx index a0b52da48..aac71a6cd 100644 --- a/src/app/features/settings/keyboard-shortcuts/KeyboardShortcuts.tsx +++ b/src/app/features/settings/keyboard-shortcuts/KeyboardShortcuts.tsx @@ -46,6 +46,10 @@ const SHORTCUT_CATEGORIES: ShortcutCategory[] = [ { keys: 'Ctrl+U / ⌘+U', description: 'Underline' }, ], }, + { + name: 'Other', + shortcuts: [{ keys: 'Alt+Shift+H', description: 'Toggle Hiding Rooms' }], + }, ]; function ShortcutRow({ keys, description }: ShortcutEntry) { diff --git a/src/app/features/settings/settingsLink.ts b/src/app/features/settings/settingsLink.ts index 6104186ed..38f31f797 100644 --- a/src/app/features/settings/settingsLink.ts +++ b/src/app/features/settings/settingsLink.ts @@ -116,6 +116,8 @@ const settingsLinkFocusIdsBySection: Record Date: Mon, 18 May 2026 14:46:45 +0300 Subject: [PATCH 5/6] add hiding rooms visually --- .changeset/add_basic_hiding_rooms.md | 5 ++++ .changeset/fix-various-banner-fixes.md | 2 +- .../components/GlobalKeyboardShortcuts.tsx | 28 ++++++++++++++++--- src/app/components/user-profile/UserChips.tsx | 25 ++++++++++++++--- src/app/pages/client/direct/Direct.tsx | 18 ++++++++++-- src/app/pages/client/home/Home.tsx | 9 ++++-- src/app/pages/client/sidebar/SpaceTabs.tsx | 27 ++++++++++++------ 7 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 .changeset/add_basic_hiding_rooms.md diff --git a/.changeset/add_basic_hiding_rooms.md b/.changeset/add_basic_hiding_rooms.md new file mode 100644 index 000000000..6e20d1371 --- /dev/null +++ b/.changeset/add_basic_hiding_rooms.md @@ -0,0 +1,5 @@ +--- +default: minor +--- + +Add per Space setting for when to show room icons in sidebar diff --git a/.changeset/fix-various-banner-fixes.md b/.changeset/fix-various-banner-fixes.md index 0c012d451..e75ee37fb 100644 --- a/.changeset/fix-various-banner-fixes.md +++ b/.changeset/fix-various-banner-fixes.md @@ -1,5 +1,5 @@ --- -default: fix +default: patch --- Various small banner changes diff --git a/src/app/components/GlobalKeyboardShortcuts.tsx b/src/app/components/GlobalKeyboardShortcuts.tsx index 3f4e12559..675efd303 100644 --- a/src/app/components/GlobalKeyboardShortcuts.tsx +++ b/src/app/components/GlobalKeyboardShortcuts.tsx @@ -24,6 +24,8 @@ import { roomIdToReplyDraftAtomFamily } from '$state/room/roomInputDrafts'; import type { Room } from '$types/matrix-sdk'; import { useSetting } from '$state/hooks/settings'; import { settingsAtom } from '$state/settings'; +import { allRoomsAtom } from '$state/room-list/roomList'; +import { useSelectedRoom } from '$hooks/router/useSelectedRoom'; export function GlobalKeyboardShortcuts() { const navigate = useNavigate(); @@ -33,7 +35,16 @@ export function GlobalKeyboardShortcuts() { const mDirects = useAtomValue(mDirectAtom); const roomToUnread = useAtomValue(roomToUnreadAtom); const unreadIndexRef = useRef(0); + + const allRooms = useAtomValue(allRoomsAtom); const [isHidingRooms, setIsHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms'); + const [hiddenSpaces] = useSetting(settingsAtom, 'hiddenSpaces'); + const selectedRoomId = useSelectedRoom(); + + const filteredRooms = allRooms.filter( + (item) => !hiddenRooms.includes(item) && !hiddenSpaces.includes(item) + ); // Derive the current room ID from the URL so we know which room is active. const roomMatch = @@ -57,7 +68,7 @@ export function GlobalKeyboardShortcuts() { /** Navigate to a room by ID and announce it to screen readers. */ const navigateToRoom = useCallback( - (roomId: string, remaining: number) => { + (roomId: string, remaining?: number) => { const roomIdOrAliasToNav = getCanonicalAliasOrRoomId(mx, roomId); const isDirect = mDirects.has(roomId); if (isDirect) { @@ -78,7 +89,9 @@ export function GlobalKeyboardShortcuts() { } const roomName = mx.getRoom(roomId)?.name ?? 'Room'; const roomType = isDirect ? 'Direct Message' : 'Group Room'; - announce(`${roomName}, ${roomType}. ${remaining} room${remaining === 1 ? '' : 's'} unread.`); + announce( + `${roomName}, ${roomType}.${remaining && `${remaining} room${remaining === 1 ? '' : 's'} unread.`}` + ); }, [mx, mDirects, roomToParents, navigate] ); @@ -159,10 +172,17 @@ export function GlobalKeyboardShortcuts() { (evt: KeyboardEvent) => { if (!isKeyHotkey('alt+shift+h', evt)) return; evt.preventDefault(); - unreadIndexRef.current = 0; + announce(`${isHidingRooms ? 'Disabling' : 'Enabling'} hiding rooms.`); setIsHidingRooms(!isHidingRooms); + if ( + selectedRoomId && + filteredRooms.length > 0 && + filteredRooms[0] && + !filteredRooms.includes(selectedRoomId) + ) + navigateToRoom(filteredRooms[0]); }, - [setIsHidingRooms, isHidingRooms] + [setIsHidingRooms, isHidingRooms, navigateToRoom, filteredRooms, selectedRoomId] ); useKeyDown(window, handleNextUnreadKeyDown); diff --git a/src/app/components/user-profile/UserChips.tsx b/src/app/components/user-profile/UserChips.tsx index 2adeb5fbe..171d027df 100644 --- a/src/app/components/user-profile/UserChips.tsx +++ b/src/app/components/user-profile/UserChips.tsx @@ -50,6 +50,8 @@ import { SettingTile } from '$components/setting-tile'; import { RoomAvatar, RoomIcon } from '$components/room-avatar'; import { heroMenuItemStyle } from './heroMenuItemStyle'; import * as css from './styles.css'; +import { useSetting } from '$state/hooks/settings'; +import { settingsAtom } from '$state/settings'; export function ServerChip({ server, @@ -368,6 +370,21 @@ export function MutualRoomsChip({ const [cords, setCords] = useState(); + const [isHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms'); + const [hiddenSpaces] = useSetting(settingsAtom, 'hiddenSpaces'); + const baseMutualRooms = useMemo( + () => + (mutualRoomsState.status === AsyncStatus.Success && + (!isHidingRooms + ? mutualRoomsState.data + : mutualRoomsState.data.filter( + (item) => !hiddenRooms.includes(item) && !hiddenSpaces.includes(item) + ))) || + [], + [isHidingRooms, hiddenRooms, hiddenSpaces, mutualRoomsState] + ); + const open: MouseEventHandler = (evt) => { setCords(evt.currentTarget.getBoundingClientRect()); }; @@ -382,7 +399,7 @@ export function MutualRoomsChip({ }; if (mutualRoomsState.status === AsyncStatus.Success) { - const mutualRooms = mutualRoomsState.data + const mutualRooms = baseMutualRooms .toSorted(factoryRoomIdByAtoZ(mx)) .map(getRoom) .filter((room) => !!room); @@ -399,7 +416,7 @@ export function MutualRoomsChip({ }); } return data; - }, [mutualRoomsState, getRoom, directs, mx]); + }, [mutualRoomsState, getRoom, directs, mx, baseMutualRooms]); if ( userId === mx.getSafeUserId() || @@ -542,7 +559,7 @@ export function MutualRoomsChip({ radii="Pill" before={mutualRoomsState.status === AsyncStatus.Loading && } disabled={ - mutualRoomsState.status !== AsyncStatus.Success || mutualRoomsState.data.length === 0 + mutualRoomsState.status !== AsyncStatus.Success || baseMutualRooms.length === 0 } onClick={open} aria-pressed={!!cords} @@ -554,7 +571,7 @@ export function MutualRoomsChip({ > {mutualRoomsState.status === AsyncStatus.Success && - `${mutualRoomsState.data.length} Mutual Rooms`} + `${baseMutualRooms.length} Mutual Rooms`} {mutualRoomsState.status === AsyncStatus.Loading && 'Mutual Rooms'} diff --git a/src/app/pages/client/direct/Direct.tsx b/src/app/pages/client/direct/Direct.tsx index 81dc6181d..fec92596b 100644 --- a/src/app/pages/client/direct/Direct.tsx +++ b/src/app/pages/client/direct/Direct.tsx @@ -189,9 +189,11 @@ export function Direct() { const roomToUnread = useAtomValue(roomToUnreadAtom); const navigate = useNavigate(); const [customDMCards] = useSetting(settingsAtom, 'customDMCards'); + const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms'); + const [isHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const [roomSidebarWidth, setRoomSidebarWidth] = useSetting(settingsAtom, 'roomSidebarWidth'); const [curWidth, setCurWidth] = useState(roomSidebarWidth); - useEffect(() => { setCurWidth(roomSidebarWidth); }, [roomSidebarWidth]); @@ -233,7 +235,8 @@ export function Direct() { const sortedDirects = useMemo(() => { void activityCounter; - const items = Array.from(directs).toSorted(factoryRoomIdByActivity(mx)); + let items = Array.from(directs).toSorted(factoryRoomIdByActivity(mx)); + if (isHidingRooms) items = items.filter((rId) => !hiddenRooms.includes(rId)); const hasUnread = (roomId: string) => { const unread = roomToUnread.get(roomId); return !!unread && (unread.total > 0 || unread.highlight > 0); @@ -242,7 +245,16 @@ export function Direct() { return items.filter((rId) => hasUnread(rId) || rId === selectedRoomId); } return items; - }, [mx, directs, closedCategories, roomToUnread, selectedRoomId, activityCounter]); + }, [ + mx, + directs, + closedCategories, + roomToUnread, + selectedRoomId, + activityCounter, + hiddenRooms, + isHidingRooms, + ]); 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 cddcefbb0..37c93d996 100644 --- a/src/app/pages/client/home/Home.tsx +++ b/src/app/pages/client/home/Home.tsx @@ -211,6 +211,9 @@ export function Home() { const roomToUnread = useAtomValue(roomToUnreadAtom); const navigate = useNavigate(); + const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms'); + const [isHidingRooms] = useSetting(settingsAtom, 'isHidingRooms'); + const [roomSidebarWidth, setRoomSidebarWidth] = useSetting(settingsAtom, 'roomSidebarWidth'); const [curWidth, setCurWidth] = useState(roomSidebarWidth); useEffect(() => { @@ -236,11 +239,13 @@ export function Home() { const [closedCategories, setClosedCategories] = useAtom(useClosedNavCategoriesAtom()); const sortedRooms = useMemo(() => { - const items = Array.from(rooms).toSorted( + let items = Array.from(rooms).toSorted( closedCategories.has(DEFAULT_CATEGORY_ID) ? factoryRoomIdByActivity(mx) : factoryRoomIdByAtoZ(mx) ); + + if (isHidingRooms) items = items.filter((rId) => !hiddenRooms.includes(rId)); const hasUnread = (roomId: string) => { const unread = roomToUnread.get(roomId); return !!unread && (unread.total > 0 || unread.highlight > 0); @@ -249,7 +254,7 @@ export function Home() { return items.filter((rId) => hasUnread(rId) || rId === selectedRoomId); } return items; - }, [mx, rooms, closedCategories, roomToUnread, selectedRoomId]); + }, [mx, rooms, closedCategories, roomToUnread, selectedRoomId, hiddenRooms, isHidingRooms]); const virtualizer = useVirtualizer({ count: sortedRooms.length, diff --git a/src/app/pages/client/sidebar/SpaceTabs.tsx b/src/app/pages/client/sidebar/SpaceTabs.tsx index 7ab00e859..34c01a273 100644 --- a/src/app/pages/client/sidebar/SpaceTabs.tsx +++ b/src/app/pages/client/sidebar/SpaceTabs.tsx @@ -660,7 +660,6 @@ type ClosedSpaceFolderProps = { onDragging: (dragItem?: SidebarDraggable) => void; disabled?: boolean; onFolderContextMenu?: MouseEventHandler; - hiddenSpaces?: string[]; }; function ClosedSpaceFolder({ folder, @@ -669,7 +668,6 @@ function ClosedSpaceFolder({ onDragging, disabled, onFolderContextMenu, - hiddenSpaces, }: Readonly) { const mx = useMatrixClient(); const useAuthentication = useMediaAuthentication(); @@ -703,7 +701,6 @@ function ClosedSpaceFolder({ onContextMenu={onFolderContextMenu} > {folder.content.map((sId) => { - if (hiddenSpaces?.includes(sId)) return null; const space = mx.getRoom(sId); if (!space) return null; @@ -963,7 +960,24 @@ export function SpaceTabs({ scrollRef }: Readonly) { [mx, sidebarItems, orphanSpaces, localEchoSidebarItem] ); - if (sidebarItems.length === 0) return null; + //This is a negative filter, so everything that IS inside of the 'filter' argument gets filtered OUT of the list + function handleFilterSpaces(list: SidebarItems, filter: string[] | undefined) { + if (filter?.length === 0) return list; + let spaces: TSidebarItem[] = []; + list.forEach((item) => { + if (typeof item === 'object') { + const filterSubSpaces = item.content.filter((sId) => !filter?.includes(sId)); + if (filterSubSpaces.length) { + let folder = item; + folder.content = filterSubSpaces; + spaces.push(folder); + } + } else if (!filter?.includes(item)) spaces.push(item); + }); + return spaces; + } + const filteredSidebarItems = handleFilterSpaces(sidebarItems, hiddenSpaces); + if (filteredSidebarItems.length === 0) return null; return ( <> {folderMenuState && ( @@ -1004,7 +1018,7 @@ export function SpaceTabs({ scrollRef }: Readonly) { )} - {sidebarItems.map((item) => { + {filteredSidebarItems.map((item) => { if (typeof item === 'object') { if (openedFolder.has(item.id)) { return ( @@ -1015,7 +1029,6 @@ export function SpaceTabs({ scrollRef }: Readonly) { onFolderContextMenu={handleFolderContextMenu(item)} > {item.content.map((sId) => { - if (hiddenSpaces?.includes(sId)) return null; const space = mx.getRoom(sId); if (!space) return null; return ( @@ -1050,11 +1063,9 @@ export function SpaceTabs({ scrollRef }: Readonly) { disabled={ typeof draggingItem === 'object' ? draggingItem.folder.id === item.id : false } - hiddenSpaces={hiddenSpaces} /> ); } - if (hiddenSpaces?.includes(item)) return null; const space = mx.getRoom(item); if (!space) return null; From f7cbce3bd2c39da782838d9e1ade1a72d619f02c Mon Sep 17 00:00:00 2001 From: Shea Duma Date: Mon, 18 May 2026 15:32:08 +0300 Subject: [PATCH 6/6] make the formatter happy :) --- src/app/components/user-profile/UserChips.tsx | 4 +--- src/app/features/settings/cosmetics/Themes.tsx | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/app/components/user-profile/UserChips.tsx b/src/app/components/user-profile/UserChips.tsx index 171d027df..2abb69961 100644 --- a/src/app/components/user-profile/UserChips.tsx +++ b/src/app/components/user-profile/UserChips.tsx @@ -558,9 +558,7 @@ export function MutualRoomsChip({ variant={cardColor ? undefined : 'SurfaceVariant'} radii="Pill" before={mutualRoomsState.status === AsyncStatus.Loading && } - disabled={ - mutualRoomsState.status !== AsyncStatus.Success || baseMutualRooms.length === 0 - } + disabled={mutualRoomsState.status !== AsyncStatus.Success || baseMutualRooms.length === 0} onClick={open} aria-pressed={!!cords} className={cardColor ? css.UserHeroChipThemed : css.UserHeroBrightnessHover} diff --git a/src/app/features/settings/cosmetics/Themes.tsx b/src/app/features/settings/cosmetics/Themes.tsx index 606dc92cd..de1ab971e 100644 --- a/src/app/features/settings/cosmetics/Themes.tsx +++ b/src/app/features/settings/cosmetics/Themes.tsx @@ -883,7 +883,7 @@ export function Appearance({ setHiddenSpaces([]); }} radii="300" - disabled={hiddenRooms.length === 0 && hiddenSpaces.length === 0} + disabled={hiddenRooms?.length === 0 && hiddenSpaces?.length === 0} >