diff --git a/web/src/ui/roomlist/FakeSpace.tsx b/web/src/ui/roomlist/FakeSpace.tsx index f8c595a..00ac3a7 100644 --- a/web/src/ui/roomlist/FakeSpace.tsx +++ b/web/src/ui/roomlist/FakeSpace.tsx @@ -27,6 +27,7 @@ export interface FakeSpaceProps { space: Space | null setSpace: (space: RoomListFilter | null) => void isActive: boolean + onClickUnread?: (evt: React.MouseEvent | null, space: Space | null) => void } const getFakeSpaceIcon = (space: RoomListFilter | null): JSX.Element | null => { @@ -44,10 +45,11 @@ const getFakeSpaceIcon = (space: RoomListFilter | null): JSX.Element | null => { } } -const FakeSpace = ({ space, setSpace, isActive }: FakeSpaceProps) => { +const FakeSpace = ({ space, setSpace, isActive, onClickUnread }: FakeSpaceProps) => { const unreads = useEventAsState(space?.counts) + const onClickUnreadWrapped = onClickUnread ? () => onClickUnread(null, space) : undefined return
setSpace(space)}> - + {getFakeSpaceIcon(space)}
} diff --git a/web/src/ui/roomlist/RoomList.tsx b/web/src/ui/roomlist/RoomList.tsx index 9b6ace3..04aff8d 100644 --- a/web/src/ui/roomlist/RoomList.tsx +++ b/web/src/ui/roomlist/RoomList.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import React, { use, useCallback, useRef, useState } from "react" -import { RoomListFilter } from "@/api/statestore/space.ts" +import { RoomListFilter, Space as SpaceStore, SpaceUnreadCounts } from "@/api/statestore/space.ts" import type { RoomID } from "@/api/types" import { useEventAsState } from "@/util/eventdispatcher.ts" import reverseMap from "@/util/reversemap.ts" @@ -54,6 +54,38 @@ const RoomList = ({ activeRoomID }: RoomListProps) => { const store = client.store.getSpaceStore(evt.currentTarget.getAttribute("data-target-space")!) setSpace(store) }, [setSpace, client]) + const onClickSpaceUnread = useCallback(( + evt: React.MouseEvent | null, space?: SpaceStore | null, + ) => { + if (evt) { + const targetSpace = evt.currentTarget.closest("div.space-entry")?.getAttribute("data-target-space") + if (!targetSpace) { + return + } + space = client.store.getSpaceStore(targetSpace) + } + if (!space) { + return + } + const counts = space.counts.current + let wantedField: keyof SpaceUnreadCounts + if (counts.unread_highlights > 0) { + wantedField = "unread_highlights" + } else if (counts.unread_notifications > 0) { + wantedField = "unread_notifications" + } else if (counts.unread_messages > 0) { + wantedField = "unread_messages" + } else { + return + } + for (let i = client.store.roomList.current.length - 1; i >= 0; i--) { + const entry = client.store.roomList.current[i] + if (entry[wantedField] > 0 && space.include(entry)) { + mainScreen.setActiveRoom(entry.room_id) + break + } + } + }, [mainScreen, client]) const clearQuery = () => { client.store.currentRoomListQuery = "" directSetQuery("") @@ -97,6 +129,7 @@ const RoomList = ({ activeRoomID }: RoomListProps) => { key={pseudoSpace.id} space={pseudoSpace} setSpace={setSpace} + onClickUnread={onClickSpaceUnread} isActive={space?.id === pseudoSpace.id} />)} {spaces.map(roomID => { client={client} onClick={onClickSpace} isActive={space?.id === roomID} + onClickUnread={onClickSpaceUnread} />)}
diff --git a/web/src/ui/roomlist/Space.tsx b/web/src/ui/roomlist/Space.tsx index 579915b..daeb35c 100644 --- a/web/src/ui/roomlist/Space.tsx +++ b/web/src/ui/roomlist/Space.tsx @@ -25,17 +25,18 @@ export interface SpaceProps { roomID: RoomID client: Client onClick: (evt: React.MouseEvent) => void + onClickUnread: (evt: React.MouseEvent) => void isActive: boolean } -const Space = ({ roomID, client, onClick, isActive }: SpaceProps) => { +const Space = ({ roomID, client, onClick, isActive, onClickUnread }: SpaceProps) => { const unreads = useEventAsState(client.store.spaceEdges.get(roomID)?.counts) const room = useEventAsState(client.store.rooms.get(roomID)?.meta) if (!room) { return } return
- + {room.name}
} diff --git a/web/src/ui/roomlist/UnreadCount.tsx b/web/src/ui/roomlist/UnreadCount.tsx index c563ae3..82807c0 100644 --- a/web/src/ui/roomlist/UnreadCount.tsx +++ b/web/src/ui/roomlist/UnreadCount.tsx @@ -22,9 +22,10 @@ interface UnreadCounts extends SpaceUnreadCounts { interface UnreadCountProps { counts: UnreadCounts | null space?: true + onClick?: (evt: React.MouseEvent) => void } -const UnreadCount = ({ counts, space }: UnreadCountProps) => { +const UnreadCount = ({ counts, space, onClick }: UnreadCountProps) => { if (!counts) { return null } @@ -46,15 +47,15 @@ const UnreadCount = ({ counts, space }: UnreadCountProps) => { if (countIsBig) { classNames.push("big") } - let unreadCountTitle = unreadCount.toString() if (space) { classNames.push("space") - unreadCountTitle = [ - counts.unread_highlights && `${counts.unread_highlights} highlights`, - counts.unread_notifications && `${counts.unread_notifications} notifications`, - counts.unread_messages && `${counts.unread_messages} messages`, - ].filter(x => !!x).join("\n") } + const unreadCountTitle = [ + counts.unread_highlights && `${counts.unread_highlights} highlights`, + counts.unread_notifications && `${counts.unread_notifications} notifications`, + counts.unread_messages && `${counts.unread_messages} messages`, + counts.marked_unread && "Marked unread", + ].filter(x => !!x).join("\n") if (counts.marked_unread) { classNames.push("marked-unread") } @@ -65,7 +66,7 @@ const UnreadCount = ({ counts, space }: UnreadCountProps) => { classNames.push("highlighted") } return
-
+
{unreadCountDisplay}