diff --git a/src/WidgetMessaging.js b/src/WidgetMessaging.js index 50013a1c30..93fee6133b 100644 --- a/src/WidgetMessaging.js +++ b/src/WidgetMessaging.js @@ -195,8 +195,8 @@ export default class WidgetMessaging extends MatrixPostMessageApi { api: INBOUND_API_NAME, version: WIDGET_API_VERSION, }); - } else if (action === 'sticker_message') { - dis.dispatch({action: 'sticker_message', data: event.data.widgetData, widgetId: event.data.widgetId}); + } else if (action === 'm.sticker') { + dis.dispatch({action: 'm.sticker', data: event.data.widgetData, widgetId: event.data.widgetId}); } else if (action === 'integration_manager_open') { // Close the stickerpicker dis.dispatch({action: 'stickerpicker_close'}); diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index bd03683830..3249cae22c 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -69,7 +69,7 @@ const FilePanel = React.createClass({ "timeline": { "contains_url": true, "not_types": [ - "m.room.sticker", + "m.sticker", ], }, }, diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 01008b4f8e..e408d752a8 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -72,7 +72,9 @@ export default class AppTile extends React.Component { error: null, deleting: false, widgetPageTitle: newProps.widgetPageTitle, - capabilities: [], + allowedCapabilities: (this.props.whitelistCapabilities && this.props.whitelistCapabilities.length > 0) ? + this.props.whitelistCapabilities : [], + requestedCapabilities: [], }; } @@ -82,7 +84,7 @@ export default class AppTile extends React.Component { * @return {Boolean} True if capability supported */ _hasCapability(capability) { - return this.state.capabilities.some((c) => {return c === capability;}); + return this.state.allowedCapabilities.some((c) => {return c === capability;}); } /** @@ -341,10 +343,27 @@ export default class AppTile extends React.Component { this.widgetMessaging = new WidgetMessaging(this.props.id, this.refs.appFrame.contentWindow); this.widgetMessaging.startListening(); this.widgetMessaging.addEndpoint(this.props.id, this.props.url); - this.widgetMessaging.getCapabilities().then((capabilities) => { - console.log("Got widget capabilities", this.props.id, capabilities); - capabilities = capabilities || []; - this.setState({capabilities}); + this.widgetMessaging.getCapabilities().then((requestedCapabilities) => { + console.log(`Widget ${this.props.id} requested capabilities:`, requestedCapabilities); + requestedCapabilities = requestedCapabilities || []; + + // Allow whitelisted capabilities + const requestedWhitelistCapabilies = + requestedCapabilities.filter(function(e) { + return this.indexOf(e)>=0; + }, this.props.whitelistCapabilities); + console.warn(`Widget ${this.props.id} allowing requested, whitelisted properties:`, + requestedWhitelistCapabilies); + + // TODO -- Add UI to warn about and optionally allow requested capabilities + this.setState({ + requestedCapabilities, + allowedCapabilities: this.state.allowedCapabilities.concat(requestedWhitelistCapabilies), + }); + + if (this.props.onCapabilityRequest) { + this.props.onCapabilityRequest(requestedCapabilities); + } }).catch((err) => { console.log("Failed to get widget capabilities", this.widgetId, err); }); @@ -354,8 +373,8 @@ export default class AppTile extends React.Component { _onWidgetAction(payload) { if (payload.widgetId === this.props.id) { switch (payload.action) { - case 'sticker_message': - if (this._hasCapability('sticker_message')) { + case 'm.sticker': + if (this._hasCapability('m.sticker')) { dis.dispatch({action: 'post_sticker_message', data: payload.data}); } else { console.warn('Ignoring sticker message. Invalid capability'); @@ -626,6 +645,13 @@ AppTile.propTypes = { handleMinimisePointerEvents: PropTypes.bool, // Optionally hide the delete icon showDelete: PropTypes.bool, + // Widget apabilities to allow by default (without user confirmation) + // NOTE -- Use with caution. This is intended to aid better integration / UX + // basic widget capabilities, e.g. injecting sticker message events. + whitelistCapabilities: PropTypes.array, + // Optional function to be called on widget capability request + // Called with an array of the requested capabilities + onCapabilityRequest: PropTypes.func, }; AppTile.defaultProps = { @@ -636,4 +662,5 @@ AppTile.defaultProps = { showMinimise: true, showDelete: true, handleMinimisePointerEvents: false, + whitelistCapabilities: [], }; diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 080a756db7..7358e297c7 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -65,7 +65,7 @@ module.exports = React.createClass({ let BodyType = UnknownBody; if (msgtype && bodyTypes[msgtype]) { BodyType = bodyTypes[msgtype]; - } else if (this.props.mxEvent.getType() === 'm.room.sticker') { + } else if (this.props.mxEvent.getType() === 'm.sticker') { BodyType = sdk.getComponent('messages.MStickerBody'); } else if (content.url) { // Fallback to MFileBody if there's a content URL diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 50c8ddd67e..0d587b0e7b 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -36,7 +36,7 @@ const ObjectUtils = require('../../../ObjectUtils'); const eventTileTypes = { 'm.room.message': 'messages.MessageEvent', - 'm.room.sticker': 'messages.MessageEvent', + 'm.sticker': 'messages.MessageEvent', 'm.call.invite': 'messages.TextualEvent', 'm.call.answer': 'messages.TextualEvent', 'm.call.hangup': 'messages.TextualEvent', diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 76ef0a8753..1171ad1ee0 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -159,6 +159,7 @@ export default class Stickerpicker extends React.Component { showDelete={false} onMinimiseClick={this.onHideStickersClick} handleMinimisePointerEvents={true} + whitelistCapabilities={['m.sticker']} />