From 6b01dec30737bee1d1718bad0598bfb07d16745a Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 29 Dec 2024 14:40:32 +0200 Subject: [PATCH] web/roomlist: add pseudo-spaces for unreads and DMs Fixes #519 --- web/src/api/statestore/space.ts | 17 ++++++++- web/src/icons/notifications-unread.svg | 1 + web/src/icons/person.svg | 1 + web/src/icons/tag.svg | 1 + web/src/ui/roomlist/FakeSpace.tsx | 52 ++++++++++++++++++++++++++ web/src/ui/roomlist/RoomList.tsx | 10 ++--- 6 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 web/src/icons/notifications-unread.svg create mode 100644 web/src/icons/person.svg create mode 100644 web/src/icons/tag.svg create mode 100644 web/src/ui/roomlist/FakeSpace.tsx diff --git a/web/src/api/statestore/space.ts b/web/src/api/statestore/space.ts index f3a3fc0..22d354d 100644 --- a/web/src/api/statestore/space.ts +++ b/web/src/api/statestore/space.ts @@ -17,11 +17,24 @@ import { RoomListEntry, StateStore } from "@/api/statestore/main.ts" import { DBSpaceEdge, RoomID } from "@/api/types" export interface RoomListFilter { - id: unknown + id: string include(room: RoomListEntry): boolean } -export class SpaceEdgeStore { +export const DirectChatSpace: RoomListFilter = { + id: "fi.mau.gomuks.direct_chats", + include: room => !!room.dm_user_id, +} + +export const UnreadsSpace: RoomListFilter = { + id: "fi.mau.gomuks.unreads", + include: room => Boolean(room.unread_messages + || room.unread_notifications + || room.unread_highlights + || room.marked_unread), +} + +export class SpaceEdgeStore implements RoomListFilter { #children: DBSpaceEdge[] = [] #childRooms: Set = new Set() #flattenedRooms: Set = new Set() diff --git a/web/src/icons/notifications-unread.svg b/web/src/icons/notifications-unread.svg new file mode 100644 index 0000000..c96868b --- /dev/null +++ b/web/src/icons/notifications-unread.svg @@ -0,0 +1 @@ + diff --git a/web/src/icons/person.svg b/web/src/icons/person.svg new file mode 100644 index 0000000..aa2b620 --- /dev/null +++ b/web/src/icons/person.svg @@ -0,0 +1 @@ + diff --git a/web/src/icons/tag.svg b/web/src/icons/tag.svg new file mode 100644 index 0000000..71dadef --- /dev/null +++ b/web/src/icons/tag.svg @@ -0,0 +1 @@ + diff --git a/web/src/ui/roomlist/FakeSpace.tsx b/web/src/ui/roomlist/FakeSpace.tsx new file mode 100644 index 0000000..f3ffa53 --- /dev/null +++ b/web/src/ui/roomlist/FakeSpace.tsx @@ -0,0 +1,52 @@ +// gomuks - A Matrix client written in Go. +// Copyright (C) 2024 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +import { JSX } from "react" +import type { RoomListFilter } from "@/api/statestore/space.ts" +import HomeIcon from "@/icons/home.svg?react" +import NotificationsIcon from "@/icons/notifications.svg?react" +import PersonIcon from "@/icons/person.svg?react" +import TagIcon from "@/icons/tag.svg?react" +import "./RoomList.css" + +export interface FakeSpaceProps { + space: RoomListFilter | null + setSpace: (space: RoomListFilter | null) => void + isActive: boolean +} + +const getFakeSpaceIcon = (space: RoomListFilter | null): JSX.Element | null => { + switch (space?.id) { + case undefined: + return + case "fi.mau.gomuks.direct_chats": + return + case "fi.mau.gomuks.unreads": + return + case "fi.mau.gomuks.space_orphans": + return + default: + return null + } +} + +const FakeSpace = ({ space, setSpace, isActive }: FakeSpaceProps) => { + return
setSpace(space)}> + {getFakeSpaceIcon(space)} +
+ +} + +export default FakeSpace diff --git a/web/src/ui/roomlist/RoomList.tsx b/web/src/ui/roomlist/RoomList.tsx index 324c144..3289526 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 type { RoomListFilter } from "@/api/statestore/space.ts" +import { DirectChatSpace, RoomListFilter, UnreadsSpace } from "@/api/statestore/space.ts" import type { RoomID } from "@/api/types" import { useEventAsState } from "@/util/eventdispatcher.ts" import reverseMap from "@/util/reversemap.ts" @@ -23,9 +23,9 @@ import ClientContext from "../ClientContext.ts" import MainScreenContext from "../MainScreenContext.ts" import { keyToString } from "../keybindings.ts" import Entry from "./Entry.tsx" +import FakeSpace from "./FakeSpace.tsx" import Space from "./Space.tsx" import CloseIcon from "@/icons/close.svg?react" -import HomeIcon from "@/icons/home.svg?react" import SearchIcon from "@/icons/search.svg?react" import "./RoomList.css" @@ -92,9 +92,9 @@ const RoomList = ({ activeRoomID }: RoomListProps) => {
-
setSpace(null)}> - -
+ + + {spaces.map(roomID =>