1
0
Fork 0
forked from Mirrors/gomuks

web/roomlist: add pseudo-space for space orphans

This commit is contained in:
Tulir Asokan 2024-12-29 14:55:18 +02:00
parent 6b01dec307
commit f4a778ecbb
3 changed files with 43 additions and 12 deletions

View file

@ -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<RoomListEntry[]>([])
readonly topLevelSpaces = new NonNullCachedEventDispatcher<RoomID[]>([])
readonly spaceEdges: Map<RoomID, SpaceEdgeStore> = new Map()
readonly spaceOrphans = new SpaceOrphansSpace(this)
currentRoomListQuery: string = ""
currentRoomListFilter: RoomListFilter | null = null
readonly accountData: Map<string, UnknownEventContent> = new Map()
@ -277,11 +278,18 @@ export class StateStore {
if (updatedRoomList) {
this.roomList.emit(updatedRoomList)
}
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 }))
}
}

View file

@ -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
}
}

View file

@ -75,6 +75,12 @@ const RoomList = ({ activeRoomID }: RoomListProps) => {
}
const roomListFilter = client.store.roomListFilterFunc
const pseudoSpaces = [
null,
DirectChatSpace,
UnreadsSpace,
client.store.spaceOrphans,
]
return <div className="room-list-wrapper">
<div className="room-search-wrapper">
<input
@ -92,9 +98,12 @@ const RoomList = ({ activeRoomID }: RoomListProps) => {
</button>
</div>
<div className="space-bar">
<FakeSpace space={null} setSpace={setSpace} isActive={space === null} />
<FakeSpace space={DirectChatSpace} setSpace={setSpace} isActive={space?.id === DirectChatSpace.id} />
<FakeSpace space={UnreadsSpace} setSpace={setSpace} isActive={space?.id === UnreadsSpace.id} />
{pseudoSpaces.map(pseudoSpace => <FakeSpace
key={pseudoSpace?.id ?? "null"}
space={pseudoSpace}
setSpace={setSpace}
isActive={space?.id === pseudoSpace?.id}
/>)}
{spaces.map(roomID => <Space
roomID={roomID}
client={client}