diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 100a31bdcc..18be0eeb67 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -344,10 +344,18 @@ export default class AppTile extends React.Component { * @returns {Promise<*>} Resolves when the widget is terminated, or timeout passed. */ _endWidgetActions() { - const timeout = 2000; - const messaging = ActiveWidgetStore.getWidgetMessaging(this.props.app.id); + let promise; - return Promise.race([messaging.terminate(), sleep(timeout)]).finally(() => { + if (this._hasCapability('m.receive_terminate')) { + // Wait for widget to terminate within a timeout + const timeout = 2000; + const messaging = ActiveWidgetStore.getWidgetMessaging(this.props.app.id); + promise = Promise.race([messaging.terminate(), sleep(timeout)]); + } else { + promise = Promise.resolve(); + } + + return promise.finally(() => { // HACK: This is a really dirty way to ensure that Jitsi cleans up // its hold on the webcam. Without this, the widget holds a media // stream open, even after death. See https://github.com/vector-im/riot-web/issues/7351 diff --git a/src/utils/WidgetUtils.js b/src/utils/WidgetUtils.js index 6a0556c2b3..11dd5a88f7 100644 --- a/src/utils/WidgetUtils.js +++ b/src/utils/WidgetUtils.js @@ -420,6 +420,7 @@ export default class WidgetUtils { if (WidgetType.JITSI.matches(appType)) { capWhitelist.push(Capability.AlwaysOnScreen); } + capWhitelist.push(Capability.ReceiveTerminate); return capWhitelist; } diff --git a/src/widgets/WidgetApi.ts b/src/widgets/WidgetApi.ts index e08476edb5..6a29955713 100644 --- a/src/widgets/WidgetApi.ts +++ b/src/widgets/WidgetApi.ts @@ -23,6 +23,7 @@ export enum Capability { Screenshot = "m.capability.screenshot", Sticker = "m.sticker", AlwaysOnScreen = "m.always_on_screen", + ReceiveTerminate = "m.receive_terminate", } export enum KnownWidgetActions {