This commit is contained in:
@@ -7,11 +7,11 @@ use std::collections::HashMap;
|
||||
|
||||
/// Get space hierarchy
|
||||
pub async fn hierarchy(client: MatrixClientExtractor) -> HttpResult {
|
||||
let spaces = client.client.client.joined_space_rooms();
|
||||
let space_service = SpaceService::new(client.client.client);
|
||||
let spaces = space_service.joined_spaces().await;
|
||||
let mut hierarchy = HashMap::new();
|
||||
for space in spaces {
|
||||
let rooms = space_service.space_room_list(space.room_id.to_owned());
|
||||
let rooms = space_service.space_room_list(space.room_id().to_owned());
|
||||
while !matches!(
|
||||
rooms.pagination_state(),
|
||||
SpaceRoomListPaginationState::Idle { end_reached: true }
|
||||
@@ -20,7 +20,7 @@ pub async fn hierarchy(client: MatrixClientExtractor) -> HttpResult {
|
||||
}
|
||||
|
||||
hierarchy.insert(
|
||||
space.room_id.to_owned(),
|
||||
space.room_id().to_owned(),
|
||||
rooms
|
||||
.rooms()
|
||||
.into_iter()
|
||||
|
||||
40
matrixgw_frontend/src/api/matrix/MatrixApiSpace.ts
Normal file
40
matrixgw_frontend/src/api/matrix/MatrixApiSpace.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { APIClient } from "../ApiClient";
|
||||
|
||||
export type SpaceHierarchy = Map<string, string[]>;
|
||||
|
||||
export class MatrixApiSpace {
|
||||
/**
|
||||
* Request Matrix space hierarchy
|
||||
*/
|
||||
static async Hierarchy(): Promise<SpaceHierarchy> {
|
||||
const hierarchy = new Map(
|
||||
Object.entries(
|
||||
(
|
||||
await APIClient.exec({
|
||||
method: "GET",
|
||||
uri: "/matrix/space/hierarchy",
|
||||
})
|
||||
).data as { [s: string]: string[] }
|
||||
)
|
||||
) as SpaceHierarchy;
|
||||
|
||||
// Simplify hierarchy
|
||||
while (true) {
|
||||
let changed = false;
|
||||
for (const [roomid, children] of hierarchy) {
|
||||
for (const child of children) {
|
||||
if (!hierarchy.has(child)) continue;
|
||||
hierarchy.set(roomid, [
|
||||
...hierarchy.get(roomid)!,
|
||||
...hierarchy.get(child)!,
|
||||
]);
|
||||
hierarchy.delete(child);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (!changed) break;
|
||||
}
|
||||
|
||||
return hierarchy;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,10 @@ import {
|
||||
type UsersMap,
|
||||
} from "../../api/matrix/MatrixApiProfile";
|
||||
import { MatrixApiRoom, type Room } from "../../api/matrix/MatrixApiRoom";
|
||||
import {
|
||||
MatrixApiSpace,
|
||||
type SpaceHierarchy,
|
||||
} from "../../api/matrix/MatrixApiSpace";
|
||||
import { MatrixSyncApi } from "../../api/MatrixSyncApi";
|
||||
import type { WsMessage } from "../../api/WsApi";
|
||||
import { RoomEventsManager } from "../../utils/RoomEventsManager";
|
||||
@@ -19,13 +23,19 @@ import { SpaceSelector } from "./SpaceSelector";
|
||||
|
||||
export function MainMessageWidget(): React.ReactElement {
|
||||
const [rooms, setRooms] = React.useState<Room[] | undefined>();
|
||||
const [hierarchy, setHierarchy] = React.useState<
|
||||
SpaceHierarchy | undefined
|
||||
>();
|
||||
const [users, setUsers] = React.useState<UsersMap | undefined>();
|
||||
|
||||
const loadRoomsList = async () => {
|
||||
await MatrixSyncApi.Start();
|
||||
|
||||
const rooms = await MatrixApiRoom.ListJoined();
|
||||
const hierarchy = await MatrixApiSpace.Hierarchy();
|
||||
|
||||
setRooms(rooms);
|
||||
setHierarchy(hierarchy);
|
||||
|
||||
// Get the list of users in rooms
|
||||
const users = rooms.reduce((prev, r) => {
|
||||
@@ -40,11 +50,12 @@ export function MainMessageWidget(): React.ReactElement {
|
||||
<AsyncWidget
|
||||
loadKey={1}
|
||||
load={loadRoomsList}
|
||||
ready={!!rooms && !!users}
|
||||
ready={!!rooms && !!users && !!hierarchy}
|
||||
errMsg="Failed to initialize messaging component!"
|
||||
build={() => (
|
||||
<MainMessageWidgetInner
|
||||
rooms={rooms!}
|
||||
hierarchy={hierarchy!}
|
||||
users={users!}
|
||||
onRoomsListUpdate={(cb) => setRooms((r) => cb(r!))}
|
||||
/>
|
||||
@@ -55,6 +66,7 @@ export function MainMessageWidget(): React.ReactElement {
|
||||
|
||||
function MainMessageWidgetInner(p: {
|
||||
rooms: Room[];
|
||||
hierarchy: SpaceHierarchy;
|
||||
users: UsersMap;
|
||||
onRoomsListUpdate: (cb: (a: Room[]) => Room[]) => void;
|
||||
}): React.ReactElement {
|
||||
@@ -65,7 +77,9 @@ function MainMessageWidgetInner(p: {
|
||||
|
||||
const spaceRooms = React.useMemo(() => {
|
||||
return p.rooms
|
||||
.filter((r) => !r.is_space && (!space || r.parents.includes(space)))
|
||||
.filter(
|
||||
(r) => !r.is_space && (!space || p.hierarchy.get(space)?.includes(r.id))
|
||||
)
|
||||
.sort(
|
||||
(a, b) => (b.latest_event?.time ?? 0) - (a.latest_event?.time ?? 0)
|
||||
);
|
||||
|
||||
@@ -3,16 +3,18 @@ import { Button } from "@mui/material";
|
||||
import React from "react";
|
||||
import type { UsersMap } from "../../api/matrix/MatrixApiProfile";
|
||||
import type { Room } from "../../api/matrix/MatrixApiRoom";
|
||||
import type { SpaceHierarchy } from "../../api/matrix/MatrixApiSpace";
|
||||
import { RoomIcon } from "./RoomIcon";
|
||||
|
||||
export function SpaceSelector(p: {
|
||||
rooms: Room[];
|
||||
hierarchy: SpaceHierarchy;
|
||||
users: UsersMap;
|
||||
selectedSpace?: string;
|
||||
onChange: (space?: string) => void;
|
||||
}): React.ReactElement {
|
||||
const spaces = React.useMemo(
|
||||
() => p.rooms.filter((r) => r.is_space),
|
||||
() => p.rooms.filter((r) => r.is_space && p.hierarchy.has(r.id)),
|
||||
[p.rooms]
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user