feat: implement useMarkAsRead hook for improved unread state management and update notification handling

This commit is contained in:
2026-02-28 00:10:35 +11:00
parent c890cce37a
commit 29c409fad8
16 changed files with 299 additions and 113 deletions

View File

@@ -42,7 +42,7 @@ import { useDirectRooms } from './useDirectRooms';
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
import { useRoomsUnread } from '../../../state/hooks/unread';
import { markAsRead } from '../../../utils/notifications';
import { useMarkRoomsAsRead } from '../../../hooks/useMarkAsRead';
import { stopPropagation } from '../../../utils/keyboard';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
@@ -60,10 +60,11 @@ const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
const orphanRooms = useDirectRooms();
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
const markRoomsAsRead = useMarkRoomsAsRead(mx);
const handleMarkAsRead = () => {
if (!unread) return;
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
markRoomsAsRead(orphanRooms, hideActivity);
requestClose();
};

View File

@@ -54,7 +54,7 @@ import { useCategoryHandler } from '../../../hooks/useCategoryHandler';
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
import { PageNav, PageNavHeader, PageNavContent } from '../../../components/page';
import { useRoomsUnread } from '../../../state/hooks/unread';
import { markAsRead } from '../../../utils/notifications';
import { useMarkRoomsAsRead } from '../../../hooks/useMarkAsRead';
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
import { stopPropagation } from '../../../utils/keyboard';
import { useSetting } from '../../../state/hooks/settings';
@@ -78,10 +78,11 @@ const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
const mx = useMatrixClient();
const markRoomsAsRead = useMarkRoomsAsRead(mx);
const handleMarkAsRead = () => {
if (!unread) return;
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
markRoomsAsRead(orphanRooms, hideActivity);
requestClose();
};

View File

