mirror of https://github.com/vector-im/riot-web
				
				
				
			Prevent mutations of js-sdk owned objects as it breaks accountData (#7504)
							parent
							
								
									3c70aa15d1
								
							
						
					
					
						commit
						8c20bcfe56
					
				| 
						 | 
				
			
			@ -15,6 +15,7 @@ limitations under the License.
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
import { Room } from "matrix-js-sdk/src/models/room";
 | 
			
		||||
import { EventType } from "matrix-js-sdk/src/@types/event";
 | 
			
		||||
 | 
			
		||||
import { MatrixClientPeg } from './MatrixClientPeg';
 | 
			
		||||
import AliasCustomisations from './customisations/Alias';
 | 
			
		||||
| 
						 | 
				
			
			@ -90,10 +91,10 @@ export function guessAndSetDMRoom(room: Room, isDirect: boolean): Promise<void>
 | 
			
		|||
export async function setDMRoom(roomId: string, userId: string): Promise<void> {
 | 
			
		||||
    if (MatrixClientPeg.get().isGuest()) return;
 | 
			
		||||
 | 
			
		||||
    const mDirectEvent = MatrixClientPeg.get().getAccountData('m.direct');
 | 
			
		||||
    const mDirectEvent = MatrixClientPeg.get().getAccountData(EventType.Direct);
 | 
			
		||||
    let dmRoomMap = {};
 | 
			
		||||
 | 
			
		||||
    if (mDirectEvent !== undefined) dmRoomMap = mDirectEvent.getContent();
 | 
			
		||||
    if (mDirectEvent !== undefined) dmRoomMap = { ...mDirectEvent.getContent() }; // copy as we will mutate
 | 
			
		||||
 | 
			
		||||
    // remove it from the lists of any others users
 | 
			
		||||
    // (it can only be a DM room for one person)
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +118,7 @@ export async function setDMRoom(roomId: string, userId: string): Promise<void> {
 | 
			
		|||
        dmRoomMap[userId] = roomList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await MatrixClientPeg.get().setAccountData('m.direct', dmRoomMap);
 | 
			
		||||
    await MatrixClientPeg.get().setAccountData(EventType.Direct, dmRoomMap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ limitations under the License.
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
import React, { ComponentType, createRef } from 'react';
 | 
			
		||||
import { createClient, MatrixClient } from 'matrix-js-sdk/src/matrix';
 | 
			
		||||
import { createClient, EventType, MatrixClient } from 'matrix-js-sdk/src/matrix';
 | 
			
		||||
import { ISyncStateData, SyncState } from 'matrix-js-sdk/src/sync';
 | 
			
		||||
import { MatrixError } from 'matrix-js-sdk/src/http-api';
 | 
			
		||||
import { InvalidStoreError } from "matrix-js-sdk/src/errors";
 | 
			
		||||
| 
						 | 
				
			
			@ -1297,16 +1297,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
 | 
			
		|||
            // run without the update to m.direct, making another welcome
 | 
			
		||||
            // user room (it doesn't wait for new data from the server, just
 | 
			
		||||
            // the saved sync to be loaded).
 | 
			
		||||
            const saveWelcomeUser = (ev) => {
 | 
			
		||||
                if (
 | 
			
		||||
                    ev.getType() === 'm.direct' &&
 | 
			
		||||
                    ev.getContent() &&
 | 
			
		||||
                    ev.getContent()[this.props.config.welcomeUserId]
 | 
			
		||||
                ) {
 | 
			
		||||
            const saveWelcomeUser = (ev: MatrixEvent) => {
 | 
			
		||||
                if (ev.getType() === EventType.Direct && ev.getContent()[this.props.config.welcomeUserId]) {
 | 
			
		||||
                    MatrixClientPeg.get().store.save(true);
 | 
			
		||||
                    MatrixClientPeg.get().removeListener(
 | 
			
		||||
                        "accountData", saveWelcomeUser,
 | 
			
		||||
                    );
 | 
			
		||||
                    MatrixClientPeg.get().removeListener("accountData", saveWelcomeUser);
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            MatrixClientPeg.get().on("accountData", saveWelcomeUser);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
 | 
			
		|||
import { Room } from "matrix-js-sdk/src/models/room";
 | 
			
		||||
import { isNullOrUndefined } from "matrix-js-sdk/src/utils";
 | 
			
		||||
import { logger } from "matrix-js-sdk/src/logger";
 | 
			
		||||
import { EventType } from "matrix-js-sdk/src/@types/event";
 | 
			
		||||
 | 
			
		||||
import SettingsStore from "../../settings/SettingsStore";
 | 
			
		||||
import { DefaultTagID, isCustomTag, OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models";
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +282,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> {
 | 
			
		|||
            }
 | 
			
		||||
            await this.handleRoomUpdate(room, RoomUpdateCause.Timeline);
 | 
			
		||||
            this.updateFn.trigger();
 | 
			
		||||
        } else if (payload.action === 'MatrixActions.accountData' && payload.event_type === 'm.direct') {
 | 
			
		||||
        } else if (payload.action === 'MatrixActions.accountData' && payload.event_type === EventType.Direct) {
 | 
			
		||||
            const eventPayload = (<any>payload); // TODO: Type out the dispatcher types
 | 
			
		||||
            const dmMap = eventPayload.event.getContent();
 | 
			
		||||
            for (const userId of Object.keys(dmMap)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,8 @@ import { uniq } from "lodash";
 | 
			
		|||
import { Room } from "matrix-js-sdk/src/models/room";
 | 
			
		||||
import { MatrixClient } from "matrix-js-sdk/src/client";
 | 
			
		||||
import { logger } from "matrix-js-sdk/src/logger";
 | 
			
		||||
import { EventType } from "matrix-js-sdk/src/@types/event";
 | 
			
		||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 | 
			
		||||
 | 
			
		||||
import { MatrixClientPeg } from '../MatrixClientPeg';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,14 +37,14 @@ export default class DMRoomMap {
 | 
			
		|||
    private roomToUser: {[key: string]: string} = null;
 | 
			
		||||
    private userToRooms: {[key: string]: string[]} = null;
 | 
			
		||||
    private hasSentOutPatchDirectAccountDataPatch: boolean;
 | 
			
		||||
    private mDirectEvent: object;
 | 
			
		||||
    private mDirectEvent: {[key: string]: string[]};
 | 
			
		||||
 | 
			
		||||
    constructor(private readonly matrixClient: MatrixClient) {
 | 
			
		||||
        // see onAccountData
 | 
			
		||||
        this.hasSentOutPatchDirectAccountDataPatch = false;
 | 
			
		||||
 | 
			
		||||
        const mDirectEvent = matrixClient.getAccountData('m.direct');
 | 
			
		||||
        this.mDirectEvent = mDirectEvent ? mDirectEvent.getContent() : {};
 | 
			
		||||
        const mDirectEvent = matrixClient.getAccountData(EventType.Direct)?.getContent() ?? {};
 | 
			
		||||
        this.mDirectEvent = { ...mDirectEvent }; // copy as we will mutate
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -81,9 +83,9 @@ export default class DMRoomMap {
 | 
			
		|||
        this.matrixClient.removeListener("accountData", this.onAccountData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private onAccountData = (ev) => {
 | 
			
		||||
        if (ev.getType() == 'm.direct') {
 | 
			
		||||
            this.mDirectEvent = this.matrixClient.getAccountData('m.direct').getContent() || {};
 | 
			
		||||
    private onAccountData = (ev: MatrixEvent) => {
 | 
			
		||||
        if (ev.getType() == EventType.Direct) {
 | 
			
		||||
            this.mDirectEvent = { ...ev.getContent() }; // copy as we will mutate
 | 
			
		||||
            this.userToRooms = null;
 | 
			
		||||
            this.roomToUser = null;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +96,7 @@ export default class DMRoomMap {
 | 
			
		|||
     * with ourself, not the other user. Fix it by guessing the other user and
 | 
			
		||||
     * modifying userToRooms
 | 
			
		||||
     */
 | 
			
		||||
    private patchUpSelfDMs(userToRooms) {
 | 
			
		||||
    private patchUpSelfDMs(userToRooms: Record<string, string[]>) {
 | 
			
		||||
        const myUserId = this.matrixClient.getUserId();
 | 
			
		||||
        const selfRoomIds = userToRooms[myUserId];
 | 
			
		||||
        if (selfRoomIds) {
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +132,7 @@ export default class DMRoomMap {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public getDMRoomsForUserId(userId): string[] {
 | 
			
		||||
    public getDMRoomsForUserId(userId: string): string[] {
 | 
			
		||||
        // Here, we return the empty list if there are no rooms,
 | 
			
		||||
        // since the number of conversations you have with this user is zero.
 | 
			
		||||
        return this.getUserToRooms()[userId] || [];
 | 
			
		||||
| 
						 | 
				
			
			@ -189,10 +191,10 @@ export default class DMRoomMap {
 | 
			
		|||
 | 
			
		||||
    private getUserToRooms(): {[key: string]: string[]} {
 | 
			
		||||
        if (!this.userToRooms) {
 | 
			
		||||
            const userToRooms = this.mDirectEvent as {[key: string]: string[]};
 | 
			
		||||
            const userToRooms = this.mDirectEvent;
 | 
			
		||||
            const myUserId = this.matrixClient.getUserId();
 | 
			
		||||
            const selfDMs = userToRooms[myUserId];
 | 
			
		||||
            if (selfDMs && selfDMs.length) {
 | 
			
		||||
            if (selfDMs?.length) {
 | 
			
		||||
                const neededPatching = this.patchUpSelfDMs(userToRooms);
 | 
			
		||||
                // to avoid multiple devices fighting to correct
 | 
			
		||||
                // the account data, only try to send the corrected
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +203,7 @@ export default class DMRoomMap {
 | 
			
		|||
                    `(self-chats that shouldn't be), patching it up.`);
 | 
			
		||||
                if (neededPatching && !this.hasSentOutPatchDirectAccountDataPatch) {
 | 
			
		||||
                    this.hasSentOutPatchDirectAccountDataPatch = true;
 | 
			
		||||
                    this.matrixClient.setAccountData('m.direct', userToRooms);
 | 
			
		||||
                    this.matrixClient.setAccountData(EventType.Direct, userToRooms);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            this.userToRooms = userToRooms;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue