From 7c80355ea7bff6f52bd2af1ea023ab69e44f6b0e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 13:38:23 -0600 Subject: [PATCH 01/12] Convert IntegrationsManager to a class --- .eslintignore.errorfiles | 1 - .../views/settings/IntegrationsManager.js | 57 +++++++++---------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/.eslintignore.errorfiles b/.eslintignore.errorfiles index a89c083518..9ecd39ffc2 100644 --- a/.eslintignore.errorfiles +++ b/.eslintignore.errorfiles @@ -47,7 +47,6 @@ src/components/views/rooms/UserTile.js src/components/views/settings/ChangeAvatar.js src/components/views/settings/ChangePassword.js src/components/views/settings/DevicesPanel.js -src/components/views/settings/IntegrationsManager.js src/components/views/settings/Notifications.js src/GroupAddressPicker.js src/HtmlUtils.js diff --git a/src/components/views/settings/IntegrationsManager.js b/src/components/views/settings/IntegrationsManager.js index a517771f1d..2e292b63fc 100644 --- a/src/components/views/settings/IntegrationsManager.js +++ b/src/components/views/settings/IntegrationsManager.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,50 +15,48 @@ See the License for the specific language governing permissions and limitations under the License. */ -'use strict'; +import React from 'react'; +import PropTypes from 'prop-types'; +import sdk from '../../../index'; +import MatrixClientPeg from '../../../MatrixClientPeg'; +import { _t } from '../../../languageHandler'; +import Modal from '../../../Modal'; +import dis from '../../../dispatcher'; -const React = require('react'); -const sdk = require('../../../index'); -const MatrixClientPeg = require('../../../MatrixClientPeg'); -const dis = require('../../../dispatcher'); +export default class IntegrationsManager extends React.Component { + static propTypes = { + // the source of the integration manager being embedded + src: PropTypes.string.isRequired, -module.exports = React.createClass({ - displayName: 'IntegrationsManager', + // callback when the manager is dismissed + onFinished: PropTypes.func.isRequired, + }; - propTypes: { - src: React.PropTypes.string.isRequired, // the source of the integration manager being embedded - onFinished: React.PropTypes.func.isRequired, // callback when the lightbox is dismissed - }, - - // XXX: keyboard shortcuts for managing dialogs should be done by the modal - // dialog base class somehow, surely... - componentDidMount: function() { + componentDidMount() { this.dispatcherRef = dis.register(this.onAction); document.addEventListener("keydown", this.onKeyDown); - }, + } - componentWillUnmount: function() { + componentWillUnmount() { dis.unregister(this.dispatcherRef); document.removeEventListener("keydown", this.onKeyDown); - }, + } - onKeyDown: function(ev) { - if (ev.keyCode == 27) { // escape + onKeyDown = (ev) => { + if (ev.keyCode === 27) { // escape ev.stopPropagation(); ev.preventDefault(); this.props.onFinished(); } - }, + }; - onAction: function(payload) { + onAction = (payload) => { if (payload.action === 'close_scalar') { this.props.onFinished(); } - }, + }; - render: function() { - return ( - - ); - }, -}); + render() { + return ; + } +} \ No newline at end of file From 6cc443cd018af9b416e5470b60cddf80d2267334 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:27:35 -0600 Subject: [PATCH 02/12] spelling --- src/CallHandler.js | 2 +- src/IntegrationManager.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CallHandler.js b/src/CallHandler.js index e47209eebe..5b58400ae6 100644 --- a/src/CallHandler.js +++ b/src/CallHandler.js @@ -344,7 +344,7 @@ function _onAction(payload) { } async function _startCallApp(roomId, type) { - // check for a working intgrations manager. Technically we could put + // check for a working integrations manager. Technically we could put // the state event in anyway, but the resulting widget would then not // work for us. Better that the user knows before everyone else in the // room sees it. diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 165ee6390d..4ca7fc57dc 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -44,7 +44,7 @@ export default class IntegrationManager { } /** - * Launch the integrations manager on the stickers integration page + * Launch the integrations manager on the specified integration page * @param {string} integName integration / widget type * @param {string} integId integration / widget ID * @param {function} onFinished Callback to invoke on integration manager close From a5f296457f53bd264c8e392c0d54b31c465eb508 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:29:19 -0600 Subject: [PATCH 03/12] Make the Manage Integrations Button defer scalar auth to the manager This moves the responsibility of creating a URL to open from the button (and other components) to the integrations manager dialog itself. By doing this, we also cut down on scalar API calls because we don't pick up on account information until the user opens the dialog. --- .../views/settings/_IntegrationsManager.scss | 13 +++ src/ScalarAuthClient.js | 11 ++- .../views/elements/ManageIntegsButton.js | 87 +++---------------- .../views/settings/IntegrationsManager.js | 86 ++++++++++++++++-- src/i18n/strings/en_EN.json | 8 +- 5 files changed, 125 insertions(+), 80 deletions(-) diff --git a/res/css/views/settings/_IntegrationsManager.scss b/res/css/views/settings/_IntegrationsManager.scss index 93ee0e20fe..c5769d3645 100644 --- a/res/css/views/settings/_IntegrationsManager.scss +++ b/res/css/views/settings/_IntegrationsManager.scss @@ -29,3 +29,16 @@ limitations under the License. width: 100%; height: 100%; } + +.mx_IntegrationsManager_loading h3 { + text-align: center; +} + +.mx_IntegrationsManager_error { + text-align: center; + padding-top: 20px; +} + +.mx_IntegrationsManager_error h3 { + color: $warning-color; +} \ No newline at end of file diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js index 24979aff65..27d8f0d0da 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.js @@ -29,6 +29,14 @@ class ScalarAuthClient { this.scalarToken = null; } + /** + * Determines if setting up a ScalarAuthClient is even possible + * @returns {boolean} true if possible, false otherwise. + */ + static isPossible() { + return SdkConfig.get()['integrations_rest_url'] && SdkConfig.get()['integrations_ui_url']; + } + connect() { return this.getScalarToken().then((tok) => { this.scalarToken = tok; @@ -41,7 +49,8 @@ class ScalarAuthClient { // Returns a scalar_token string getScalarToken() { - const token = window.localStorage.getItem("mx_scalar_token"); + let token = this.scalarToken; + if (!token) token = window.localStorage.getItem("mx_scalar_token"); if (!token) { return this.registerForToken(); diff --git a/src/components/views/elements/ManageIntegsButton.js b/src/components/views/elements/ManageIntegsButton.js index 165cd20eb5..f5d087e452 100644 --- a/src/components/views/elements/ManageIntegsButton.js +++ b/src/components/views/elements/ManageIntegsButton.js @@ -1,5 +1,6 @@ /* Copyright 2017 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,10 +18,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import sdk from '../../../index'; -import classNames from 'classnames'; -import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; -import ScalarMessaging from '../../../ScalarMessaging'; import Modal from "../../../Modal"; import { _t } from '../../../languageHandler'; import AccessibleButton from './AccessibleButton'; @@ -28,85 +26,28 @@ import AccessibleButton from './AccessibleButton'; export default class ManageIntegsButton extends React.Component { constructor(props) { super(props); - - this.state = { - scalarError: null, - }; - - this.onManageIntegrations = this.onManageIntegrations.bind(this); } - componentWillMount() { - ScalarMessaging.startListening(); - this.scalarClient = null; - - if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { - this.scalarClient = new ScalarAuthClient(); - this.scalarClient.connect().done(() => { - this.forceUpdate(); - }, (err) => { - this.setState({scalarError: err}); - console.error('Error whilst initialising scalarClient for ManageIntegsButton', err); - }); - } - } - - componentWillUnmount() { - ScalarMessaging.stopListening(); - } - - onManageIntegrations(ev) { + onManageIntegrations = (ev) => { ev.preventDefault(); - if (this.state.scalarError && !this.scalarClient.hasCredentials()) { - return; - } + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - this.scalarClient.connect().done(() => { - Modal.createDialog(IntegrationsManager, { - src: (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? - this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room) : - null, - }, "mx_IntegrationsManager"); - }, (err) => { - this.setState({scalarError: err}); - console.error('Error ensuring a valid scalar_token exists', err); - }); - } + Modal.createDialog(IntegrationsManager, { + room: this.props.room, + }, "mx_IntegrationsManager"); + }; render() { let integrationsButton =
; - let integrationsWarningTriangle =
; - let integrationsErrorPopup =
; - if (this.scalarClient !== null) { - const integrationsButtonClasses = classNames({ - mx_RoomHeader_button: true, - mx_RoomHeader_manageIntegsButton: true, - mx_ManageIntegsButton_error: !!this.state.scalarError, - }); - - if (this.state.scalarError && !this.scalarClient.hasCredentials()) { - integrationsWarningTriangle = ; - // Popup shown when hovering over integrationsButton_error (via CSS) - integrationsErrorPopup = ( - - { _t('Could not connect to the integration server') } - - ); - } - + if (ScalarAuthClient.isPossible()) { + const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); integrationsButton = ( - - { integrationsWarningTriangle } - { integrationsErrorPopup } - - ); + /> + ) } return integrationsButton; diff --git a/src/components/views/settings/IntegrationsManager.js b/src/components/views/settings/IntegrationsManager.js index 2e292b63fc..d9bf6351e9 100644 --- a/src/components/views/settings/IntegrationsManager.js +++ b/src/components/views/settings/IntegrationsManager.js @@ -18,20 +18,68 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import sdk from '../../../index'; -import MatrixClientPeg from '../../../MatrixClientPeg'; import { _t } from '../../../languageHandler'; -import Modal from '../../../Modal'; import dis from '../../../dispatcher'; +import ScalarAuthClient from '../../../ScalarAuthClient'; export default class IntegrationsManager extends React.Component { static propTypes = { - // the source of the integration manager being embedded - src: PropTypes.string.isRequired, + // the room object where the integrations manager should be opened in + room: PropTypes.object.isRequired, + + // the screen name to open + screen: PropTypes.string, + + // the integration ID to open + integrationId: PropTypes.string, // callback when the manager is dismissed onFinished: PropTypes.func.isRequired, }; + constructor(props) { + super(props); + + this.state = { + loading: true, + configured: ScalarAuthClient.isPossible(), + connected: false, // true if a `src` is set and able to be connected to + src: null, // string for where to connect to + }; + } + + componentWillMount() { + if (!this.state.configured) return; + + const scalarClient = new ScalarAuthClient(); + scalarClient.connect().then(() => { + const hasCredentials = scalarClient.hasCredentials(); + if (!hasCredentials) { + this.setState({ + connected: false, + loading: false, + }); + } else { + const src = scalarClient.getScalarInterfaceUrlForRoom( + this.props.room, + this.props.screen, + this.props.integrationId, + ); + this.setState({ + loading: false, + connected: true, + src: src, + }); + } + }).catch(err => { + console.error(err); + this.setState({ + loading: false, + connected: false, + }); + }) + } + componentDidMount() { this.dispatcherRef = dis.register(this.onAction); document.addEventListener("keydown", this.onKeyDown); @@ -57,6 +105,34 @@ export default class IntegrationsManager extends React.Component { }; render() { - return ; + if (!this.state.configured) { + return ( +
+

{_t("No integrations server configured")}

+

{_t("This Riot instance does not have an integrations server configured.")}

+
+ ); + } + + if (this.state.loading) { + const Spinner = sdk.getComponent("elements.Spinner"); + return ( +
+

{_t("Connecting to integrations server...")}

+ +
+ ); + } + + if (!this.state.connected) { + return ( +
+

{_t("Cannot connect to integrations server")}

+

{_t("The integrations server is offline or it cannot reach your homeserver.")}

+
+ ); + } + + return ; } } \ No newline at end of file diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 53fd82f6f2..c1fd3662ee 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -483,6 +483,11 @@ "Email Address": "Email Address", "Disable Notifications": "Disable Notifications", "Enable Notifications": "Enable Notifications", + "No integrations server configured": "No integrations server configured", + "This Riot instance does not have an integrations server configured.": "This Riot instance does not have an integrations server configured.", + "Connecting to integrations server...": "Connecting to integrations server...", + "Cannot connect to integrations server": "Cannot connect to integrations server", + "The integrations server is offline or it cannot reach your homeserver.": "The integrations server is offline or it cannot reach your homeserver.", "Delete Backup": "Delete Backup", "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.": "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.", "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", @@ -864,6 +869,8 @@ "This Room": "This Room", "All Rooms": "All Rooms", "Search…": "Search…", + "Failed to connect to integrations server": "Failed to connect to integrations server", + "No integrations server is configured to manage stickers with": "No integrations server is configured to manage stickers with", "You don't currently have any stickerpacks enabled": "You don't currently have any stickerpacks enabled", "Add some now": "Add some now", "Stickerpack": "Stickerpack", @@ -1017,7 +1024,6 @@ "Rotate Right": "Rotate Right", "Rotate clockwise": "Rotate clockwise", "Download this file": "Download this file", - "Integrations Error": "Integrations Error", "Manage Integrations": "Manage Integrations", "%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s", "%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sjoined %(count)s times", From ebabc5238d068509e3c8dd9d40c6d21ccd8c1218 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:30:01 -0600 Subject: [PATCH 04/12] Port integration manager class to new dialog props --- src/IntegrationManager.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 4ca7fc57dc..9cd984f12f 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -1,5 +1,6 @@ /* Copyright 2017 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,11 +20,14 @@ import SdkConfig from './SdkConfig'; import ScalarMessaging from './ScalarMessaging'; import ScalarAuthClient from './ScalarAuthClient'; import RoomViewStore from './stores/RoomViewStore'; +import MatrixClientPeg from "./MatrixClientPeg"; if (!global.mxIntegrationManager) { global.mxIntegrationManager = {}; } +// TODO: TravisR - What even is this? + export default class IntegrationManager { static _init() { if (!global.mxIntegrationManager.client || !global.mxIntegrationManager.connected) { @@ -62,16 +66,10 @@ export default class IntegrationManager { console.error("Scalar error", global.mxIntegrationManager); return; } - const integType = 'type_' + integName; - const src = (global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials()) ? - global.mxIntegrationManager.client.getScalarInterfaceUrlForRoom( - {roomId: RoomViewStore.getRoomId()}, - integType, - integId, - ) : - null; Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { - src: src, + room: MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), + screen: 'type_' + integName, + integrationId: integId, onFinished: onFinished, }, "mx_IntegrationsManager"); } From f699fed720a2689b48810685c3df2f034841defa Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:30:24 -0600 Subject: [PATCH 05/12] Defer sticker picker scalar auth to integration manager dialog or when needed, instead of up front. --- src/components/views/rooms/Stickerpicker.js | 78 +++++++++++---------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index a0e3f1b7a9..809d948840 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ import React from 'react'; -import { _t } from '../../../languageHandler'; +import {_t, _td} from '../../../languageHandler'; import AppTile from '../elements/AppTile'; import MatrixClientPeg from '../../../MatrixClientPeg'; import Modal from '../../../Modal'; @@ -53,6 +53,9 @@ export default class Stickerpicker extends React.Component { this.popoverWidth = 300; this.popoverHeight = 300; + // This is loaded by _acquireScalarClient on an as-needed basis. + this.scalarClient = null; + this.state = { showStickers: false, imError: null, @@ -63,14 +66,34 @@ export default class Stickerpicker extends React.Component { }; } - _removeStickerpickerWidgets() { + _acquireScalarClient() { + if (this.scalarClient) return Promise.resolve(this.scalarClient); + if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { + this.scalarClient = new ScalarAuthClient(); + return this.scalarClient.connect().then(() => { + this.forceUpdate(); + return this.scalarClient; + }).catch((e) => { + this._imError(_td("Failed to connect to integrations server"), e); + }); + } else { + this._imError(_td("No integrations server is configured to manage stickers with")); + } + } + + async _removeStickerpickerWidgets() { + const scalarClient = await this._acquireScalarClient(); console.warn('Removing Stickerpicker widgets'); if (this.state.widgetId) { - this.scalarClient.disableWidgetAssets(widgetType, this.state.widgetId).then(() => { - console.warn('Assets disabled'); - }).catch((err) => { - console.error('Failed to disable assets'); - }); + if (scalarClient) { + scalarClient.disableWidgetAssets(widgetType, this.state.widgetId).then(() => { + console.warn('Assets disabled'); + }).catch((err) => { + console.error('Failed to disable assets'); + }); + } else { + console.error("Cannot disable assets: no scalar client"); + } } else { console.warn('No widget ID specified, not disabling assets'); } @@ -87,19 +110,7 @@ export default class Stickerpicker extends React.Component { // Close the sticker picker when the window resizes window.addEventListener('resize', this._onResize); - this.scalarClient = null; - if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { - this.scalarClient = new ScalarAuthClient(); - this.scalarClient.connect().then(() => { - this.forceUpdate(); - }).catch((e) => { - this._imError("Failed to connect to integrations server", e); - }); - } - - if (!this.state.imError) { - this.dispatcherRef = dis.register(this._onWidgetAction); - } + this.dispatcherRef = dis.register(this._onWidgetAction); // Track updates to widget state in account data MatrixClientPeg.get().on('accountData', this._updateWidget); @@ -126,7 +137,7 @@ export default class Stickerpicker extends React.Component { console.error(errorMsg, e); this.setState({ showStickers: false, - imError: errorMsg, + imError: _t(errorMsg), }); } @@ -337,24 +348,15 @@ export default class Stickerpicker extends React.Component { /** * Launch the integrations manager on the stickers integration page */ - _launchManageIntegrations() { + async _launchManageIntegrations() { const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - this.scalarClient.connect().done(() => { - const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? - this.scalarClient.getScalarInterfaceUrlForRoom( - this.props.room, - 'type_' + widgetType, - this.state.widgetId, - ) : - null; - Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { - src: src, - }, "mx_IntegrationsManager"); - this.setState({showStickers: false}); - }, (err) => { - this.setState({imError: err}); - console.error('Error ensuring a valid scalar_token exists', err); - }); + + // The integrations manager will handle scalar auth for us. + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + room: this.props.room, + screen: `type_${widgetType}`, + integrationId: this.state.widgetId, + }, "mx_IntegrationsManager"); } render() { From d2d0cb2e9e6f671c380eb68228f024dcb5bab009 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:34:30 -0600 Subject: [PATCH 06/12] Port AppTile (widgets) over to new integration manager dialog props --- src/components/views/elements/AppTile.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 959cee7ace..60bc8a337e 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -240,19 +240,13 @@ export default class AppTile extends React.Component { if (this.props.onEditClick) { this.props.onEditClick(); } else { + // The dialog handles scalar auth for us const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - this._scalarClient.connect().done(() => { - const src = this._scalarClient.getScalarInterfaceUrlForRoom( - this.props.room, 'type_' + this.props.type, this.props.id); - Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { - src: src, - }, "mx_IntegrationsManager"); - }, (err) => { - this.setState({ - error: err.message, - }); - console.error('Error ensuring a valid scalar_token exists', err); - }); + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + room: this.props.room, + screen: 'type_' + this.props.type, + integrationId: this.props.id + }, "mx_IntegrationsManager"); } } From 974a11ed201d11a08bfa165d61af6401cf34d957 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:39:32 -0600 Subject: [PATCH 07/12] Defer scalar auth in AppsDrawer to widgets/manager dialog --- src/components/views/rooms/AppsDrawer.js | 30 ++++-------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index e0e7a48b8c..3e5528996f 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -24,8 +24,6 @@ import AppTile from '../elements/AppTile'; import Modal from '../../../Modal'; import dis from '../../../dispatcher'; import sdk from '../../../index'; -import SdkConfig from '../../../SdkConfig'; -import ScalarAuthClient from '../../../ScalarAuthClient'; import ScalarMessaging from '../../../ScalarMessaging'; import { _t } from '../../../languageHandler'; import WidgetUtils from '../../../utils/WidgetUtils'; @@ -63,20 +61,6 @@ module.exports = React.createClass({ }, componentDidMount: function() { - this.scalarClient = null; - if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { - this.scalarClient = new ScalarAuthClient(); - this.scalarClient.connect().then(() => { - this.forceUpdate(); - }).catch((e) => { - console.log('Failed to connect to integrations server'); - // TODO -- Handle Scalar errors - // this.setState({ - // scalar_error: err, - // }); - }); - } - this.dispatcherRef = dis.register(this.onAction); }, @@ -144,16 +128,10 @@ module.exports = React.createClass({ _launchManageIntegrations: function() { const IntegrationsManager = sdk.getComponent('views.settings.IntegrationsManager'); - this.scalarClient.connect().done(() => { - const src = (this.scalarClient !== null && this.scalarClient.hasCredentials()) ? - this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room, 'add_integ') : - null; - Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { - src: src, - }, 'mx_IntegrationsManager'); - }, (err) => { - console.error('Error ensuring a valid scalar_token exists', err); - }); + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + room: this.props.room, + screen: 'add_integ', + }, 'mx_IntegrationsManager'); }, onClickAddWidget: function(e) { From d58ab8e6d079b2a2f29c78b9a386cfdb56453491 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:50:09 -0600 Subject: [PATCH 08/12] Remove excessive scalar auth checks in manager util class --- src/IntegrationManager.js | 65 ++++++++++----------------------------- 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 9cd984f12f..7a9d336e97 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -22,55 +22,22 @@ import ScalarAuthClient from './ScalarAuthClient'; import RoomViewStore from './stores/RoomViewStore'; import MatrixClientPeg from "./MatrixClientPeg"; -if (!global.mxIntegrationManager) { - global.mxIntegrationManager = {}; -} - -// TODO: TravisR - What even is this? - +// TODO: We should use this everywhere. export default class IntegrationManager { - static _init() { - if (!global.mxIntegrationManager.client || !global.mxIntegrationManager.connected) { - if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { - ScalarMessaging.startListening(); - global.mxIntegrationManager.client = new ScalarAuthClient(); - - return global.mxIntegrationManager.client.connect().then(() => { - global.mxIntegrationManager.connected = true; - }).catch((e) => { - console.error("Failed to connect to integrations server", e); - global.mxIntegrationManager.error = e; - }); - } else { - console.error('Invalid integration manager config', SdkConfig.get()); - } + /** + * Launch the integrations manager on the specified integration page + * @param {string} integName integration / widget type + * @param {string} integId integration / widget ID + * @param {function} onFinished Callback to invoke on integration manager close + */ + static async open(integName, integId, onFinished) { + // The dialog will take care of scalar auth for us + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + room: MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), + screen: 'type_' + integName, + integrationId: integId, + onFinished: onFinished, + }, "mx_IntegrationsManager"); } - } - - /** - * Launch the integrations manager on the specified integration page - * @param {string} integName integration / widget type - * @param {string} integId integration / widget ID - * @param {function} onFinished Callback to invoke on integration manager close - */ - static async open(integName, integId, onFinished) { - await IntegrationManager._init(); - if (global.mxIntegrationManager.client) { - await global.mxIntegrationManager.client.connect(); - } else { - return; - } - const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - if (global.mxIntegrationManager.error || - !(global.mxIntegrationManager.client && global.mxIntegrationManager.client.hasCredentials())) { - console.error("Scalar error", global.mxIntegrationManager); - return; - } - Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { - room: MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), - screen: 'type_' + integName, - integrationId: integId, - onFinished: onFinished, - }, "mx_IntegrationsManager"); - } } From 8f6e8c1ec7dfe1ab5937ac5496a6506587e86c15 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:51:14 -0600 Subject: [PATCH 09/12] Appease the linter --- src/components/views/elements/AppTile.js | 2 +- src/components/views/elements/ManageIntegsButton.js | 3 +-- src/components/views/settings/IntegrationsManager.js | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 60bc8a337e..034a3318a5 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -245,7 +245,7 @@ export default class AppTile extends React.Component { Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { room: this.props.room, screen: 'type_' + this.props.type, - integrationId: this.props.id + integrationId: this.props.id, }, "mx_IntegrationsManager"); } } diff --git a/src/components/views/elements/ManageIntegsButton.js b/src/components/views/elements/ManageIntegsButton.js index f5d087e452..ef5604dba6 100644 --- a/src/components/views/elements/ManageIntegsButton.js +++ b/src/components/views/elements/ManageIntegsButton.js @@ -21,7 +21,6 @@ import sdk from '../../../index'; import ScalarAuthClient from '../../../ScalarAuthClient'; import Modal from "../../../Modal"; import { _t } from '../../../languageHandler'; -import AccessibleButton from './AccessibleButton'; export default class ManageIntegsButton extends React.Component { constructor(props) { @@ -47,7 +46,7 @@ export default class ManageIntegsButton extends React.Component { title={_t("Manage Integrations")} onClick={this.onManageIntegrations} /> - ) + ); } return integrationsButton; diff --git a/src/components/views/settings/IntegrationsManager.js b/src/components/views/settings/IntegrationsManager.js index d9bf6351e9..754693b73e 100644 --- a/src/components/views/settings/IntegrationsManager.js +++ b/src/components/views/settings/IntegrationsManager.js @@ -77,7 +77,7 @@ export default class IntegrationsManager extends React.Component { loading: false, connected: false, }); - }) + }); } componentDidMount() { @@ -135,4 +135,4 @@ export default class IntegrationsManager extends React.Component { return ; } -} \ No newline at end of file +} From d5db0077edf820717a6d9c74d55cd83130cc3218 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 17 Jun 2019 15:53:11 -0600 Subject: [PATCH 10/12] Remove unused imports --- src/IntegrationManager.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js index 7a9d336e97..7ff9aff86e 100644 --- a/src/IntegrationManager.js +++ b/src/IntegrationManager.js @@ -16,9 +16,6 @@ limitations under the License. */ import Modal from './Modal'; import sdk from './index'; -import SdkConfig from './SdkConfig'; -import ScalarMessaging from './ScalarMessaging'; -import ScalarAuthClient from './ScalarAuthClient'; import RoomViewStore from './stores/RoomViewStore'; import MatrixClientPeg from "./MatrixClientPeg"; From be37332bb07ef59822ba0c3fbe7444172db830c9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 18 Jun 2019 07:55:43 -0600 Subject: [PATCH 11/12] Further simplify usage of integrations --- src/FromWidgetPostMessageApi.js | 14 ++++++-- src/IntegrationManager.js | 40 --------------------- src/components/views/rooms/Stickerpicker.js | 4 +-- 3 files changed, 14 insertions(+), 44 deletions(-) delete mode 100644 src/IntegrationManager.js diff --git a/src/FromWidgetPostMessageApi.js b/src/FromWidgetPostMessageApi.js index 61c51d4a20..79e5206f50 100644 --- a/src/FromWidgetPostMessageApi.js +++ b/src/FromWidgetPostMessageApi.js @@ -17,9 +17,12 @@ limitations under the License. import URL from 'url'; import dis from './dispatcher'; -import IntegrationManager from './IntegrationManager'; import WidgetMessagingEndpoint from './WidgetMessagingEndpoint'; import ActiveWidgetStore from './stores/ActiveWidgetStore'; +import sdk from "./index"; +import Modal from "./Modal"; +import MatrixClientPeg from "./MatrixClientPeg"; +import RoomViewStore from "./stores/RoomViewStore"; const WIDGET_API_VERSION = '0.0.2'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ @@ -189,7 +192,14 @@ export default class FromWidgetPostMessageApi { const data = event.data.data || event.data.widgetData; const integType = (data && data.integType) ? data.integType : null; const integId = (data && data.integId) ? data.integId : null; - IntegrationManager.open(integType, integId); + + // The dialog will take care of scalar auth for us + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { + room: MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), + screen: 'type_' + integType, + integrationId: integId, + }, "mx_IntegrationsManager"); } else if (action === 'set_always_on_screen') { // This is a new message: there is no reason to support the deprecated widgetData here const data = event.data.data; diff --git a/src/IntegrationManager.js b/src/IntegrationManager.js deleted file mode 100644 index 7ff9aff86e..0000000000 --- a/src/IntegrationManager.js +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2017 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -import Modal from './Modal'; -import sdk from './index'; -import RoomViewStore from './stores/RoomViewStore'; -import MatrixClientPeg from "./MatrixClientPeg"; - -// TODO: We should use this everywhere. -export default class IntegrationManager { - /** - * Launch the integrations manager on the specified integration page - * @param {string} integName integration / widget type - * @param {string} integId integration / widget ID - * @param {function} onFinished Callback to invoke on integration manager close - */ - static async open(integName, integId, onFinished) { - // The dialog will take care of scalar auth for us - const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, { - room: MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), - screen: 'type_' + integName, - integrationId: integId, - onFinished: onFinished, - }, "mx_IntegrationsManager"); - } -} diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 809d948840..2dc174ceac 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -68,7 +68,7 @@ export default class Stickerpicker extends React.Component { _acquireScalarClient() { if (this.scalarClient) return Promise.resolve(this.scalarClient); - if (SdkConfig.get().integrations_ui_url && SdkConfig.get().integrations_rest_url) { + if (ScalarAuthClient.isPossible()) { this.scalarClient = new ScalarAuthClient(); return this.scalarClient.connect().then(() => { this.forceUpdate(); @@ -348,7 +348,7 @@ export default class Stickerpicker extends React.Component { /** * Launch the integrations manager on the stickers integration page */ - async _launchManageIntegrations() { + _launchManageIntegrations() { const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); // The integrations manager will handle scalar auth for us. From b6ca0ea6bf31f74a30ef031be9e1ac484854a7e3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 18 Jun 2019 08:01:38 -0600 Subject: [PATCH 12/12] Appease the linter --- src/components/views/rooms/Stickerpicker.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 2dc174ceac..6918810842 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -19,7 +19,6 @@ import AppTile from '../elements/AppTile'; import MatrixClientPeg from '../../../MatrixClientPeg'; import Modal from '../../../Modal'; import sdk from '../../../index'; -import SdkConfig from '../../../SdkConfig'; import ScalarAuthClient from '../../../ScalarAuthClient'; import dis from '../../../dispatcher'; import AccessibleButton from '../elements/AccessibleButton';