From 26a030abcd76daf27c9f360000e20d54fc65cb19 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 8 Jun 2021 12:40:38 +0100 Subject: [PATCH] Better handling for widgets that fail to load --- src/components/views/elements/AppTile.js | 40 +++++++++++++++++------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index b898ad2ebc..91ffbf2c27 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -47,9 +47,14 @@ export default class AppTile extends React.Component { // The key used for PersistedElement this._persistKey = getPersistKey(this.props.app.id); - this._sgWidget = new StopGapWidget(this.props); - this._sgWidget.on("preparing", this._onWidgetPrepared); - this._sgWidget.on("ready", this._onWidgetReady); + try { + this._sgWidget = new StopGapWidget(this.props); + this._sgWidget.on("preparing", this._onWidgetPrepared); + this._sgWidget.on("ready", this._onWidgetReady); + } catch (e) { + console.log("Failed to construct widget", e); + this._sgWidget = null; + } this.iframe = null; // ref to the iframe (callback style) this.state = this._getNewState(props); @@ -97,7 +102,7 @@ export default class AppTile extends React.Component { // Force the widget to be non-persistent (able to be deleted/forgotten) ActiveWidgetStore.destroyPersistentWidget(this.props.app.id); PersistedElement.destroyElement(this._persistKey); - this._sgWidget.stop(); + if (this._sgWidget) this._sgWidget.stop(); } this.setState({ hasPermissionToLoad }); @@ -117,7 +122,7 @@ export default class AppTile extends React.Component { componentDidMount() { // Only fetch IM token on mount if we're showing and have permission to load - if (this.state.hasPermissionToLoad) { + if (this._sgWidget && this.state.hasPermissionToLoad) { this._startWidget(); } @@ -146,10 +151,15 @@ export default class AppTile extends React.Component { if (this._sgWidget) { this._sgWidget.stop(); } - this._sgWidget = new StopGapWidget(newProps); - this._sgWidget.on("preparing", this._onWidgetPrepared); - this._sgWidget.on("ready", this._onWidgetReady); - this._startWidget(); + try { + this._sgWidget = new StopGapWidget(newProps); + this._sgWidget.on("preparing", this._onWidgetPrepared); + this._sgWidget.on("ready", this._onWidgetReady); + this._startWidget(); + } catch (e) { + console.log("Failed to construct widget", e); + this._sgWidget = null; + } } _startWidget() { @@ -161,7 +171,7 @@ export default class AppTile extends React.Component { _iframeRefChange = (ref) => { this.iframe = ref; if (ref) { - this._sgWidget.start(ref); + if (this._sgWidget) this._sgWidget.start(ref); } else { this._resetWidget(this.props); } @@ -209,7 +219,7 @@ export default class AppTile extends React.Component { // Delete the widget from the persisted store for good measure. PersistedElement.destroyElement(this._persistKey); - this._sgWidget.stop({forceDestroy: true}); + if (this._sgWidget) this._sgWidget.stop({forceDestroy: true}); } _onWidgetPrepared = () => { @@ -340,7 +350,13 @@ export default class AppTile extends React.Component { ); - if (!this.state.hasPermissionToLoad) { + if (this._sgWidget === null) { + appTileBody = ( +
+ +
+ ); + } else if (!this.state.hasPermissionToLoad) { // only possible for room widgets, can assert this.props.room here const isEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId); appTileBody = (