mirror of
https://github.com/element-hq/element-web
synced 2024-11-23 17:56:01 +03:00
Merge pull request #437 from matrix-org/kegan/starter-links
Implement starter link support
This commit is contained in:
commit
6e2fd85760
3 changed files with 113 additions and 32 deletions
|
@ -18,9 +18,41 @@ var q = require("q");
|
||||||
var request = require('browser-request');
|
var request = require('browser-request');
|
||||||
|
|
||||||
var SdkConfig = require('./SdkConfig');
|
var SdkConfig = require('./SdkConfig');
|
||||||
|
var MatrixClientPeg = require('./MatrixClientPeg');
|
||||||
|
|
||||||
class ScalarAuthClient {
|
class ScalarAuthClient {
|
||||||
getScalarToken(openid_token_object) {
|
|
||||||
|
constructor() {
|
||||||
|
this.scalarToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
return this.getScalarToken().then((tok) => {
|
||||||
|
this.scalarToken = tok;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
hasCredentials() {
|
||||||
|
return this.scalarToken != null; // undef or null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a scalar_token string
|
||||||
|
getScalarToken() {
|
||||||
|
var tok = window.localStorage.getItem("mx_scalar_token");
|
||||||
|
if (tok) return q(tok);
|
||||||
|
|
||||||
|
// No saved token, so do the dance to get one. First, we
|
||||||
|
// need an openid bearer token from the HS.
|
||||||
|
return MatrixClientPeg.get().getOpenIdToken().then((token_object) => {
|
||||||
|
// Now we can send that to scalar and exchange it for a scalar token
|
||||||
|
return this.exchangeForScalarToken(token_object);
|
||||||
|
}).then((token_object) => {
|
||||||
|
window.localStorage.setItem("mx_scalar_token", token_object);
|
||||||
|
return token_object;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exchangeForScalarToken(openid_token_object) {
|
||||||
var defer = q.defer();
|
var defer = q.defer();
|
||||||
|
|
||||||
var scalar_rest_url = SdkConfig.get().integrations_rest_url;
|
var scalar_rest_url = SdkConfig.get().integrations_rest_url;
|
||||||
|
@ -43,6 +75,17 @@ class ScalarAuthClient {
|
||||||
|
|
||||||
return defer.promise;
|
return defer.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getScalarInterfaceUrlForRoom(roomId) {
|
||||||
|
var url = SdkConfig.get().integrations_ui_url;
|
||||||
|
url += "?scalar_token=" + encodeURIComponent(this.scalarToken);
|
||||||
|
url += "&room_id=" + encodeURIComponent(roomId);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStarterLink(starterLinkUrl) {
|
||||||
|
return starterLinkUrl + "?scalar_token=" + encodeURIComponent(this.scalarToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ScalarAuthClient;
|
module.exports = ScalarAuthClient;
|
||||||
|
|
|
@ -23,6 +23,10 @@ var linkify = require('linkifyjs');
|
||||||
var linkifyElement = require('linkifyjs/element');
|
var linkifyElement = require('linkifyjs/element');
|
||||||
var linkifyMatrix = require('../../../linkify-matrix');
|
var linkifyMatrix = require('../../../linkify-matrix');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
|
var ScalarAuthClient = require("../../../ScalarAuthClient");
|
||||||
|
var Modal = require("../../../Modal");
|
||||||
|
var SdkConfig = require('../../../SdkConfig');
|
||||||
|
var UserSettingsStore = require('../../../UserSettingsStore');
|
||||||
|
|
||||||
linkifyMatrix(linkify);
|
linkifyMatrix(linkify);
|
||||||
|
|
||||||
|
@ -176,15 +180,66 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onStarterLinkClick: function(starterLink, ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
// We need to add on our scalar token to the starter link, but we may not have one!
|
||||||
|
// In addition, we can't fetch one on click and then go to it immediately as that
|
||||||
|
// is then treated as a popup!
|
||||||
|
// We can get around this by fetching one now and showing a "confirmation dialog" (hurr hurr)
|
||||||
|
// which requires the user to click through and THEN we can open the link in a new tab because
|
||||||
|
// the window.open command occurs in the same stack frame as the onClick callback.
|
||||||
|
|
||||||
|
let integrationsEnabled = UserSettingsStore.isFeatureEnabled("integration_management");
|
||||||
|
if (!integrationsEnabled) {
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Integrations disabled",
|
||||||
|
description: "You need to enable the Labs option 'Integrations Management' in your Vector user settings first.",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go fetch a scalar token
|
||||||
|
let scalarClient = new ScalarAuthClient();
|
||||||
|
scalarClient.connect().then(() => {
|
||||||
|
let completeUrl = scalarClient.getStarterLink(starterLink);
|
||||||
|
let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
|
let integrationsUrl = SdkConfig.get().integrations_ui_url;
|
||||||
|
Modal.createDialog(QuestionDialog, {
|
||||||
|
title: "Add an Integration",
|
||||||
|
description:
|
||||||
|
<div>
|
||||||
|
You are about to taken to a third-party site so you can authenticate your account for use with {integrationsUrl}.<br/>
|
||||||
|
Do you wish to continue?
|
||||||
|
</div>,
|
||||||
|
button: "Continue",
|
||||||
|
onFinished: function(confirmed) {
|
||||||
|
if (!confirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let width = window.screen.width > 1024 ? 1024 : window.screen.width;
|
||||||
|
let height = window.screen.height > 800 ? 800 : window.screen.height;
|
||||||
|
let left = (window.screen.width - width) / 2;
|
||||||
|
let top = (window.screen.height - height) / 2;
|
||||||
|
window.open(completeUrl, '_blank', `height=${height}, width=${width}, top=${top}, left=${left},`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||||
var mxEvent = this.props.mxEvent;
|
var mxEvent = this.props.mxEvent;
|
||||||
var content = mxEvent.getContent();
|
var content = mxEvent.getContent();
|
||||||
|
|
||||||
var body = HtmlUtils.bodyToHtml(content, this.props.highlights, {});
|
var body = HtmlUtils.bodyToHtml(content, this.props.highlights, {});
|
||||||
|
|
||||||
if (this.props.highlightLink) {
|
if (this.props.highlightLink) {
|
||||||
body = <a href={ this.props.highlightLink }>{ body }</a>;
|
body = <a href={ this.props.highlightLink }>{ body }</a>;
|
||||||
}
|
}
|
||||||
|
else if (content.data && typeof content.data["org.matrix.neb.starter_link"] === "string") {
|
||||||
|
body = <a href="#" onClick={ this.onStarterLinkClick.bind(this, content.data["org.matrix.neb.starter_link"]) }>{ body }</a>;
|
||||||
|
}
|
||||||
|
|
||||||
var widgets;
|
var widgets;
|
||||||
if (this.state.links.length && !this.state.widgetHidden && this.props.showUrlPreview) {
|
if (this.state.links.length && !this.state.widgetHidden && this.props.showUrlPreview) {
|
||||||
|
|
|
@ -65,7 +65,6 @@ module.exports = React.createClass({
|
||||||
// Default to false if it's undefined, otherwise react complains about changing
|
// Default to false if it's undefined, otherwise react complains about changing
|
||||||
// components from uncontrolled to controlled
|
// components from uncontrolled to controlled
|
||||||
isRoomPublished: this._originalIsRoomPublished || false,
|
isRoomPublished: this._originalIsRoomPublished || false,
|
||||||
scalar_token: null,
|
|
||||||
scalar_error: null,
|
scalar_error: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -81,11 +80,16 @@ module.exports = React.createClass({
|
||||||
console.error("Failed to get room visibility: " + err);
|
console.error("Failed to get room visibility: " + err);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getScalarToken().done((token) => {
|
if (UserSettingsStore.isFeatureEnabled("integration_management")) {
|
||||||
this.setState({scalar_token: token});
|
this.scalarClient = new ScalarAuthClient();
|
||||||
|
this.scalarClient.connect().done(() => {
|
||||||
|
this.forceUpdate();
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
this.setState({scalar_error: err});
|
this.setState({
|
||||||
|
scalar_error: err
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'ui_opacity',
|
action: 'ui_opacity',
|
||||||
|
@ -395,34 +399,13 @@ module.exports = React.createClass({
|
||||||
roomState.mayClientSendStateEvent("m.room.guest_access", cli))
|
roomState.mayClientSendStateEvent("m.room.guest_access", cli))
|
||||||
},
|
},
|
||||||
|
|
||||||
getScalarInterfaceUrl: function() {
|
|
||||||
var url = SdkConfig.get().integrations_ui_url;
|
|
||||||
url += "?scalar_token=" + encodeURIComponent(this.state.scalar_token);
|
|
||||||
url += "&room_id=" + encodeURIComponent(this.props.room.roomId);
|
|
||||||
return url;
|
|
||||||
},
|
|
||||||
|
|
||||||
getScalarToken() {
|
|
||||||
var tok = window.localStorage.getItem("mx_scalar_token");
|
|
||||||
if (tok) return q(tok);
|
|
||||||
|
|
||||||
// No saved token, so do the dance to get one. First, we
|
|
||||||
// need an openid bearer token from the HS.
|
|
||||||
return MatrixClientPeg.get().getOpenIdToken().then((token_object) => {
|
|
||||||
// Now we can send that to scalar and exchange it for a scalar token
|
|
||||||
var scalar_auth_client = new ScalarAuthClient();
|
|
||||||
return scalar_auth_client.getScalarToken(token_object);
|
|
||||||
}).then((token_object) => {
|
|
||||||
window.localStorage.setItem("mx_scalar_token", token_object);
|
|
||||||
return token_object;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onManageIntegrations(ev) {
|
onManageIntegrations(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
var IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
var IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
||||||
Modal.createDialog(IntegrationsManager, {
|
Modal.createDialog(IntegrationsManager, {
|
||||||
src: this.state.scalar_token ? this.getScalarInterfaceUrl() : null
|
src: this.scalarClient.hasCredentials() ?
|
||||||
|
this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId) :
|
||||||
|
null
|
||||||
}, "");
|
}, "");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -649,7 +632,7 @@ module.exports = React.createClass({
|
||||||
if (UserSettingsStore.isFeatureEnabled("integration_management")) {
|
if (UserSettingsStore.isFeatureEnabled("integration_management")) {
|
||||||
let integrations_body;
|
let integrations_body;
|
||||||
|
|
||||||
if (this.state.scalar_token) {
|
if (this.scalarClient.hasCredentials()) {
|
||||||
integrations_body = (
|
integrations_body = (
|
||||||
<div className="mx_RoomSettings_settings">
|
<div className="mx_RoomSettings_settings">
|
||||||
<a href="#" onClick={ this.onManageIntegrations }>Manage integrations</a>
|
<a href="#" onClick={ this.onManageIntegrations }>Manage integrations</a>
|
||||||
|
|
Loading…
Reference in a new issue