mirror of https://github.com/vector-im/riot-web
Implement RequiresClient capability for widgets (#7005)
parent
68b64564c0
commit
5736fea5f3
|
@ -84,6 +84,7 @@ interface IState {
|
|||
error: Error;
|
||||
menuDisplayed: boolean;
|
||||
widgetPageTitle: string;
|
||||
requiresClient: boolean;
|
||||
}
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
@ -114,8 +115,10 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
this.persistKey = getPersistKey(this.props.app.id);
|
||||
try {
|
||||
this.sgWidget = new StopGapWidget(this.props);
|
||||
this.sgWidget.on("preparing", this.onWidgetPrepared);
|
||||
this.sgWidget.on("preparing", this.onWidgetPreparing);
|
||||
this.sgWidget.on("ready", this.onWidgetReady);
|
||||
// emits when the capabilites have been setup or changed
|
||||
this.sgWidget.on("capabilitiesNotified", this.onWidgetCapabilitiesNotified);
|
||||
} catch (e) {
|
||||
logger.log("Failed to construct widget", e);
|
||||
this.sgWidget = null;
|
||||
|
@ -155,6 +158,10 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
error: null,
|
||||
menuDisplayed: false,
|
||||
widgetPageTitle: this.props.widgetPageTitle,
|
||||
// requiresClient is initially set to true. This avoids the broken state of the popout
|
||||
// button being visible (for an instance) and then disappearing when the widget is loaded.
|
||||
// requiresClient <-> hide the popout button
|
||||
requiresClient: true,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -216,7 +223,7 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
}
|
||||
try {
|
||||
this.sgWidget = new StopGapWidget(newProps);
|
||||
this.sgWidget.on("preparing", this.onWidgetPrepared);
|
||||
this.sgWidget.on("preparing", this.onWidgetPreparing);
|
||||
this.sgWidget.on("ready", this.onWidgetReady);
|
||||
this.startWidget();
|
||||
} catch (e) {
|
||||
|
@ -287,7 +294,7 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
if (this.sgWidget) this.sgWidget.stop({ forceDestroy: true });
|
||||
}
|
||||
|
||||
private onWidgetPrepared = (): void => {
|
||||
private onWidgetPreparing = (): void => {
|
||||
this.setState({ loading: false });
|
||||
};
|
||||
|
||||
|
@ -297,6 +304,12 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onWidgetCapabilitiesNotified = (): void => {
|
||||
this.setState({
|
||||
requiresClient: this.sgWidget.widgetApi.hasCapability(MatrixCapabilities.RequiresClient),
|
||||
});
|
||||
};
|
||||
|
||||
private onAction = (payload): void => {
|
||||
if (payload.widgetId === this.props.app.id) {
|
||||
switch (payload.action) {
|
||||
|
@ -512,7 +525,7 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
{ this.props.showTitle && this.getTileTitle() }
|
||||
</span>
|
||||
<span className="mx_AppTileMenuBarWidgets">
|
||||
{ this.props.showPopout && <AccessibleButton
|
||||
{ (this.props.showPopout && !this.state.requiresClient) && <AccessibleButton
|
||||
className="mx_AppTileMenuBar_iconButton mx_AppTileMenuBar_iconButton_popout"
|
||||
title={_t('Popout widget')}
|
||||
onClick={this.onPopoutWidgetClick}
|
||||
|
|
|
@ -135,7 +135,7 @@ export class ElementWidget extends Widget {
|
|||
};
|
||||
}
|
||||
|
||||
public getCompleteUrl(params: ITemplateParams, asPopout=false): string {
|
||||
public getCompleteUrl(params: ITemplateParams, asPopout = false): string {
|
||||
return runTemplate(asPopout ? this.popoutTemplateUrl : this.templateUrl, {
|
||||
...this.rawDefinition,
|
||||
data: this.rawData,
|
||||
|
@ -149,7 +149,7 @@ export class StopGapWidget extends EventEmitter {
|
|||
private scalarToken: string;
|
||||
private roomId?: string;
|
||||
private kind: WidgetKind;
|
||||
private readUpToMap: {[roomId: string]: string} = {}; // room ID to event ID
|
||||
private readUpToMap: { [roomId: string]: string } = {}; // room ID to event ID
|
||||
|
||||
constructor(private appTileProps: IAppTileProps) {
|
||||
super();
|
||||
|
@ -262,6 +262,7 @@ export class StopGapWidget extends EventEmitter {
|
|||
this.messaging = new ClientWidgetApi(this.mockWidget, iframe, driver);
|
||||
this.messaging.on("preparing", () => this.emit("preparing"));
|
||||
this.messaging.on("ready", () => this.emit("ready"));
|
||||
this.messaging.on("capabilitiesNotified", () => this.emit("capabilitiesNotified"));
|
||||
this.messaging.on(`action:${WidgetApiFromWidgetAction.OpenModalWidget}`, this.onOpenModal);
|
||||
WidgetMessagingStore.instance.storeMessaging(this.mockWidget, this.messaging);
|
||||
|
||||
|
|
|
@ -73,7 +73,9 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
|||
// Always allow screenshots to be taken because it's a client-induced flow. The widget can't
|
||||
// spew screenshots at us and can't request screenshots of us, so it's up to us to provide the
|
||||
// button if the widget says it supports screenshots.
|
||||
this.allowedCapabilities = new Set([...allowedCapabilities, MatrixCapabilities.Screenshots]);
|
||||
this.allowedCapabilities = new Set([...allowedCapabilities,
|
||||
MatrixCapabilities.Screenshots,
|
||||
MatrixCapabilities.RequiresClient]);
|
||||
|
||||
// Grant the permissions that are specific to given widget types
|
||||
if (WidgetType.JITSI.matches(this.forWidget.type) && forWidgetKind === WidgetKind.Room) {
|
||||
|
|
Loading…
Reference in New Issue