Fix codepath which can wrongly cause automatic space switch from all rooms (#8560)

* Fix codepath which can wrongly cause automatic space switch from all rooms

* Improve typing
This commit is contained in:
Michael Telatynski 2022-05-11 16:44:02 +01:00 committed by GitHub
parent 13aa610cd2
commit f9c85ac7c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 36 deletions

View file

@ -25,6 +25,8 @@ import { JoinedRoom as JoinedRoomEvent } from "matrix-analytics-events/types/typ
import { JoinRule } from "matrix-js-sdk/src/@types/partials"; import { JoinRule } from "matrix-js-sdk/src/@types/partials";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { ClientEvent } from "matrix-js-sdk/src/client"; import { ClientEvent } from "matrix-js-sdk/src/client";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Optional } from "matrix-events-sdk";
import dis from '../dispatcher/dispatcher'; import dis from '../dispatcher/dispatcher';
import { MatrixClientPeg } from '../MatrixClientPeg'; import { MatrixClientPeg } from '../MatrixClientPeg';
@ -53,30 +55,30 @@ const INITIAL_STATE = {
// Whether we're joining the currently viewed room (see isJoining()) // Whether we're joining the currently viewed room (see isJoining())
joining: false, joining: false,
// Any error that has occurred during joining // Any error that has occurred during joining
joinError: null, joinError: null as Error,
// The room ID of the room currently being viewed // The room ID of the room currently being viewed
roomId: null, roomId: null as string,
// The event to scroll to when the room is first viewed // The event to scroll to when the room is first viewed
initialEventId: null, initialEventId: null as string,
initialEventPixelOffset: null, initialEventPixelOffset: null as number,
// Whether to highlight the initial event // Whether to highlight the initial event
isInitialEventHighlighted: false, isInitialEventHighlighted: false,
// whether to scroll `event_id` into view // whether to scroll `event_id` into view
initialEventScrollIntoView: true, initialEventScrollIntoView: true,
// The room alias of the room (or null if not originally specified in view_room) // The room alias of the room (or null if not originally specified in view_room)
roomAlias: null, roomAlias: null as string,
// Whether the current room is loading // Whether the current room is loading
roomLoading: false, roomLoading: false,
// Any error that has occurred during loading // Any error that has occurred during loading
roomLoadError: null, roomLoadError: null as MatrixError,
replyingToEvent: null, replyingToEvent: null as MatrixEvent,
shouldPeek: false, shouldPeek: false,
viaServers: [], viaServers: [] as string[],
wasContextSwitch: false, wasContextSwitch: false,
}; };
@ -103,12 +105,12 @@ export class RoomViewStore extends Store<ActionPayload> {
super(dis); super(dis);
} }
public addRoomListener(roomId: string, fn: Listener) { public addRoomListener(roomId: string, fn: Listener): void {
if (!this.roomIdActivityListeners[roomId]) this.roomIdActivityListeners[roomId] = []; if (!this.roomIdActivityListeners[roomId]) this.roomIdActivityListeners[roomId] = [];
this.roomIdActivityListeners[roomId].push(fn); this.roomIdActivityListeners[roomId].push(fn);
} }
public removeRoomListener(roomId: string, fn: Listener) { public removeRoomListener(roomId: string, fn: Listener): void {
if (this.roomIdActivityListeners[roomId]) { if (this.roomIdActivityListeners[roomId]) {
const i = this.roomIdActivityListeners[roomId].indexOf(fn); const i = this.roomIdActivityListeners[roomId].indexOf(fn);
if (i > -1) { if (i > -1) {
@ -119,7 +121,7 @@ export class RoomViewStore extends Store<ActionPayload> {
} }
} }
private emitForRoom(roomId: string, isActive: boolean) { private emitForRoom(roomId: string, isActive: boolean): void {
if (!this.roomIdActivityListeners[roomId]) return; if (!this.roomIdActivityListeners[roomId]) return;
for (const fn of this.roomIdActivityListeners[roomId]) { for (const fn of this.roomIdActivityListeners[roomId]) {
@ -127,7 +129,7 @@ export class RoomViewStore extends Store<ActionPayload> {
} }
} }
private setState(newState: Partial<typeof INITIAL_STATE>) { private setState(newState: Partial<typeof INITIAL_STATE>): void {
// If values haven't changed, there's nothing to do. // If values haven't changed, there's nothing to do.
// This only tries a shallow comparison, so unchanged objects will slip // This only tries a shallow comparison, so unchanged objects will slip
// through, but that's probably okay for now. // through, but that's probably okay for now.
@ -160,7 +162,7 @@ export class RoomViewStore extends Store<ActionPayload> {
this.__emitChange(); this.__emitChange();
} }
protected __onDispatch(payload) { // eslint-disable-line @typescript-eslint/naming-convention protected __onDispatch(payload): void { // eslint-disable-line @typescript-eslint/naming-convention
switch (payload.action) { switch (payload.action) {
// view_room: // view_room:
// - room_alias: '#somealias:matrix.org' // - room_alias: '#somealias:matrix.org'
@ -367,7 +369,7 @@ export class RoomViewStore extends Store<ActionPayload> {
} }
} }
private viewRoomError(payload: ViewRoomErrorPayload) { private viewRoomError(payload: ViewRoomErrorPayload): void {
this.setState({ this.setState({
roomId: payload.room_id, roomId: payload.room_id,
roomAlias: payload.room_alias, roomAlias: payload.room_alias,
@ -376,7 +378,7 @@ export class RoomViewStore extends Store<ActionPayload> {
}); });
} }
private async joinRoom(payload: JoinRoomPayload) { private async joinRoom(payload: JoinRoomPayload): Promise<void> {
this.setState({ this.setState({
joining: true, joining: true,
}); });
@ -415,14 +417,14 @@ export class RoomViewStore extends Store<ActionPayload> {
private getInvitingUserId(roomId: string): string { private getInvitingUserId(roomId: string): string {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const room = cli.getRoom(roomId); const room = cli.getRoom(roomId);
if (room && room.getMyMembership() === "invite") { if (room?.getMyMembership() === "invite") {
const myMember = room.getMember(cli.getUserId()); const myMember = room.getMember(cli.getUserId());
const inviteEvent = myMember ? myMember.events.member : null; const inviteEvent = myMember ? myMember.events.member : null;
return inviteEvent && inviteEvent.getSender(); return inviteEvent && inviteEvent.getSender();
} }
} }
public showJoinRoomError(err: MatrixError, roomId: string) { public showJoinRoomError(err: MatrixError, roomId: string): void {
let description: ReactNode = err.message ? err.message : JSON.stringify(err); let description: ReactNode = err.message ? err.message : JSON.stringify(err);
logger.log("Failed to join room:", description); logger.log("Failed to join room:", description);
@ -452,7 +454,7 @@ export class RoomViewStore extends Store<ActionPayload> {
}); });
} }
private joinRoomError(payload: JoinRoomErrorPayload) { private joinRoomError(payload: JoinRoomErrorPayload): void {
this.setState({ this.setState({
joining: false, joining: false,
joinError: payload.err, joinError: payload.err,
@ -460,42 +462,42 @@ export class RoomViewStore extends Store<ActionPayload> {
this.showJoinRoomError(payload.err, payload.roomId); this.showJoinRoomError(payload.err, payload.roomId);
} }
public reset() { public reset(): void {
this.state = Object.assign({}, INITIAL_STATE); this.state = Object.assign({}, INITIAL_STATE);
} }
// The room ID of the room currently being viewed // The room ID of the room currently being viewed
public getRoomId() { public getRoomId(): Optional<string> {
return this.state.roomId; return this.state.roomId;
} }
// The event to scroll to when the room is first viewed // The event to scroll to when the room is first viewed
public getInitialEventId() { public getInitialEventId(): Optional<string> {
return this.state.initialEventId; return this.state.initialEventId;
} }
// Whether to highlight the initial event // Whether to highlight the initial event
public isInitialEventHighlighted() { public isInitialEventHighlighted(): boolean {
return this.state.isInitialEventHighlighted; return this.state.isInitialEventHighlighted;
} }
// Whether to avoid jumping to the initial event // Whether to avoid jumping to the initial event
public initialEventScrollIntoView() { public initialEventScrollIntoView(): boolean {
return this.state.initialEventScrollIntoView; return this.state.initialEventScrollIntoView;
} }
// The room alias of the room (or null if not originally specified in view_room) // The room alias of the room (or null if not originally specified in view_room)
public getRoomAlias() { public getRoomAlias(): Optional<string> {
return this.state.roomAlias; return this.state.roomAlias;
} }
// Whether the current room is loading (true whilst resolving an alias) // Whether the current room is loading (true whilst resolving an alias)
public isRoomLoading() { public isRoomLoading(): boolean {
return this.state.roomLoading; return this.state.roomLoading;
} }
// Any error that has occurred during loading // Any error that has occurred during loading
public getRoomLoadError() { public getRoomLoadError(): Optional<MatrixError> {
return this.state.roomLoadError; return this.state.roomLoadError;
} }
@ -522,25 +524,25 @@ export class RoomViewStore extends Store<ActionPayload> {
// // show join prompt // // show join prompt
// } // }
// } // }
public isJoining() { public isJoining(): boolean {
return this.state.joining; return this.state.joining;
} }
// Any error that has occurred during joining // Any error that has occurred during joining
public getJoinError() { public getJoinError(): Optional<Error> {
return this.state.joinError; return this.state.joinError;
} }
// The mxEvent if one is currently being replied to/quoted // The mxEvent if one is currently being replied to/quoted
public getQuotingEvent() { public getQuotingEvent(): Optional<MatrixEvent> {
return this.state.replyingToEvent; return this.state.replyingToEvent;
} }
public shouldPeek() { public shouldPeek(): boolean {
return this.state.shouldPeek; return this.state.shouldPeek;
} }
public getWasContextSwitch() { public getWasContextSwitch(): boolean {
return this.state.wasContextSwitch; return this.state.wasContextSwitch;
} }
} }

View file

@ -803,8 +803,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
this.updateNotificationStates(notificationStatesToUpdate); this.updateNotificationStates(notificationStatesToUpdate);
}; };
private switchSpaceIfNeeded = () => { private switchSpaceIfNeeded = (roomId = RoomViewStore.instance.getRoomId()) => {
const roomId = RoomViewStore.instance.getRoomId();
if (!this.isRoomInSpace(this.activeSpace, roomId) && !this.matrixClient.getRoom(roomId)?.isSpaceRoom()) { if (!this.isRoomInSpace(this.activeSpace, roomId) && !this.matrixClient.getRoom(roomId)?.isSpaceRoom()) {
this.switchToRelatedSpace(roomId); this.switchToRelatedSpace(roomId);
} }
@ -856,7 +855,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
// if the room currently being viewed was just joined then switch to its related space // if the room currently being viewed was just joined then switch to its related space
if (newMembership === "join" && room.roomId === RoomViewStore.instance.getRoomId()) { if (newMembership === "join" && room.roomId === RoomViewStore.instance.getRoomId()) {
this.switchToRelatedSpace(room.roomId); this.switchSpaceIfNeeded(room.roomId);
} }
} }
return; return;
@ -1131,8 +1130,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
// Don't context switch when navigating to the space room // Don't context switch when navigating to the space room
// as it will cause you to end up in the wrong room // as it will cause you to end up in the wrong room
this.setActiveSpace(room.roomId, false); this.setActiveSpace(room.roomId, false);
} else if (!this.isRoomInSpace(this.activeSpace, roomId)) { } else {
this.switchToRelatedSpace(roomId); this.switchSpaceIfNeeded(roomId);
} }
// Persist last viewed room from a space // Persist last viewed room from a space