diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index fda2652d12..c732d8ec95 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -240,10 +240,14 @@ export default class AppTile extends React.Component { this.iframe.src = 'about:blank'; } + if (WidgetType.JITSI.matches(this.props.app.type)) { + dis.dispatch({action: 'hangup_conference'}); + } + // Delete the widget from the persisted store for good measure. PersistedElement.destroyElement(this._persistKey); - this._sgWidget.stop(); + this._sgWidget.stop({forceDestroy: true}); } /* If user has permission to modify widgets, delete the widget, @@ -387,6 +391,9 @@ export default class AppTile extends React.Component { if (this.props.show) { // if we were being shown, end the widget as we're about to be minimized. this._endWidgetActions(); + } else { + // restart the widget actions + this._resetWidget(this.props); } dis.dispatch({ action: 'appsDrawer', diff --git a/src/components/views/elements/PersistentApp.js b/src/components/views/elements/PersistentApp.js index a3e413151a..8b2aa5c87c 100644 --- a/src/components/views/elements/PersistentApp.js +++ b/src/components/views/elements/PersistentApp.js @@ -58,6 +58,11 @@ export default class PersistentApp extends React.Component { const persistentWidgetInRoomId = ActiveWidgetStore.getRoomId(this.state.persistentWidgetId); if (this.state.roomId !== persistentWidgetInRoomId) { const persistentWidgetInRoom = MatrixClientPeg.get().getRoom(persistentWidgetInRoomId); + + // Sanity check the room - the widget may have been destroyed between render cycles, and + // thus no room is associated anymore. + if (!persistentWidgetInRoom) return null; + // get the widget data const appEvent = WidgetUtils.getRoomWidgets(persistentWidgetInRoom).find((ev) => { return ev.getStateKey() === ActiveWidgetStore.getPersistentWidgetId(); diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts index 1eb4f9cd27..41b040b8c6 100644 --- a/src/stores/widgets/StopGapWidget.ts +++ b/src/stores/widgets/StopGapWidget.ts @@ -74,6 +74,16 @@ class ElementWidget extends Widget { return super.templateUrl; } + public get popoutTemplateUrl(): string { + if (WidgetType.JITSI.matches(this.type)) { + return WidgetUtils.getLocalJitsiWrapperUrl({ + forLocalRender: false, // The only important difference between this and templateUrl() + auth: super.rawData?.auth, + }); + } + return this.templateUrl; // use this instead of super to ensure we get appropriate templating + } + public get rawData(): IWidgetData { let conferenceId = super.rawData['conferenceId']; if (conferenceId === undefined) { @@ -94,8 +104,8 @@ class ElementWidget extends Widget { }; } - public getCompleteUrl(params: ITemplateParams): string { - return runTemplate(this.templateUrl, { + public getCompleteUrl(params: ITemplateParams, asPopout=false): string { + return runTemplate(asPopout ? this.popoutTemplateUrl : this.templateUrl, { // we need to supply a whole widget to the template, but don't have // easy access to the definition the superclass is using, so be sad // and gutwrench it. @@ -109,7 +119,7 @@ class ElementWidget extends Widget { export class StopGapWidget extends EventEmitter { private messaging: ClientWidgetApi; - private mockWidget: Widget; + private mockWidget: ElementWidget; private scalarToken: string; constructor(private appTileProps: IAppTileProps) { @@ -133,12 +143,23 @@ export class StopGapWidget extends EventEmitter { * The URL to use in the iframe */ public get embedUrl(): string { + return this.runUrlTemplate({asPopout: false}); + } + + /** + * The URL to use in the popout + */ + public get popoutUrl(): string { + return this.runUrlTemplate({asPopout: true}); + } + + private runUrlTemplate(opts = {asPopout: false}): string { const templated = this.mockWidget.getCompleteUrl({ currentRoomId: RoomViewStore.getRoomId(), currentUserId: MatrixClientPeg.get().getUserId(), userDisplayName: OwnProfileStore.instance.displayName, userHttpAvatarUrl: OwnProfileStore.instance.getHttpAvatarUrl(), - }); + }, opts?.asPopout); // Add in some legacy support sprinkles // TODO: Replace these with proper widget params @@ -158,19 +179,6 @@ export class StopGapWidget extends EventEmitter { return parsed.toString().replace(/%24/g, '$'); } - /** - * The URL to use in the popout - */ - public get popoutUrl(): string { - if (WidgetType.JITSI.matches(this.mockWidget.type)) { - return WidgetUtils.getLocalJitsiWrapperUrl({ - forLocalRender: false, - auth: this.mockWidget.rawData?.auth, - }); - } - return this.embedUrl; - } - public get isManagedByManager(): boolean { return !!this.scalarToken; } @@ -275,8 +283,8 @@ export class StopGapWidget extends EventEmitter { } } - public stop() { - if (ActiveWidgetStore.getPersistentWidgetId() === this.mockWidget.id) { + public stop(opts = {forceDestroy: false}) { + if (!opts?.forceDestroy && ActiveWidgetStore.getPersistentWidgetId() === this.mockWidget.id) { console.log("Skipping destroy - persistent widget"); return; }