diff --git a/src/app/pages/client/home/Home.tsx b/src/app/pages/client/home/Home.tsx index 4a3a0e0df..b08f7dc77 100644 --- a/src/app/pages/client/home/Home.tsx +++ b/src/app/pages/client/home/Home.tsx @@ -255,6 +255,8 @@ function HomeCustomSection({ return (localName ?? matrixName).toLowerCase().includes(query); }); }, [mx, section.rooms, closed, roomsWithUnreadSet, selectedRoomId, filterQuery]); + // [Gitea #289] While filtering, a section with no matches is hidden. + if (filterQuery.trim() && items.length === 0) return null; // Sections are user-curated and small, so they render plainly — no // virtualizer per section (a late-mounted one never measured its scroller). return ( @@ -443,6 +445,26 @@ export function Home() { }); }, [mx, sortedRooms, filterQuery]); + // [Gitea #289] While filtering, hide empty sections; with no match at all, + // say so instead of leaving bare headers. + const filtering = filterQuery.trim().length > 0; + const customSectionMatch = useMemo(() => { + if (!filtering) return true; + const query = filterQuery.toLowerCase(); + const localNames = getLocalRoomNamesContent(mx); + return customSections.some((section) => + section.rooms.some((rId) => + (localNames.rooms[rId] ?? mx.getRoom(rId)?.name ?? '').toLowerCase().includes(query), + ), + ); + }, [mx, customSections, filtering, filterQuery]); + const noFilterMatch = + filtering && + !customSectionMatch && + filteredFavoriteRooms.length === 0 && + filteredRooms.length === 0 && + filteredLowPriorityRooms.length === 0; + const favVirtualizer = useVirtualizer({ count: filteredFavoriteRooms.length, getScrollElement: () => scrollRef.current, @@ -580,7 +602,7 @@ export function Home() { /> - {favoriteRooms.length > 0 && ( + {favoriteRooms.length > 0 && (!filtering || filteredFavoriteRooms.length > 0) && ( ))} - - - + - Rooms - - {!closedCategories.has(DEFAULT_CATEGORY_ID) && ( - <> - ) => { - const cords = evt.currentTarget.getBoundingClientRect(); - setSortMenuAnchor((current) => (current ? undefined : cords)); - }} - aria-label="Sort rooms" - > - - - setSortMenuAnchor(undefined), - clickOutsideDeactivates: true, - isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown', - isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp', - escapeDeactivates: stopPropagation, - }} - > - - - { - setHomeRoomSort('recent'); - setSortMenuAnchor(undefined); - }} - size="300" - after={ - homeRoomSort === 'recent' ? ( - - ) : undefined - } - radii="300" + + No rooms match “{filterQuery.trim()}” + + + + + )} + {(!filtering || filteredRooms.length > 0) && ( + + + + Rooms + + {!closedCategories.has(DEFAULT_CATEGORY_ID) && ( + <> + ) => { + const cords = evt.currentTarget.getBoundingClientRect(); + setSortMenuAnchor((current) => (current ? undefined : cords)); + }} + aria-label="Sort rooms" + > + + + setSortMenuAnchor(undefined), + clickOutsideDeactivates: true, + isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown', + isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp', + escapeDeactivates: stopPropagation, + }} + > + + - - Recent Activity - - - { - setHomeRoomSort('alpha'); - setSortMenuAnchor(undefined); - }} - size="300" - after={ - homeRoomSort === 'alpha' ? ( - - ) : undefined - } - radii="300" - > - - A → Z - - - { - setHomeRoomSort('unread'); - setSortMenuAnchor(undefined); - }} - size="300" - after={ - homeRoomSort === 'unread' ? ( - - ) : undefined - } - radii="300" - > - - Unread First - - - - - - } - /> - - )} - -
- {virtualizer.getVirtualItems().map((vItem) => { - const roomId = filteredRooms[vItem.index]; - const room = mx.getRoom(roomId); - if (!room) return null; - const selected = selectedRoomId === roomId; - - return ( - - { + setHomeRoomSort('recent'); + setSortMenuAnchor(undefined); + }} + size="300" + after={ + homeRoomSort === 'recent' ? ( + + ) : undefined + } + radii="300" + > + + Recent Activity + + + { + setHomeRoomSort('alpha'); + setSortMenuAnchor(undefined); + }} + size="300" + after={ + homeRoomSort === 'alpha' ? ( + + ) : undefined + } + radii="300" + > + + A → Z + + + { + setHomeRoomSort('unread'); + setSortMenuAnchor(undefined); + }} + size="300" + after={ + homeRoomSort === 'unread' ? ( + + ) : undefined + } + radii="300" + > + + Unread First + + + +
+ + } /> - - ); - })} - -
- {lowPriorityRooms.length > 0 && ( + + )} +
+
+ {virtualizer.getVirtualItems().map((vItem) => { + const roomId = filteredRooms[vItem.index]; + const room = mx.getRoom(roomId); + if (!room) return null; + const selected = selectedRoomId === roomId; + + return ( + + + + ); + })} +
+
+ )} + {lowPriorityRooms.length > 0 && (!filtering || filteredLowPriorityRooms.length > 0) && (