fix(perf,a11y): selectAtom for unread subscriptions, semantic headings, Perf-5 binary search
Perf-3: Replace raw roomToUnreadAtom subscription in Home, Direct, Space with selectAtom-derived Set<string> — components now only re-render when rooms gain/lose unread presence, not on every notification count update Perf-5: RoomTimeline eventRenderer now uses binary search on precomputed timelineSegments instead of O(N×T) linear scan per visible message A11y L-1: Add as=h2 semantic heading to Home, Direct, Inbox, Space page nav titles so screen readers announce page sections correctly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import React, {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import { selectAtom } from 'jotai/utils';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
@@ -267,7 +268,7 @@ function SpaceHeader() {
|
||||
<PageNavHeader>
|
||||
<Box alignItems="Center" grow="Yes" gap="300">
|
||||
<Box grow="Yes" alignItems="Center" gap="100">
|
||||
<Text size="H4" truncate>
|
||||
<Text as="h2" size="H4" truncate>
|
||||
{spaceName}
|
||||
</Text>
|
||||
{joinRules?.join_rule !== JoinRule.Public && <Icon src={Icons.Lock} size="50" />}
|
||||
@@ -382,7 +383,25 @@ export function Space() {
|
||||
const spaceIdOrAlias = getCanonicalAliasOrRoomId(mx, space.roomId);
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
const roomToUnread = useAtomValue(roomToUnreadAtom);
|
||||
const roomsWithUnreadSet = useAtomValue(
|
||||
useMemo(
|
||||
() =>
|
||||
selectAtom(
|
||||
roomToUnreadAtom,
|
||||
(rtu) => {
|
||||
const s = new Set<string>();
|
||||
for (const id of rtu.keys()) s.add(id);
|
||||
return s;
|
||||
},
|
||||
(a, b) => {
|
||||
if (a.size !== b.size) return false;
|
||||
for (const id of a) if (!b.has(id)) return false;
|
||||
return true;
|
||||
}
|
||||
),
|
||||
[]
|
||||
)
|
||||
);
|
||||
const allRooms = useAtomValue(allRoomsAtom);
|
||||
const allJoinedRooms = useMemo(() => new Set(allRooms), [allRooms]);
|
||||
const notificationPreferences = useRoomsNotificationPreferencesContext();
|
||||
@@ -414,10 +433,10 @@ export function Space() {
|
||||
return false;
|
||||
}
|
||||
const showRoomAnyway =
|
||||
roomToUnread.has(roomId) || roomId === selectedRoomId || callEmbed?.roomId === roomId;
|
||||
roomsWithUnreadSet.has(roomId) || roomId === selectedRoomId || callEmbed?.roomId === roomId;
|
||||
return !showRoomAnyway;
|
||||
},
|
||||
[space.roomId, closedCategories, roomToUnread, selectedRoomId, callEmbed]
|
||||
[space.roomId, closedCategories, roomsWithUnreadSet, selectedRoomId, callEmbed]
|
||||
),
|
||||
useCallback(
|
||||
(sId) => closedCategories.has(makeNavCategoryId(space.roomId, sId)),
|
||||
|
||||
Reference in New Issue
Block a user