From ffa49df8892fa5377312dce28adb721326a9009e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 9 Aug 2019 16:05:05 -0600 Subject: [PATCH 1/4] Refactor integration manager handling into a common place It was already in a common place, but this is the boilerplate for supporting multiple integration managers, and multiple integration manager sources. For https://github.com/vector-im/riot-web/issues/4913 / https://github.com/vector-im/riot-web/issues/10161 --- src/CallHandler.js | 22 +++-- src/FromWidgetPostMessageApi.js | 13 +-- src/ScalarAuthClient.js | 69 ++++++++++------ src/components/views/elements/AppTile.js | 31 ++++--- .../views/elements/ManageIntegsButton.js | 12 ++- src/components/views/messages/TextualBody.js | 13 ++- src/components/views/rooms/AppsDrawer.js | 7 +- src/components/views/rooms/Stickerpicker.js | 19 ++--- .../IntegrationManagerInstance.js | 81 +++++++++++++++++++ src/integrations/IntegrationManagers.js | 68 ++++++++++++++++ src/integrations/integrations.js | 79 ------------------ 11 files changed, 267 insertions(+), 147 deletions(-) create mode 100644 src/integrations/IntegrationManagerInstance.js create mode 100644 src/integrations/IntegrationManagers.js delete mode 100644 src/integrations/integrations.js diff --git a/src/CallHandler.js b/src/CallHandler.js index 5b58400ae65..8dfd283e60d 100644 --- a/src/CallHandler.js +++ b/src/CallHandler.js @@ -63,7 +63,7 @@ import SdkConfig from './SdkConfig'; import { showUnknownDeviceDialogForCalls } from './cryptodevices'; import WidgetUtils from './utils/WidgetUtils'; import WidgetEchoStore from './stores/WidgetEchoStore'; -import ScalarAuthClient from './ScalarAuthClient'; +import {IntegrationManagers} from "./integrations/IntegrationManagers"; global.mxCalls = { //room_id: MatrixCall @@ -348,14 +348,20 @@ async function _startCallApp(roomId, type) { // 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. - const scalarClient = new ScalarAuthClient(); - let haveScalar = false; - try { - await scalarClient.connect(); - haveScalar = scalarClient.hasCredentials(); - } catch (e) { - // fall through + const managers = IntegrationManagers.sharedInstance(); + let haveScalar = true; + if (managers.hasManager()) { + try { + const scalarClient = managers.getPrimaryManager().getScalarClient(); + await scalarClient.connect(); + haveScalar = scalarClient.hasCredentials(); + } catch (e) { + // ignore + } + } else { + haveScalar = false; } + if (!haveScalar) { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); diff --git a/src/FromWidgetPostMessageApi.js b/src/FromWidgetPostMessageApi.js index d34e3d8ed0e..b2bd579b743 100644 --- a/src/FromWidgetPostMessageApi.js +++ b/src/FromWidgetPostMessageApi.js @@ -22,7 +22,7 @@ import WidgetMessagingEndpoint from './WidgetMessagingEndpoint'; import ActiveWidgetStore from './stores/ActiveWidgetStore'; import MatrixClientPeg from "./MatrixClientPeg"; import RoomViewStore from "./stores/RoomViewStore"; -import { showIntegrationsManager } from './integrations/integrations'; +import {IntegrationManagers} from "./integrations/IntegrationManagers"; const WIDGET_API_VERSION = '0.0.2'; // Current API version const SUPPORTED_WIDGET_API_VERSIONS = [ @@ -193,11 +193,12 @@ export default class FromWidgetPostMessageApi { const integType = (data && data.integType) ? data.integType : null; const integId = (data && data.integId) ? data.integId : null; - showIntegrationsManager({ - room: MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), - screen: 'type_' + integType, - integrationId: integId, - }); + // TODO: Open the right integration manager for the widget + IntegrationManagers.sharedInstance().getPrimaryManager().open( + MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), + `type_${integType}`, + integId, + ); } 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/ScalarAuthClient.js b/src/ScalarAuthClient.js index c268fbe3fba..3623d47f8e1 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.js @@ -29,20 +29,43 @@ import * as Matrix from 'matrix-js-sdk'; // The version of the integration manager API we're intending to work with const imApiVersion = "1.1"; -class ScalarAuthClient { - constructor() { +export default class ScalarAuthClient { + constructor(apiUrl, uiUrl) { + this.apiUrl = apiUrl; + this.uiUrl = uiUrl; this.scalarToken = null; // `undefined` to allow `startTermsFlow` to fallback to a default // callback if this is unset. this.termsInteractionCallback = undefined; + + // We try and store the token on a per-manager basis, but need a fallback + // for the default manager. + const configApiUrl = SdkConfig.get()['integrations_rest_url']; + const configUiUrl = SdkConfig.get()['integrations_ui_url']; + this.isDefaultManager = apiUrl === configApiUrl && configUiUrl === uiUrl; } - /** - * 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']; + _writeTokenToStore() { + window.localStorage.setItem("mx_scalar_token_at_" + this.apiUrl, this.scalarToken); + if (this.isDefaultManager) { + // We remove the old token from storage to migrate upwards. This is safe + // to do because even if the user switches to /app when this is on /develop + // they'll at worst register for a new token. + window.localStorage.removeItem("mx_scalar_token"); // no-op when not present + } + } + + _readTokenFromStore() { + let token = window.localStorage.getItem("mx_scalar_token_at_" + this.apiUrl); + if (!token && this.isDefaultManager) { + token = window.localStorage.getItem("mx_scalar_token"); + } + return token; + } + + _readToken() { + if (this.scalarToken) return this.scalarToken; + return this._readTokenFromStore(); } setTermsInteractionCallback(callback) { @@ -61,8 +84,7 @@ class ScalarAuthClient { // Returns a promise that resolves to a scalar_token string getScalarToken() { - let token = this.scalarToken; - if (!token) token = window.localStorage.getItem("mx_scalar_token"); + const token = this._readToken(); if (!token) { return this.registerForToken(); @@ -78,7 +100,7 @@ class ScalarAuthClient { } _getAccountName(token) { - const url = SdkConfig.get().integrations_rest_url + "/account"; + const url = this.apiUrl + "/account"; return new Promise(function(resolve, reject) { request({ @@ -111,7 +133,7 @@ class ScalarAuthClient { return token; }).catch((e) => { if (e instanceof TermsNotSignedError) { - console.log("Integrations manager requires new terms to be agreed to"); + console.log("Integration manager requires new terms to be agreed to"); // The terms endpoints are new and so live on standard _matrix prefixes, // but IM rest urls are currently configured with paths, so remove the // path from the base URL before passing it to the js-sdk @@ -126,7 +148,7 @@ class ScalarAuthClient { // Once we've fully transitioned to _matrix URLs, we can give people // a grace period to update their configs, then use the rest url as // a regular base url. - const parsedImRestUrl = url.parse(SdkConfig.get().integrations_rest_url); + const parsedImRestUrl = url.parse(this.apiUrl); parsedImRestUrl.path = ''; parsedImRestUrl.pathname = ''; return startTermsFlow([new Service( @@ -147,17 +169,18 @@ class ScalarAuthClient { return MatrixClientPeg.get().getOpenIdToken().then((tokenObject) => { // Now we can send that to scalar and exchange it for a scalar token return this.exchangeForScalarToken(tokenObject); - }).then((tokenObject) => { + }).then((token) => { // Validate it (this mostly checks to see if the IM needs us to agree to some terms) - return this._checkToken(tokenObject); - }).then((tokenObject) => { - window.localStorage.setItem("mx_scalar_token", tokenObject); - return tokenObject; + return this._checkToken(token); + }).then((token) => { + this.scalarToken = token; + this._writeTokenToStore(); + return token; }); } exchangeForScalarToken(openidTokenObject) { - const scalarRestUrl = SdkConfig.get().integrations_rest_url; + const scalarRestUrl = this.apiUrl; return new Promise(function(resolve, reject) { request({ @@ -181,7 +204,7 @@ class ScalarAuthClient { } getScalarPageTitle(url) { - let scalarPageLookupUrl = SdkConfig.get().integrations_rest_url + '/widgets/title_lookup'; + let scalarPageLookupUrl = this.apiUrl + '/widgets/title_lookup'; scalarPageLookupUrl = this.getStarterLink(scalarPageLookupUrl); scalarPageLookupUrl += '&curl=' + encodeURIComponent(url); @@ -217,7 +240,7 @@ class ScalarAuthClient { * @return {Promise} Resolves on completion */ disableWidgetAssets(widgetType, widgetId) { - let url = SdkConfig.get().integrations_rest_url + '/widgets/set_assets_state'; + let url = this.apiUrl + '/widgets/set_assets_state'; url = this.getStarterLink(url); return new Promise((resolve, reject) => { request({ @@ -246,7 +269,7 @@ class ScalarAuthClient { getScalarInterfaceUrlForRoom(room, screen, id) { const roomId = room.roomId; const roomName = room.name; - let url = SdkConfig.get().integrations_ui_url; + let url = this.uiUrl; url += "?scalar_token=" + encodeURIComponent(this.scalarToken); url += "&room_id=" + encodeURIComponent(roomId); url += "&room_name=" + encodeURIComponent(roomName); @@ -264,5 +287,3 @@ class ScalarAuthClient { return starterLinkUrl + "?scalar_token=" + encodeURIComponent(this.scalarToken); } } - -module.exports = ScalarAuthClient; diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 38830d78f26..82953cf52e3 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -22,7 +22,6 @@ import qs from 'querystring'; import React from 'react'; import PropTypes from 'prop-types'; import MatrixClientPeg from '../../../MatrixClientPeg'; -import ScalarAuthClient from '../../../ScalarAuthClient'; import WidgetMessaging from '../../../WidgetMessaging'; import AccessibleButton from './AccessibleButton'; import Modal from '../../../Modal'; @@ -35,7 +34,7 @@ import WidgetUtils from '../../../utils/WidgetUtils'; import dis from '../../../dispatcher'; import ActiveWidgetStore from '../../../stores/ActiveWidgetStore'; import classNames from 'classnames'; -import { showIntegrationsManager } from '../../../integrations/integrations'; +import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; const ALLOWED_APP_URL_SCHEMES = ['https:', 'http:']; const ENABLE_REACT_PERF = false; @@ -178,9 +177,22 @@ export default class AppTile extends React.Component { return; } + const managers = IntegrationManagers.sharedInstance(); + if (!managers.hasManager()) { + console.warn("No integration manager - not setting scalar token", url); + this.setState({ + error: null, + widgetUrl: this._addWurlParams(this.props.url), + initialising: false, + }); + return; + } + + // TODO: Pick the right manager for the widget + // Fetch the token before loading the iframe as we need it to mangle the URL if (!this._scalarClient) { - this._scalarClient = new ScalarAuthClient(); + this._scalarClient = managers.getPrimaryManager().getScalarClient(); } this._scalarClient.getScalarToken().done((token) => { // Append scalar_token as a query param if not already present @@ -189,7 +201,7 @@ export default class AppTile extends React.Component { const params = qs.parse(u.query); if (!params.scalar_token) { params.scalar_token = encodeURIComponent(token); - // u.search must be set to undefined, so that u.format() uses query paramerters - https://nodejs.org/docs/latest/api/url.html#url_url_format_url_options + // u.search must be set to undefined, so that u.format() uses query parameters - https://nodejs.org/docs/latest/api/url.html#url_url_format_url_options u.search = undefined; u.query = params; } @@ -251,11 +263,12 @@ export default class AppTile extends React.Component { if (this.props.onEditClick) { this.props.onEditClick(); } else { - showIntegrationsManager({ - room: this.props.room, - screen: 'type_' + this.props.type, - integrationId: this.props.id, - }); + // TODO: Open the right manager for the widget + IntegrationManagers.sharedInstance().getPrimaryManager().open( + this.props.room, + this.props.type, + this.props.id, + ); } } diff --git a/src/components/views/elements/ManageIntegsButton.js b/src/components/views/elements/ManageIntegsButton.js index f5b6d75d6c5..ca7391329fc 100644 --- a/src/components/views/elements/ManageIntegsButton.js +++ b/src/components/views/elements/ManageIntegsButton.js @@ -18,9 +18,8 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import sdk from '../../../index'; -import ScalarAuthClient from '../../../ScalarAuthClient'; import { _t } from '../../../languageHandler'; -import { showIntegrationsManager } from '../../../integrations/integrations'; +import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; export default class ManageIntegsButton extends React.Component { constructor(props) { @@ -30,12 +29,17 @@ export default class ManageIntegsButton extends React.Component { onManageIntegrations = (ev) => { ev.preventDefault(); - showIntegrationsManager({ room: this.props.room }); + const managers = IntegrationManagers.sharedInstance(); + if (!managers.hasManager()) { + managers.openNoManagerDialog(); + } else { + managers.getPrimaryManager().open(this.props.room); + } }; render() { let integrationsButton =
; - if (ScalarAuthClient.isPossible()) { + if (IntegrationManagers.sharedInstance().hasManager()) { const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); integrationsButton = ( { const completeUrl = scalarClient.getStarterLink(starterLink); const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - const integrationsUrl = SdkConfig.get().integrations_ui_url; + const integrationsUrl = integrationManager.uiUrl; Modal.createTrackedDialog('Add an integration', '', QuestionDialog, { title: _t("Add an Integration"), description: diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 2e9d3e50713..4d2c1e03806 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -29,7 +29,7 @@ import { _t } from '../../../languageHandler'; import WidgetUtils from '../../../utils/WidgetUtils'; import WidgetEchoStore from "../../../stores/WidgetEchoStore"; import AccessibleButton from '../elements/AccessibleButton'; -import { showIntegrationsManager } from '../../../integrations/integrations'; +import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; // The maximum number of widgets that can be added in a room const MAX_WIDGETS = 2; @@ -128,10 +128,7 @@ module.exports = React.createClass({ }, _launchManageIntegrations: function() { - showIntegrationsManager({ - room: this.props.room, - screen: 'add_integ', - }); + IntegrationManagers.sharedInstance().getPrimaryManager().open(this.props.room, 'add_integ'); }, onClickAddWidget: function(e) { diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index 6c483519927..2d3508c4044 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -18,13 +18,12 @@ import {_t, _td} from '../../../languageHandler'; import AppTile from '../elements/AppTile'; import MatrixClientPeg from '../../../MatrixClientPeg'; import sdk from '../../../index'; -import ScalarAuthClient from '../../../ScalarAuthClient'; import dis from '../../../dispatcher'; import AccessibleButton from '../elements/AccessibleButton'; import WidgetUtils from '../../../utils/WidgetUtils'; import ActiveWidgetStore from '../../../stores/ActiveWidgetStore'; import PersistedElement from "../elements/PersistedElement"; -import { showIntegrationsManager } from '../../../integrations/integrations'; +import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; const widgetType = 'm.stickerpicker'; @@ -67,8 +66,9 @@ export default class Stickerpicker extends React.Component { _acquireScalarClient() { if (this.scalarClient) return Promise.resolve(this.scalarClient); - if (ScalarAuthClient.isPossible()) { - this.scalarClient = new ScalarAuthClient(); + // TODO: Pick the right manager for the widget + if (IntegrationManagers.sharedInstance().hasManager()) { + this.scalarClient = IntegrationManagers.sharedInstance().getPrimaryManager().getScalarClient(); return this.scalarClient.connect().then(() => { this.forceUpdate(); return this.scalarClient; @@ -348,11 +348,12 @@ export default class Stickerpicker extends React.Component { * Launch the integrations manager on the stickers integration page */ _launchManageIntegrations() { - showIntegrationsManager({ - room: this.props.room, - screen: `type_${widgetType}`, - integrationId: this.state.widgetId, - }); + // TODO: Open the right integration manager for the widget + IntegrationManagers.sharedInstance().getPrimaryManager().open( + this.props.room, + `type_${widgetType}`, + this.state.widgetId, + ); } render() { diff --git a/src/integrations/IntegrationManagerInstance.js b/src/integrations/IntegrationManagerInstance.js new file mode 100644 index 00000000000..b5f6e4f2a80 --- /dev/null +++ b/src/integrations/IntegrationManagerInstance.js @@ -0,0 +1,81 @@ +/* +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 ScalarAuthClient from "../ScalarAuthClient"; +import sdk from "../index"; +import {dialogTermsInteractionCallback, TermsNotSignedError} from "../Terms"; +import type {Room} from "matrix-js-sdk"; +import Modal from '../Modal'; + +export class IntegrationManagerInstance { + apiUrl: string; + uiUrl: string; + + constructor(apiUrl: string, uiUrl: string) { + this.apiUrl = apiUrl; + this.uiUrl = uiUrl; + + // Per the spec: UI URL is optional. + if (!this.uiUrl) this.uiUrl = this.apiUrl; + } + + getScalarClient(): ScalarAuthClient { + return new ScalarAuthClient(this.apiUrl, this.uiUrl); + } + + async open(room: Room = null, screen: string = null, integrationId: string = null): void { + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + const dialog = Modal.createTrackedDialog( + 'Integration Manager', '', IntegrationsManager, + {loading: true}, 'mx_IntegrationsManager', + ); + + const client = this.getScalarClient(); + client.setTermsInteractionCallback((policyInfo, agreedUrls) => { + // To avoid visual glitching of two modals stacking briefly, we customise the + // terms dialog sizing when it will appear for the integrations manager so that + // it gets the same basic size as the IM's own modal. + return dialogTermsInteractionCallback( + policyInfo, agreedUrls, 'mx_TermsDialog_forIntegrationsManager', + ); + }); + + let newProps = {}; + try { + await client.connect(); + if (!client.hasCredentials()) { + newProps["connected"] = false; + } else { + newProps["url"] = client.getScalarInterfaceUrlForRoom(room, screen, integrationId); + } + } catch (e) { + if (e instanceof TermsNotSignedError) { + dialog.close(); + return; + } + + console.error(e); + props["connected"] = false; + } + + // Close the old dialog and open a new one + dialog.close(); + Modal.createTrackedDialog( + 'Integration Manager', '', IntegrationsManager, + newProps, 'mx_IntegrationsManager', + ); + } +} \ No newline at end of file diff --git a/src/integrations/IntegrationManagers.js b/src/integrations/IntegrationManagers.js new file mode 100644 index 00000000000..9df5d80ee1e --- /dev/null +++ b/src/integrations/IntegrationManagers.js @@ -0,0 +1,68 @@ +/* +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 SdkConfig from '../SdkConfig'; +import sdk from "../index"; +import Modal from '../Modal'; +import {IntegrationManagerInstance} from "./IntegrationManagerInstance"; + +export class IntegrationManagers { + static _instance; + + static sharedInstance(): IntegrationManagers { + if (!IntegrationManagers._instance) { + IntegrationManagers._instance = new IntegrationManagers(); + } + return IntegrationManagers._instance; + } + + _managers: IntegrationManagerInstance[] = []; + + constructor() { + this._setupConfiguredManager(); + } + + _setupConfiguredManager() { + const apiUrl = SdkConfig.get()['integrations_rest_url']; + const uiUrl = SdkConfig.get()['integrations_ui_url']; + + if (apiUrl && uiUrl) { + this._managers.push(new IntegrationManagerInstance(apiUrl, uiUrl)); + } + } + + hasManager(): boolean { + return this._managers.length > 0; + } + + getPrimaryManager(): IntegrationManagerInstance { + if (this.hasManager()) { + // TODO: TravisR - Handle custom integration managers (widgets) + return this._managers[0]; + } else { + return null; + } + } + + openNoManagerDialog(): void { + // TODO: Is it Integrations (plural) or Integration (singular). Singular is easier spoken. + const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); + Modal.createTrackedDialog( + "Integration Manager", "None", IntegrationsManager, + {configured: false}, 'mx_IntegrationsManager', + ); + } +} diff --git a/src/integrations/integrations.js b/src/integrations/integrations.js deleted file mode 100644 index dad6cbf3e89..00000000000 --- a/src/integrations/integrations.js +++ /dev/null @@ -1,79 +0,0 @@ -/* -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 sdk from "../index"; -import ScalarAuthClient from '../ScalarAuthClient'; -import Modal from '../Modal'; -import { TermsNotSignedError, dialogTermsInteractionCallback } from '../Terms'; - -export async function showIntegrationsManager(opts) { - const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager"); - - let props = {}; - if (ScalarAuthClient.isPossible()) { - props.loading = true; - } else { - props.configured = false; - } - - const close = Modal.createTrackedDialog( - 'Integrations Manager', '', IntegrationsManager, props, "mx_IntegrationsManager", - ).close; - - if (!ScalarAuthClient.isPossible()) { - return; - } - - const scalarClient = new ScalarAuthClient(); - scalarClient.setTermsInteractionCallback(integrationsTermsInteractionCallback); - try { - await scalarClient.connect(); - if (!scalarClient.hasCredentials()) { - props = { connected: false }; - } else { - props = { - url: scalarClient.getScalarInterfaceUrlForRoom( - opts.room, - opts.screen, - opts.integrationId, - ), - }; - } - } catch (err) { - if (err instanceof TermsNotSignedError) { - // user canceled terms dialog, so just cancel the action - close(); - return; - } - console.error(err); - props = { connected: false }; - } - close(); - Modal.createTrackedDialog('Integrations Manager', '', IntegrationsManager, props, "mx_IntegrationsManager"); -} - -/* - * To avoid visual glitching of two modals stacking briefly, we customise the - * terms dialog sizing when it will appear for the integrations manager so that - * it gets the same basic size as the IM's own modal. - */ -function integrationsTermsInteractionCallback(policiesAndServicePairs, agreedUrls) { - return dialogTermsInteractionCallback( - policiesAndServicePairs, - agreedUrls, - "mx_TermsDialog_forIntegrationsManager", - ); -} From 5a15e78fe46bd05d11f10ba1798030f03effb6fc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 9 Aug 2019 16:14:36 -0600 Subject: [PATCH 2/4] Appease the linter --- src/integrations/IntegrationManagerInstance.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/integrations/IntegrationManagerInstance.js b/src/integrations/IntegrationManagerInstance.js index b5f6e4f2a80..4d0181f0178 100644 --- a/src/integrations/IntegrationManagerInstance.js +++ b/src/integrations/IntegrationManagerInstance.js @@ -53,7 +53,7 @@ export class IntegrationManagerInstance { ); }); - let newProps = {}; + const newProps = {}; try { await client.connect(); if (!client.hasCredentials()) { @@ -68,7 +68,7 @@ export class IntegrationManagerInstance { } console.error(e); - props["connected"] = false; + newProps["connected"] = false; } // Close the old dialog and open a new one @@ -78,4 +78,4 @@ export class IntegrationManagerInstance { newProps, 'mx_IntegrationsManager', ); } -} \ No newline at end of file +} From 018b4f5d41d4b5c324d9b7fc5de9f41b191a7805 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 9 Aug 2019 17:08:26 -0600 Subject: [PATCH 3/4] Use the default integration manager for config options --- src/CallHandler.js | 3 ++- src/ScalarMessaging.js | 4 +++- src/utils/WidgetUtils.js | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/CallHandler.js b/src/CallHandler.js index 8dfd283e60d..40a8d426f80 100644 --- a/src/CallHandler.js +++ b/src/CallHandler.js @@ -427,7 +427,8 @@ async function _startCallApp(roomId, type) { // URL, but this will at least allow the integration manager to not be hardcoded. widgetUrl = SdkConfig.get().integrations_jitsi_widget_url + '?' + queryString; } else { - widgetUrl = SdkConfig.get().integrations_rest_url + '/widgets/jitsi.html?' + queryString; + const apiUrl = IntegrationManagers.sharedInstance().getPrimaryManager().apiUrl; + widgetUrl = apiUrl + '/widgets/jitsi.html?' + queryString; } const widgetData = { widgetSessionId }; diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 8b87650929f..5d3b3ae506a 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -239,6 +239,7 @@ import dis from './dispatcher'; import WidgetUtils from './utils/WidgetUtils'; import RoomViewStore from './stores/RoomViewStore'; import { _t } from './languageHandler'; +import {IntegrationManagers} from "./integrations/IntegrationManagers"; function sendResponse(event, res) { const data = JSON.parse(JSON.stringify(event.data)); @@ -548,7 +549,8 @@ const onMessage = function(event) { // (See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) let configUrl; try { - configUrl = new URL(SdkConfig.get().integrations_ui_url); + // TODO: Support multiple integration managers + configUrl = new URL(IntegrationManagers.sharedInstance().getPrimaryManager().uiUrl); } catch (e) { // No integrations UI URL, ignore silently. return; diff --git a/src/utils/WidgetUtils.js b/src/utils/WidgetUtils.js index 41a241c905f..5e127e48d54 100644 --- a/src/utils/WidgetUtils.js +++ b/src/utils/WidgetUtils.js @@ -27,6 +27,7 @@ import WidgetEchoStore from '../stores/WidgetEchoStore'; const WIDGET_WAIT_TIME = 20000; import SettingsStore from "../settings/SettingsStore"; import ActiveWidgetStore from "../stores/ActiveWidgetStore"; +import {IntegrationManagers} from "../integrations/IntegrationManagers"; /** * Encodes a URI according to a set of template variables. Variables will be @@ -102,7 +103,8 @@ export default class WidgetUtils { let scalarUrls = SdkConfig.get().integrations_widgets_urls; if (!scalarUrls || scalarUrls.length === 0) { - scalarUrls = [SdkConfig.get().integrations_rest_url]; + const defaultManager = IntegrationManagers.sharedInstance().getPrimaryManager(); + if (defaultManager) scalarUrls = [defaultManager.apiUrl]; } for (let i = 0; i < scalarUrls.length; i++) { From 3a4c6f3eac97ea16d0cafe479384630423e17df1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 9 Aug 2019 17:20:37 -0600 Subject: [PATCH 4/4] Appease the linter again --- src/ScalarMessaging.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 5d3b3ae506a..0d61755519e 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -232,7 +232,6 @@ Example: } */ -import SdkConfig from './SdkConfig'; import MatrixClientPeg from './MatrixClientPeg'; import { MatrixEvent } from 'matrix-js-sdk'; import dis from './dispatcher';