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",