@@ -73,7 +73,7 @@ import * as customHtmlCss from '../../../styles/CustomHtml.css';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { useRoomUnread } from '../../../state/hooks/unread';
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
import { markAsRead } from '../../../utils/notifications';
import { useMarkAsRead } from '../../../hooks/useMarkAsRead';
import { ContainerColor } from '../../../styles/ContainerColor.css';
import { VirtualTile } from '../../../components/virtualizer';
import { UserAvatar } from '../../../components/user-avatar';
@@ -374,6 +374,7 @@ function RoomNotificationsGroupComp({
const mentionClickHandler = useMentionClickHandler(room.roomId);
const spoilerClickHandler = useSpoilerClickHandler();
const markAsRead = useMarkAsRead(mx);
const linkifyOpts = useMemo<LinkifyOpts>(
() => ({
@@ -540,7 +541,7 @@ function RoomNotificationsGroupComp({
onOpen(room.roomId, eventId);
};
const handleMarkAsRead = () => {
markAsRead(mx, room.roomId, hideActivity);
markAsRead(room.roomId, hideActivity);
};
return (

View File

@@ -3,6 +3,9 @@ import { useNavigate } from 'react-router-dom';
import { Box, Icon, Icons, Menu, MenuItem, PopOut, RectCords, Text, config, toRem } from 'folds';
import FocusTrap from 'focus-trap-react';
import { useAtomValue } from 'jotai';
import PaarrotSVG from '../../../../../public/res/svg/paarrot.svg';
import PaarrotUnreadSVG from '../../../../../public/res/svg/paarrot-unread.svg';
import PaarrotHighlightSVG from '../../../../../public/res/svg/paarrot-highlight.svg';
import { useDirects } from '../../../state/hooks/roomList';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { mDirectAtom } from '../../../state/mDirectList';
@@ -21,7 +24,7 @@ import { UnreadBadge } from '../../../components/unread-badge';
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
import { useDirectRooms } from '../direct/useDirectRooms';
import { markAsRead } from '../../../utils/notifications';
import { useMarkRoomsAsRead } from '../../../hooks/useMarkAsRead';
import { stopPropagation } from '../../../utils/keyboard';
import { settingsAtom } from '../../../state/settings';
import { useSetting } from '../../../state/hooks/settings';
@@ -34,10 +37,11 @@ const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
const mx = useMatrixClient();
const markRoomsAsRead = useMarkRoomsAsRead(mx);
const handleMarkAsRead = () => {
if (!unread) return;
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
markRoomsAsRead(orphanRooms, hideActivity);
requestClose();
};
@@ -98,11 +102,20 @@ export function DirectTab() {
<SidebarAvatar
as="button"
ref={triggerRef}
outlined
onClick={handleDirectClick}
onContextMenu={handleContextMenu}
>
<Icon src={Icons.User} filled={directSelected} />
<img
src={
directUnread?.highlight
? PaarrotHighlightSVG
: directUnread?.total
? PaarrotUnreadSVG
: PaarrotSVG
}
alt="Direct Messages"
style={{ width: '100%', height: '100%', objectFit: 'contain' }}
/>
</SidebarAvatar>
)}
</SidebarItemTooltip>

View File

@@ -22,7 +22,7 @@ import { UnreadBadge } from '../../../components/unread-badge';
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
import { useHomeRooms } from '../home/useHomeRooms';
import { markAsRead } from '../../../utils/notifications';
import { useMarkRoomsAsRead } from '../../../hooks/useMarkAsRead';
import { stopPropagation } from '../../../utils/keyboard';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
@@ -39,10 +39,11 @@ const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(({ requestClose, onHi
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
const mx = useMatrixClient();
const markRoomsAsRead = useMarkRoomsAsRead(mx);
const handleMarkAsRead = () => {
if (!unread) return;
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
markRoomsAsRead(orphanRooms, hideActivity);
requestClose();
};

View File

@@ -90,7 +90,7 @@ import { useOpenedSidebarFolderAtom } from '../../../state/hooks/openedSidebarFo
import { usePowerLevels } from '../../../hooks/usePowerLevels';
import { useRoomsUnread } from '../../../state/hooks/unread';
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
import { markAsRead } from '../../../utils/notifications';
import { useMarkRoomsAsRead } from '../../../hooks/useMarkAsRead';
import { copyToClipboard } from '../../../utils/dom';
import { stopPropagation } from '../../../utils/keyboard';
import { getMatrixToRoom } from '../../../plugins/matrix-to';
@@ -123,6 +123,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
const permissions = useRoomPermissions(creators, powerLevels);
const canInvite = permissions.action('invite', mx.getSafeUserId());
const openSpaceSettings = useOpenSpaceSettings();
const markRoomsAsRead = useMarkRoomsAsRead(mx);
const [invitePrompt, setInvitePrompt] = useState(false);
@@ -134,7 +135,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
const unread = useRoomsUnread(allChild, roomToUnreadAtom);
const handleMarkAsRead = () => {
allChild.forEach((childRoomId) => markAsRead(mx, childRoomId, hideActivity));
markRoomsAsRead(allChild, hideActivity);
requestClose();
};

View File

@@ -59,7 +59,7 @@ import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page
import { usePowerLevels } from '../../../hooks/usePowerLevels';
import { useRecursiveChildScopeFactory, useSpaceChildren } from '../../../state/hooks/roomList';
import { roomToParentsAtom } from '../../../state/room/roomToParents';
import { markAsRead } from '../../../utils/notifications';
import { useMarkRoomsAsRead } from '../../../hooks/useMarkAsRead';
import { useRoomsUnread } from '../../../state/hooks/unread';
import { UseStateProvider } from '../../../components/UseStateProvider';
import { LeaveSpacePrompt } from '../../../components/leave-space-prompt';
@@ -101,6 +101,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
const canInvite = permissions.action('invite', mx.getSafeUserId());
const openSpaceSettings = useOpenSpaceSettings();
const { navigateRoom } = useRoomNavigate();
const markRoomsAsRead = useMarkRoomsAsRead(mx);
const [invitePrompt, setInvitePrompt] = useState(false);
@@ -112,7 +113,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
const unread = useRoomsUnread(allChild, roomToUnreadAtom);
const handleMarkAsRead = () => {
allChild.forEach((childRoomId) => markAsRead(mx, childRoomId, hideActivity));
markRoomsAsRead(allChild, hideActivity);
requestClose();
};