mirror of https://github.com/vector-im/riot-web
				
				
				
			Fix left panel widgets causing app crashes (again) (#7814)
* Add type safety around left panel widget handling * lintpull/21833/head
							parent
							
								
									2802d39bc9
								
							
						
					
					
						commit
						fa9af44523
					
				| 
						 | 
					@ -174,7 +174,7 @@ export default class AppTile extends React.Component<IProps, IState> {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private onRoomViewStoreUpdate = () => {
 | 
					    private onRoomViewStoreUpdate = () => {
 | 
				
			||||||
        if (this.props.room.roomId == RoomViewStore.getRoomId()) return;
 | 
					        if (this.props.room?.roomId === RoomViewStore.getRoomId()) return;
 | 
				
			||||||
        const isActiveWidget = ActiveWidgetStore.instance.getWidgetPersistence(this.props.app.id);
 | 
					        const isActiveWidget = ActiveWidgetStore.instance.getWidgetPersistence(this.props.app.id);
 | 
				
			||||||
        // Stop the widget if it's not the active (persistent) widget and it's not a user widget
 | 
					        // Stop the widget if it's not the active (persistent) widget and it's not a user widget
 | 
				
			||||||
        if (!isActiveWidget && !this.props.userWidget) {
 | 
					        if (!isActiveWidget && !this.props.userWidget) {
 | 
				
			||||||
| 
						 | 
					@ -186,7 +186,7 @@ export default class AppTile extends React.Component<IProps, IState> {
 | 
				
			||||||
        const isActiveWidget = ActiveWidgetStore.instance.getWidgetPersistence(this.props.app.id);
 | 
					        const isActiveWidget = ActiveWidgetStore.instance.getWidgetPersistence(this.props.app.id);
 | 
				
			||||||
        if (isActiveWidget) {
 | 
					        if (isActiveWidget) {
 | 
				
			||||||
            // We just left the room that the active widget was from.
 | 
					            // We just left the room that the active widget was from.
 | 
				
			||||||
            if (RoomViewStore.getRoomId() !== this.props.room.roomId) {
 | 
					            if (this.props.room && RoomViewStore.getRoomId() !== this.props.room.roomId) {
 | 
				
			||||||
                // If we are not actively looking at the room then destroy this widget entirely.
 | 
					                // If we are not actively looking at the room then destroy this widget entirely.
 | 
				
			||||||
                this.endWidgetActions();
 | 
					                this.endWidgetActions();
 | 
				
			||||||
            } else if (WidgetType.JITSI.matches(this.props.app.type)) {
 | 
					            } else if (WidgetType.JITSI.matches(this.props.app.type)) {
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ export default class AppTile extends React.Component<IProps, IState> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private onMyMembership = (room: Room, membership: string): void => {
 | 
					    private onMyMembership = (room: Room, membership: string): void => {
 | 
				
			||||||
        if (membership === "leave" && room.roomId === this.props.room.roomId) {
 | 
					        if (membership === "leave" && room.roomId === this.props.room?.roomId) {
 | 
				
			||||||
            this.onUserLeftRoom();
 | 
					            this.onUserLeftRoom();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					@ -376,7 +376,7 @@ export default class AppTile extends React.Component<IProps, IState> {
 | 
				
			||||||
            this.iframe.src = 'about:blank';
 | 
					            this.iframe.src = 'about:blank';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (WidgetType.JITSI.matches(this.props.app.type)) {
 | 
					        if (WidgetType.JITSI.matches(this.props.app.type) && this.props.room) {
 | 
				
			||||||
            CallHandler.instance.hangupCallApp(this.props.room.roomId);
 | 
					            CallHandler.instance.hangupCallApp(this.props.room.roomId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -432,7 +432,7 @@ export default class AppTile extends React.Component<IProps, IState> {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private grantWidgetPermission = (): void => {
 | 
					    private grantWidgetPermission = (): void => {
 | 
				
			||||||
        const roomId = this.props.room.roomId;
 | 
					        const roomId = this.props.room?.roomId;
 | 
				
			||||||
        logger.info("Granting permission for widget to load: " + this.props.app.eventId);
 | 
					        logger.info("Granting permission for widget to load: " + this.props.app.eventId);
 | 
				
			||||||
        const current = SettingsStore.getValue("allowedWidgets", roomId);
 | 
					        const current = SettingsStore.getValue("allowedWidgets", roomId);
 | 
				
			||||||
        current[this.props.app.eventId] = true;
 | 
					        current[this.props.app.eventId] = true;
 | 
				
			||||||
| 
						 | 
					@ -509,6 +509,7 @@ export default class AppTile extends React.Component<IProps, IState> {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private onToggleMaximisedClick = (): void => {
 | 
					    private onToggleMaximisedClick = (): void => {
 | 
				
			||||||
 | 
					        if (!this.props.room) return; // ignore action - it shouldn't even be visible
 | 
				
			||||||
        const targetContainer =
 | 
					        const targetContainer =
 | 
				
			||||||
            WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, Container.Center)
 | 
					            WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, Container.Center)
 | 
				
			||||||
                ? Container.Right
 | 
					                ? Container.Right
 | 
				
			||||||
| 
						 | 
					@ -517,6 +518,7 @@ export default class AppTile extends React.Component<IProps, IState> {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private onTogglePinnedClick = (): void => {
 | 
					    private onTogglePinnedClick = (): void => {
 | 
				
			||||||
 | 
					        if (!this.props.room) return; // ignore action - it shouldn't even be visible
 | 
				
			||||||
        const targetContainer =
 | 
					        const targetContainer =
 | 
				
			||||||
            WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, Container.Top)
 | 
					            WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, Container.Top)
 | 
				
			||||||
                ? Container.Right
 | 
					                ? Container.Right
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Room } from "matrix-js-sdk/src/models/room";
 | 
					import { Room } from "matrix-js-sdk/src/models/room";
 | 
				
			||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 | 
					import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 | 
				
			||||||
 | 
					import { Optional } from "matrix-events-sdk";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import SettingsStore from "../../settings/SettingsStore";
 | 
					import SettingsStore from "../../settings/SettingsStore";
 | 
				
			||||||
import WidgetStore, { IApp } from "../WidgetStore";
 | 
					import WidgetStore, { IApp } from "../WidgetStore";
 | 
				
			||||||
| 
						 | 
					@ -345,15 +346,15 @@ export class WidgetLayoutStore extends ReadyWatchingStore {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public getContainerWidgets(room: Room, container: Container): IApp[] {
 | 
					    public getContainerWidgets(room: Optional<Room>, container: Container): IApp[] {
 | 
				
			||||||
        return this.byRoom[room?.roomId]?.[container]?.ordered || [];
 | 
					        return this.byRoom[room?.roomId]?.[container]?.ordered || [];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public isInContainer(room: Room, widget: IApp, container: Container): boolean {
 | 
					    public isInContainer(room: Optional<Room>, widget: IApp, container: Container): boolean {
 | 
				
			||||||
        return this.getContainerWidgets(room, container).some(w => w.id === widget.id);
 | 
					        return this.getContainerWidgets(room, container).some(w => w.id === widget.id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public isVisibleOnScreen(room: Room, widgetId: string) {
 | 
					    public isVisibleOnScreen(room: Optional<Room>, widgetId: string) {
 | 
				
			||||||
        const wId = widgetId;
 | 
					        const wId = widgetId;
 | 
				
			||||||
        const inRightPanel =
 | 
					        const inRightPanel =
 | 
				
			||||||
            (RightPanelStore.instance.currentCard.phase == RightPanelPhases.Widget &&
 | 
					            (RightPanelStore.instance.currentCard.phase == RightPanelPhases.Widget &&
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue