mirror of https://github.com/vector-im/riot-web
				
				
				
			Merge pull request #3242 from matrix-org/jryans/terms-modal
Avoid visual glitch when terms appear for Integration Managerpull/21833/head
						commit
						a5ac50f90f
					
				| 
						 | 
				
			
			@ -14,6 +14,17 @@ See the License for the specific language governing permissions and
 | 
			
		|||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
.mx_TermsDialog_forIntegrationsManager .mx_Dialog {
 | 
			
		||||
    width: 60%;
 | 
			
		||||
    height: 70%;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_TermsDialog_termsTableHeader {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    text-align: left;
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +32,7 @@ limitations under the License.
 | 
			
		|||
 | 
			
		||||
.mx_TermsDialog_termsTable {
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_TermsDialog_service, .mx_TermsDialog_summary {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ limitations under the License.
 | 
			
		|||
import url from 'url';
 | 
			
		||||
import Promise from 'bluebird';
 | 
			
		||||
import SettingsStore from "./settings/SettingsStore";
 | 
			
		||||
import { Service, presentTermsForServices, TermsNotSignedError } from './Terms';
 | 
			
		||||
import { Service, startTermsFlow, TermsNotSignedError } from './Terms';
 | 
			
		||||
const request = require('browser-request');
 | 
			
		||||
 | 
			
		||||
const SdkConfig = require('./SdkConfig');
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +32,9 @@ const imApiVersion = "1.1";
 | 
			
		|||
class ScalarAuthClient {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.scalarToken = null;
 | 
			
		||||
        // `undefined` to allow `startTermsFlow` to fallback to a default
 | 
			
		||||
        // callback if this is unset.
 | 
			
		||||
        this.termsInteractionCallback = undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +45,10 @@ class ScalarAuthClient {
 | 
			
		|||
        return SdkConfig.get()['integrations_rest_url'] && SdkConfig.get()['integrations_ui_url'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setTermsInteractionCallback(callback) {
 | 
			
		||||
        this.termsInteractionCallback = callback;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    connect() {
 | 
			
		||||
        return this.getScalarToken().then((tok) => {
 | 
			
		||||
            this.scalarToken = tok;
 | 
			
		||||
| 
						 | 
				
			
			@ -122,11 +129,11 @@ class ScalarAuthClient {
 | 
			
		|||
                const parsedImRestUrl = url.parse(SdkConfig.get().integrations_rest_url);
 | 
			
		||||
                parsedImRestUrl.path = '';
 | 
			
		||||
                parsedImRestUrl.pathname = '';
 | 
			
		||||
                return presentTermsForServices([new Service(
 | 
			
		||||
                return startTermsFlow([new Service(
 | 
			
		||||
                    Matrix.SERVICE_TYPES.IM,
 | 
			
		||||
                    parsedImRestUrl.format(),
 | 
			
		||||
                    token,
 | 
			
		||||
                )]).then(() => {
 | 
			
		||||
                )], this.termsInteractionCallback).then(() => {
 | 
			
		||||
                    return token;
 | 
			
		||||
                });
 | 
			
		||||
            } else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								src/Terms.js
								
								
								
								
							
							
						
						
									
										25
									
								
								src/Terms.js
								
								
								
								
							| 
						 | 
				
			
			@ -15,6 +15,7 @@ limitations under the License.
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
import Promise from 'bluebird';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
 | 
			
		||||
import MatrixClientPeg from './MatrixClientPeg';
 | 
			
		||||
import sdk from './';
 | 
			
		||||
| 
						 | 
				
			
			@ -39,17 +40,6 @@ export class Service {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Present a popup to the user prompting them to agree to terms and conditions
 | 
			
		||||
 *
 | 
			
		||||
 * @param {Service[]} services Object with keys 'serviceType', 'baseUrl', 'accessToken'
 | 
			
		||||
 * @returns {Promise} resolves when the user agreed to all necessary terms or rejects
 | 
			
		||||
 *     if they cancel.
 | 
			
		||||
 */
 | 
			
		||||
export function presentTermsForServices(services) {
 | 
			
		||||
    return startTermsFlow(services, dialogTermsInteractionCallback);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Start a flow where the user is presented with terms & conditions for some services
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +51,10 @@ export function presentTermsForServices(services) {
 | 
			
		|||
 * @returns {Promise} resolves when the user agreed to all necessary terms or rejects
 | 
			
		||||
 *     if they cancel.
 | 
			
		||||
 */
 | 
			
		||||
export async function startTermsFlow(services, interactionCallback) {
 | 
			
		||||
export async function startTermsFlow(
 | 
			
		||||
    services,
 | 
			
		||||
    interactionCallback = dialogTermsInteractionCallback,
 | 
			
		||||
) {
 | 
			
		||||
    const termsPromises = services.map(
 | 
			
		||||
        (s) => MatrixClientPeg.get().getTerms(s.serviceType, s.baseUrl),
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +153,11 @@ export async function startTermsFlow(services, interactionCallback) {
 | 
			
		|||
    return Promise.all(agreePromises);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function dialogTermsInteractionCallback(policiesAndServicePairs, agreedUrls) {
 | 
			
		||||
export function dialogTermsInteractionCallback(
 | 
			
		||||
    policiesAndServicePairs,
 | 
			
		||||
    agreedUrls,
 | 
			
		||||
    extraClassNames,
 | 
			
		||||
) {
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
        console.log("Terms that need agreement", policiesAndServicePairs);
 | 
			
		||||
        const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog");
 | 
			
		||||
| 
						 | 
				
			
			@ -175,6 +172,6 @@ function dialogTermsInteractionCallback(policiesAndServicePairs, agreedUrls) {
 | 
			
		|||
                }
 | 
			
		||||
                resolve(agreedUrls);
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
        }, classNames("mx_TermsDialog", extraClassNames));
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -176,7 +176,7 @@ export default class TermsDialog extends React.PureComponent {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
            <BaseDialog className='mx_TermsDialog'
 | 
			
		||||
            <BaseDialog
 | 
			
		||||
                fixedWidth={false}
 | 
			
		||||
                onFinished={this._onCancelClick}
 | 
			
		||||
                title={_t("Terms of Service")}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ limitations under the License.
 | 
			
		|||
import sdk from "../index";
 | 
			
		||||
import ScalarAuthClient from '../ScalarAuthClient';
 | 
			
		||||
import Modal from '../Modal';
 | 
			
		||||
import { TermsNotSignedError } from '../Terms';
 | 
			
		||||
import { TermsNotSignedError, dialogTermsInteractionCallback } from '../Terms';
 | 
			
		||||
 | 
			
		||||
export async function showIntegrationsManager(opts) {
 | 
			
		||||
    const IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ export async function showIntegrationsManager(opts) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    const scalarClient = new ScalarAuthClient();
 | 
			
		||||
    scalarClient.setTermsInteractionCallback(integrationsTermsInteractionCallback);
 | 
			
		||||
    try {
 | 
			
		||||
        await scalarClient.connect();
 | 
			
		||||
        if (!scalarClient.hasCredentials()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -63,3 +64,16 @@ export async function showIntegrationsManager(opts) {
 | 
			
		|||
    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",
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue