Respect space ordering field in m.tag for top level spaces
This commit is contained in:
parent
da13ec16f3
commit
079a5c10ad
2 changed files with 31 additions and 6 deletions
|
@ -39,7 +39,7 @@ import {mediaFromMxc} from "../../customisations/Media";
|
|||
import InfoTooltip from "../views/elements/InfoTooltip";
|
||||
import TextWithTooltip from "../views/elements/TextWithTooltip";
|
||||
import {useStateToggle} from "../../hooks/useStateToggle";
|
||||
import {getOrder} from "../../stores/SpaceStore";
|
||||
import {getChildOrder} from "../../stores/SpaceStore";
|
||||
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
||||
import {linkifyElement} from "../../HtmlUtils";
|
||||
|
||||
|
@ -286,7 +286,7 @@ export const HierarchyLevel = ({
|
|||
const children = Array.from(relations.get(spaceId)?.values() || []);
|
||||
const sortedChildren = sortBy(children, ev => {
|
||||
// XXX: Space Summary API doesn't give the child origin_server_ts but once it does we should use it for sorting
|
||||
return getOrder(ev.content.order, null, ev.state_key);
|
||||
return getChildOrder(ev.content.order, null, ev.state_key);
|
||||
});
|
||||
const [subspaces, childRooms] = sortedChildren.reduce((result, ev: ISpaceSummaryEvent) => {
|
||||
const roomId = ev.state_key;
|
||||
|
|
|
@ -33,6 +33,7 @@ import {EnhancedMap, mapDiff} from "../utils/maps";
|
|||
import {setHasDiff} from "../utils/sets";
|
||||
import {ISpaceSummaryEvent, ISpaceSummaryRoom} from "../components/structures/SpaceRoomDirectory";
|
||||
import RoomViewStore from "./RoomViewStore";
|
||||
import { arrayHasOrderChange } from "../utils/arrays";
|
||||
|
||||
interface IState {}
|
||||
|
||||
|
@ -60,8 +61,16 @@ const partitionSpacesAndRooms = (arr: Room[]): [Room[], Room[]] => { // [spaces,
|
|||
}, [[], []]);
|
||||
};
|
||||
|
||||
const SpaceTagOrderingField = "org.matrix.mscXXXX.space";
|
||||
|
||||
const getSpaceTagOrdering = (space: Room): number | undefined => {
|
||||
return space?.getAccountData(EventType.Tag)?.getContent()?.tags?.[SpaceTagOrderingField]?.order;
|
||||
};
|
||||
|
||||
const sortRootSpaces = (spaces: Room[]): Room[] => sortBy(spaces, [getSpaceTagOrdering, "roomId"]);
|
||||
|
||||
// For sorting space children using a validated `order`, `m.room.create`'s `origin_server_ts`, `room_id`
|
||||
export const getOrder = (order: string, creationTs: number, roomId: string): Array<Many<ListIteratee<any>>> => {
|
||||
export const getChildOrder = (order: string, creationTs: number, roomId: string): Array<Many<ListIteratee<any>>> => {
|
||||
let validatedOrder: string = null;
|
||||
|
||||
if (typeof order === "string" && Array.from(order).every((c: string) => {
|
||||
|
@ -214,7 +223,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
const roomId = ev.getStateKey();
|
||||
const childRoom = this.matrixClient?.getRoom(roomId);
|
||||
const createTs = childRoom?.currentState.getStateEvents(EventType.RoomCreate, "")?.getTs();
|
||||
return getOrder(ev.getContent().order, createTs, roomId);
|
||||
return getChildOrder(ev.getContent().order, createTs, roomId);
|
||||
}).map(ev => {
|
||||
return this.matrixClient.getRoom(ev.getStateKey());
|
||||
}).filter(room => {
|
||||
|
@ -326,7 +335,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
// rootSpaces.push(space);
|
||||
// });
|
||||
|
||||
this.rootSpaces = rootSpaces;
|
||||
this.rootSpaces = sortRootSpaces(rootSpaces);
|
||||
this.parentMap = backrefs;
|
||||
|
||||
// if the currently selected space no longer exists, remove its selection
|
||||
|
@ -338,7 +347,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
this.emit(UPDATE_TOP_LEVEL_SPACES, this.spacePanelSpaces);
|
||||
|
||||
// build initial state of invited spaces as we would have missed the emitted events about the room at launch
|
||||
this._invitedSpaces = new Set(invitedSpaces);
|
||||
this._invitedSpaces = new Set(sortRootSpaces(invitedSpaces));
|
||||
this.emit(UPDATE_INVITED_SPACES, this.invitedSpaces);
|
||||
}, 100, {trailing: true, leading: true});
|
||||
|
||||
|
@ -472,6 +481,20 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onRoomAccountData = (ev: MatrixEvent, room: Room, lastEv?: MatrixEvent) => {
|
||||
if (!room.isSpaceRoom() || ev.getType() !== EventType.Tag) return;
|
||||
|
||||
const order = ev.getContent()?.tags?.[SpaceTagOrderingField]?.order;
|
||||
const lastOrder = lastEv?.getContent()?.tags?.[SpaceTagOrderingField]?.order;
|
||||
if (order !== lastOrder) {
|
||||
const rootSpaces = sortRootSpaces(this.rootSpaces);
|
||||
if (arrayHasOrderChange(this.rootSpaces, rootSpaces)) {
|
||||
this.rootSpaces = rootSpaces;
|
||||
this.emit(UPDATE_TOP_LEVEL_SPACES, this.spacePanelSpaces);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private onRoomState = (ev: MatrixEvent) => {
|
||||
const room = this.matrixClient.getRoom(ev.getRoomId());
|
||||
if (!room) return;
|
||||
|
@ -516,6 +539,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
if (this.matrixClient) {
|
||||
this.matrixClient.removeListener("Room", this.onRoom);
|
||||
this.matrixClient.removeListener("Room.myMembership", this.onRoom);
|
||||
this.matrixClient.removeListener("Room.accountData", this.onRoomAccountData);
|
||||
this.matrixClient.removeListener("RoomState.events", this.onRoomState);
|
||||
}
|
||||
await this.reset();
|
||||
|
@ -525,6 +549,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
if (!SettingsStore.getValue("feature_spaces")) return;
|
||||
this.matrixClient.on("Room", this.onRoom);
|
||||
this.matrixClient.on("Room.myMembership", this.onRoom);
|
||||
this.matrixClient.on("Room.accountData", this.onRoomAccountData);
|
||||
this.matrixClient.on("RoomState.events", this.onRoomState);
|
||||
|
||||
await this.onSpaceUpdate(); // trigger an initial update
|
||||
|
|
Loading…
Reference in a new issue