From fa9af4452357ebc1c65198f8192e9680662ef5fe Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 16 Feb 2022 13:26:18 -0700 Subject: [PATCH] Fix left panel widgets causing app crashes (again) (#7814) * Add type safety around left panel widget handling * lint --- src/components/views/elements/AppTile.tsx | 12 +++++++----- src/stores/widgets/WidgetLayoutStore.ts | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/views/elements/AppTile.tsx b/src/components/views/elements/AppTile.tsx index cc6ae80a380..77ad3fd89fc 100644 --- a/src/components/views/elements/AppTile.tsx +++ b/src/components/views/elements/AppTile.tsx @@ -174,7 +174,7 @@ export default class AppTile extends React.Component { }; 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); // Stop the widget if it's not the active (persistent) widget and it's not a user widget if (!isActiveWidget && !this.props.userWidget) { @@ -186,7 +186,7 @@ export default class AppTile extends React.Component { const isActiveWidget = ActiveWidgetStore.instance.getWidgetPersistence(this.props.app.id); if (isActiveWidget) { // 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. this.endWidgetActions(); } else if (WidgetType.JITSI.matches(this.props.app.type)) { @@ -200,7 +200,7 @@ export default class AppTile extends React.Component { } 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(); } }; @@ -376,7 +376,7 @@ export default class AppTile extends React.Component { 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); } @@ -432,7 +432,7 @@ export default class AppTile extends React.Component { }; 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); const current = SettingsStore.getValue("allowedWidgets", roomId); current[this.props.app.eventId] = true; @@ -509,6 +509,7 @@ export default class AppTile extends React.Component { }; private onToggleMaximisedClick = (): void => { + if (!this.props.room) return; // ignore action - it shouldn't even be visible const targetContainer = WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, Container.Center) ? Container.Right @@ -517,6 +518,7 @@ export default class AppTile extends React.Component { }; private onTogglePinnedClick = (): void => { + if (!this.props.room) return; // ignore action - it shouldn't even be visible const targetContainer = WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, Container.Top) ? Container.Right diff --git a/src/stores/widgets/WidgetLayoutStore.ts b/src/stores/widgets/WidgetLayoutStore.ts index 71c0fccbb04..896b7556486 100644 --- a/src/stores/widgets/WidgetLayoutStore.ts +++ b/src/stores/widgets/WidgetLayoutStore.ts @@ -16,6 +16,7 @@ import { Room } from "matrix-js-sdk/src/models/room"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { Optional } from "matrix-events-sdk"; import SettingsStore from "../../settings/SettingsStore"; 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, container: Container): IApp[] { return this.byRoom[room?.roomId]?.[container]?.ordered || []; } - public isInContainer(room: Room, widget: IApp, container: Container): boolean { + public isInContainer(room: Optional, widget: IApp, container: Container): boolean { return this.getContainerWidgets(room, container).some(w => w.id === widget.id); } - public isVisibleOnScreen(room: Room, widgetId: string) { + public isVisibleOnScreen(room: Optional, widgetId: string) { const wId = widgetId; const inRightPanel = (RightPanelStore.instance.currentCard.phase == RightPanelPhases.Widget &&