mirror of
https://github.com/element-hq/element-web.git
synced 2024-12-15 21:01:35 +03:00
Tell widgets to terminate gracefully in AppTile:_endWidgetActions
If the widget fails to terminate in two seconds, proceed with disposing the iframe nevertheless. This allows e.g. Jitsi to hangup the conference when minimizing the widget, instead of abrupt disconnect that can leave ghost users behind. Signed-off-by: Pauli Virtanen <pav@iki.fi>
This commit is contained in:
parent
1f2bf0485e
commit
4fac781051
1 changed files with 43 additions and 31 deletions
|
@ -340,8 +340,14 @@ export default class AppTile extends React.Component {
|
||||||
/**
|
/**
|
||||||
* Ends all widget interaction, such as cancelling calls and disabling webcams.
|
* Ends all widget interaction, such as cancelling calls and disabling webcams.
|
||||||
* @private
|
* @private
|
||||||
|
* @returns {Promise<*>} Resolves when the widget is terminated, or timeout passed.
|
||||||
*/
|
*/
|
||||||
_endWidgetActions() {
|
_endWidgetActions() {
|
||||||
|
const timeout = 2000;
|
||||||
|
const timeoutPromise = new Promise(resolve => setTimeout(resolve, timeout));
|
||||||
|
const messaging = ActiveWidgetStore.getWidgetMessaging(this.props.app.id);
|
||||||
|
|
||||||
|
return Promise.race([messaging.terminate(), timeoutPromise]).finally(() => {
|
||||||
// HACK: This is a really dirty way to ensure that Jitsi cleans up
|
// 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
|
// 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
|
// stream open, even after death. See https://github.com/vector-im/riot-web/issues/7351
|
||||||
|
@ -357,6 +363,7 @@ export default class AppTile extends React.Component {
|
||||||
|
|
||||||
// Delete the widget from the persisted store for good measure.
|
// Delete the widget from the persisted store for good measure.
|
||||||
PersistedElement.destroyElement(this._persistKey);
|
PersistedElement.destroyElement(this._persistKey);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If user has permission to modify widgets, delete the widget,
|
/* If user has permission to modify widgets, delete the widget,
|
||||||
|
@ -380,8 +387,7 @@ export default class AppTile extends React.Component {
|
||||||
}
|
}
|
||||||
this.setState({deleting: true});
|
this.setState({deleting: true});
|
||||||
|
|
||||||
this._endWidgetActions();
|
this._endWidgetActions().then(() => {
|
||||||
|
|
||||||
WidgetUtils.setRoomWidget(
|
WidgetUtils.setRoomWidget(
|
||||||
this.props.room.roomId,
|
this.props.room.roomId,
|
||||||
this.props.app.id,
|
this.props.app.id,
|
||||||
|
@ -396,6 +402,7 @@ export default class AppTile extends React.Component {
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.setState({deleting: false});
|
this.setState({deleting: false});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -545,14 +552,19 @@ export default class AppTile extends React.Component {
|
||||||
if (this.props.userWidget) {
|
if (this.props.userWidget) {
|
||||||
this._onMinimiseClick();
|
this._onMinimiseClick();
|
||||||
} else {
|
} else {
|
||||||
|
let promise;
|
||||||
if (this.props.show) {
|
if (this.props.show) {
|
||||||
// if we were being shown, end the widget as we're about to be minimized.
|
// if we were being shown, end the widget as we're about to be minimized.
|
||||||
this._endWidgetActions();
|
promise = this._endWidgetActions();
|
||||||
|
} else {
|
||||||
|
promise = Promise.resolve();
|
||||||
}
|
}
|
||||||
|
promise.then(() => {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'appsDrawer',
|
action: 'appsDrawer',
|
||||||
show: !this.props.show,
|
show: !this.props.show,
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue