From f4a778ecbbe6d41d6ddfecae783ef76545158bd9 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 29 Dec 2024 14:55:18 +0200 Subject: [PATCH] web/roomlist: add pseudo-space for space orphans --- web/src/api/statestore/main.ts | 14 +++++++++++--- web/src/api/statestore/space.ts | 26 ++++++++++++++++++++------ web/src/ui/roomlist/RoomList.tsx | 15 ++++++++++++--- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/web/src/api/statestore/main.ts b/web/src/api/statestore/main.ts index 71db297..724754a 100644 --- a/web/src/api/statestore/main.ts +++ b/web/src/api/statestore/main.ts @@ -39,7 +39,7 @@ import { } from "../types" import { InvitedRoomStore } from "./invitedroom.ts" import { RoomStateStore } from "./room.ts" -import { RoomListFilter, SpaceEdgeStore } from "./space.ts" +import { RoomListFilter, SpaceEdgeStore, SpaceOrphansSpace } from "./space.ts" export interface RoomListEntry { room_id: RoomID @@ -75,6 +75,7 @@ export class StateStore { readonly roomList = new NonNullCachedEventDispatcher([]) readonly topLevelSpaces = new NonNullCachedEventDispatcher([]) readonly spaceEdges: Map = new Map() + readonly spaceOrphans = new SpaceOrphansSpace(this) currentRoomListQuery: string = "" currentRoomListFilter: RoomListFilter | null = null readonly accountData: Map = new Map() @@ -277,11 +278,18 @@ export class StateStore { if (updatedRoomList) { this.roomList.emit(updatedRoomList) } - for (const [spaceID, children] of Object.entries(sync.space_edges ?? {})) { - this.getSpaceStore(spaceID, true).children = children + if (sync.space_edges) { + // Ensure all space stores exist first + for (const spaceID of Object.keys(sync.space_edges)) { + this.getSpaceStore(spaceID, true) + } + for (const [spaceID, children] of Object.entries(sync.space_edges ?? {})) { + this.getSpaceStore(spaceID, true).children = children + } } if (sync.top_level_spaces) { this.topLevelSpaces.emit(sync.top_level_spaces) + this.spaceOrphans.children = sync.top_level_spaces.map(child_id => ({ child_id })) } } diff --git a/web/src/api/statestore/space.ts b/web/src/api/statestore/space.ts index 22d354d..1815533 100644 --- a/web/src/api/statestore/space.ts +++ b/web/src/api/statestore/space.ts @@ -44,11 +44,11 @@ export class SpaceEdgeStore implements RoomListFilter { constructor(public id: RoomID, private parent: StateStore) { } - addParent(parent: SpaceEdgeStore) { + #addParent(parent: SpaceEdgeStore) { this.#parentSpaces.add(parent) } - removeParent(parent: SpaceEdgeStore) { + #removeParent(parent: SpaceEdgeStore) { this.#parentSpaces.delete(parent) } @@ -95,28 +95,42 @@ export class SpaceEdgeStore implements RoomListFilter { const spaceStore = this.parent.getSpaceStore(child.child_id) if (spaceStore) { newChildSpaces.add(spaceStore) - spaceStore.addParent(this) + spaceStore.#addParent(this) } else { newChildRooms.add(child.child_id) } } for (const space of this.#childSpaces) { if (!newChildSpaces.has(space)) { - space.removeParent(this) + space.#removeParent(this) } } const addedRooms = newChildRooms.difference(this.#childRooms) const removedRooms = this.#childRooms.difference(newChildRooms) + const didAddChildren = newChildSpaces.difference(this.#childSpaces).size > 0 + const recalculateFlattened = removedRooms.size > 0 || didAddChildren this.#children = newChildren this.#childRooms = newChildRooms this.#childSpaces = newChildSpaces if (this.#childSpaces.size > 0) { - this.#updateFlattened(removedRooms.size > 0, addedRooms) + this.#updateFlattened(recalculateFlattened, addedRooms) } else { this.#flattenedRooms = newChildRooms } if (this.#parentSpaces.size > 0) { - this.#notifyParentsOfChange(removedRooms.size > 0, addedRooms, new WeakSet()) + this.#notifyParentsOfChange(recalculateFlattened, addedRooms, new WeakSet()) } } } + +export class SpaceOrphansSpace extends SpaceEdgeStore { + static id = "fi.mau.gomuks.space_orphans" + + constructor(parent: StateStore) { + super(SpaceOrphansSpace.id, parent) + } + + include(room: RoomListEntry): boolean { + return !super.include(room) && !room.dm_user_id + } +} diff --git a/web/src/ui/roomlist/RoomList.tsx b/web/src/ui/roomlist/RoomList.tsx index 3289526..587ac8d 100644 --- a/web/src/ui/roomlist/RoomList.tsx +++ b/web/src/ui/roomlist/RoomList.tsx @@ -75,6 +75,12 @@ const RoomList = ({ activeRoomID }: RoomListProps) => { } const roomListFilter = client.store.roomListFilterFunc + const pseudoSpaces = [ + null, + DirectChatSpace, + UnreadsSpace, + client.store.spaceOrphans, + ] return
{
- - - + {pseudoSpaces.map(pseudoSpace => )} {spaces.map(roomID =>