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 InfoTooltip from "../views/elements/InfoTooltip";
|
||||||
import TextWithTooltip from "../views/elements/TextWithTooltip";
|
import TextWithTooltip from "../views/elements/TextWithTooltip";
|
||||||
import {useStateToggle} from "../../hooks/useStateToggle";
|
import {useStateToggle} from "../../hooks/useStateToggle";
|
||||||
import {getOrder} from "../../stores/SpaceStore";
|
import {getChildOrder} from "../../stores/SpaceStore";
|
||||||
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
|
||||||
import {linkifyElement} from "../../HtmlUtils";
|
import {linkifyElement} from "../../HtmlUtils";
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ export const HierarchyLevel = ({
|
||||||
const children = Array.from(relations.get(spaceId)?.values() || []);
|
const children = Array.from(relations.get(spaceId)?.values() || []);
|
||||||
const sortedChildren = sortBy(children, ev => {
|
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
|
// 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 [subspaces, childRooms] = sortedChildren.reduce((result, ev: ISpaceSummaryEvent) => {
|
||||||
const roomId = ev.state_key;
|
const roomId = ev.state_key;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import {EnhancedMap, mapDiff} from "../utils/maps";
|
||||||
import {setHasDiff} from "../utils/sets";
|
import {setHasDiff} from "../utils/sets";
|
||||||
import {ISpaceSummaryEvent, ISpaceSummaryRoom} from "../components/structures/SpaceRoomDirectory";
|
import {ISpaceSummaryEvent, ISpaceSummaryRoom} from "../components/structures/SpaceRoomDirectory";
|
||||||
import RoomViewStore from "./RoomViewStore";
|
import RoomViewStore from "./RoomViewStore";
|
||||||
|
import { arrayHasOrderChange } from "../utils/arrays";
|
||||||
|
|
||||||
interface IState {}
|
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`
|
// 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;
|
let validatedOrder: string = null;
|
||||||
|
|
||||||
if (typeof order === "string" && Array.from(order).every((c: string) => {
|
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 roomId = ev.getStateKey();
|
||||||
const childRoom = this.matrixClient?.getRoom(roomId);
|
const childRoom = this.matrixClient?.getRoom(roomId);
|
||||||
const createTs = childRoom?.currentState.getStateEvents(EventType.RoomCreate, "")?.getTs();
|
const createTs = childRoom?.currentState.getStateEvents(EventType.RoomCreate, "")?.getTs();
|
||||||
return getOrder(ev.getContent().order, createTs, roomId);
|
return getChildOrder(ev.getContent().order, createTs, roomId);
|
||||||
}).map(ev => {
|
}).map(ev => {
|
||||||
return this.matrixClient.getRoom(ev.getStateKey());
|
return this.matrixClient.getRoom(ev.getStateKey());
|
||||||
}).filter(room => {
|
}).filter(room => {
|
||||||
|
@ -326,7 +335,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
// rootSpaces.push(space);
|
// rootSpaces.push(space);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
this.rootSpaces = rootSpaces;
|
this.rootSpaces = sortRootSpaces(rootSpaces);
|
||||||
this.parentMap = backrefs;
|
this.parentMap = backrefs;
|
||||||
|
|
||||||
// if the currently selected space no longer exists, remove its selection
|
// 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);
|
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
|
// 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);
|
this.emit(UPDATE_INVITED_SPACES, this.invitedSpaces);
|
||||||
}, 100, {trailing: true, leading: true});
|
}, 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) => {
|
private onRoomState = (ev: MatrixEvent) => {
|
||||||
const room = this.matrixClient.getRoom(ev.getRoomId());
|
const room = this.matrixClient.getRoom(ev.getRoomId());
|
||||||
if (!room) return;
|
if (!room) return;
|
||||||
|
@ -516,6 +539,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
if (this.matrixClient) {
|
if (this.matrixClient) {
|
||||||
this.matrixClient.removeListener("Room", this.onRoom);
|
this.matrixClient.removeListener("Room", this.onRoom);
|
||||||
this.matrixClient.removeListener("Room.myMembership", this.onRoom);
|
this.matrixClient.removeListener("Room.myMembership", this.onRoom);
|
||||||
|
this.matrixClient.removeListener("Room.accountData", this.onRoomAccountData);
|
||||||
this.matrixClient.removeListener("RoomState.events", this.onRoomState);
|
this.matrixClient.removeListener("RoomState.events", this.onRoomState);
|
||||||
}
|
}
|
||||||
await this.reset();
|
await this.reset();
|
||||||
|
@ -525,6 +549,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
if (!SettingsStore.getValue("feature_spaces")) return;
|
if (!SettingsStore.getValue("feature_spaces")) return;
|
||||||
this.matrixClient.on("Room", this.onRoom);
|
this.matrixClient.on("Room", this.onRoom);
|
||||||
this.matrixClient.on("Room.myMembership", this.onRoom);
|
this.matrixClient.on("Room.myMembership", this.onRoom);
|
||||||
|
this.matrixClient.on("Room.accountData", this.onRoomAccountData);
|
||||||
this.matrixClient.on("RoomState.events", this.onRoomState);
|
this.matrixClient.on("RoomState.events", this.onRoomState);
|
||||||
|
|
||||||
await this.onSpaceUpdate(); // trigger an initial update
|
await this.onSpaceUpdate(); // trigger an initial update
|
||||||
|
|
Loading…
Reference in a new issue