You've already forked matrix-react-sdk
							
							
				mirror of
				https://github.com/matrix-org/matrix-react-sdk.git
				synced 2025-11-03 00:33:22 +03:00 
			
		
		
		
	Convert things to Typescript and re-use a generic component
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
		@@ -14,19 +14,24 @@ See the License for the specific language governing permissions and
 | 
				
			|||||||
limitations under the License.
 | 
					limitations under the License.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { MatrixClientPeg } from './MatrixClientPeg';
 | 
					import {MatrixClientPeg} from './MatrixClientPeg';
 | 
				
			||||||
import SettingsStore from './settings/SettingsStore';
 | 
					import SettingsStore from './settings/SettingsStore';
 | 
				
			||||||
import * as sdk from './index';
 | 
					import {
 | 
				
			||||||
import { _t } from './languageHandler';
 | 
					    hideToast as hideBulkUnverifiedSessionsToast,
 | 
				
			||||||
import ToastStore from './stores/ToastStore';
 | 
					    showToast as showBulkUnverifiedSessionsToast
 | 
				
			||||||
 | 
					} from "./toasts/BulkUnverifiedSessionsToast";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    hideToast as hideSetupEncryptionToast,
 | 
				
			||||||
 | 
					    Kind as SetupKind,
 | 
				
			||||||
 | 
					    Kind,
 | 
				
			||||||
 | 
					    showToast as showSetupEncryptionToast
 | 
				
			||||||
 | 
					} from "./toasts/SetupEncryptionToast";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    hideToast as hideUnverifiedSessionsToast,
 | 
				
			||||||
 | 
					    showToast as showUnverifiedSessionsToast
 | 
				
			||||||
 | 
					} from "./toasts/UnverifiedSessionToast";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
 | 
					const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
 | 
				
			||||||
const THIS_DEVICE_TOAST_KEY = 'setupencryption';
 | 
					 | 
				
			||||||
const OTHER_DEVICES_TOAST_KEY = 'reviewsessions';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function toastKey(deviceId) {
 | 
					 | 
				
			||||||
    return "unverified_session_" + deviceId;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class DeviceListener {
 | 
					export default class DeviceListener {
 | 
				
			||||||
    // device IDs for which the user has dismissed the verify toast ('Later')
 | 
					    // device IDs for which the user has dismissed the verify toast ('Later')
 | 
				
			||||||
@@ -82,7 +87,7 @@ export default class DeviceListener {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {String[]} deviceIds List of device IDs to dismiss notifications for
 | 
					     * @param {String[]} deviceIds List of device IDs to dismiss notifications for
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async dismissUnverifiedSessions(deviceIds: string[]) {
 | 
					    async dismissUnverifiedSessions(deviceIds: Iterable<string>) {
 | 
				
			||||||
        for (const d of deviceIds) {
 | 
					        for (const d of deviceIds) {
 | 
				
			||||||
            this.dismissed.add(d);
 | 
					            this.dismissed.add(d);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -181,51 +186,25 @@ export default class DeviceListener {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const crossSigningReady = await cli.isCrossSigningReady();
 | 
					        const crossSigningReady = await cli.isCrossSigningReady();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.dismissedThisDeviceToast) {
 | 
					        if (this.dismissedThisDeviceToast || crossSigningReady) {
 | 
				
			||||||
            ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY);
 | 
					            hideSetupEncryptionToast();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if (!crossSigningReady) {
 | 
					            // make sure our keys are finished downloading
 | 
				
			||||||
                // make sure our keys are finished downlaoding
 | 
					            await cli.downloadKeys([cli.getUserId()]);
 | 
				
			||||||
                await cli.downloadKeys([cli.getUserId()]);
 | 
					            // cross signing isn't enabled - nag to enable it
 | 
				
			||||||
                // cross signing isn't enabled - nag to enable it
 | 
					            // There are 3 different toasts for:
 | 
				
			||||||
                // There are 3 different toasts for:
 | 
					            if (cli.getStoredCrossSigningForUser(cli.getUserId())) {
 | 
				
			||||||
                if (cli.getStoredCrossSigningForUser(cli.getUserId())) {
 | 
					                // Cross-signing on account but this device doesn't trust the master key (verify this session)
 | 
				
			||||||
                    // Cross-signing on account but this device doesn't trust the master key (verify this session)
 | 
					                showSetupEncryptionToast(SetupKind.VERIFY_THIS_SESSION);
 | 
				
			||||||
                    ToastStore.sharedInstance().addOrReplaceToast({
 | 
					 | 
				
			||||||
                        key: THIS_DEVICE_TOAST_KEY,
 | 
					 | 
				
			||||||
                        title: _t("Verify this session"),
 | 
					 | 
				
			||||||
                        icon: "verification_warning",
 | 
					 | 
				
			||||||
                        props: {kind: 'verify_this_session'},
 | 
					 | 
				
			||||||
                        component: sdk.getComponent("toasts.SetupEncryptionToast"),
 | 
					 | 
				
			||||||
                        priority: 95,
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    const backupInfo = await this._getKeyBackupInfo();
 | 
					 | 
				
			||||||
                    if (backupInfo) {
 | 
					 | 
				
			||||||
                        // No cross-signing on account but key backup available (upgrade encryption)
 | 
					 | 
				
			||||||
                        ToastStore.sharedInstance().addOrReplaceToast({
 | 
					 | 
				
			||||||
                            key: THIS_DEVICE_TOAST_KEY,
 | 
					 | 
				
			||||||
                            title: _t("Encryption upgrade available"),
 | 
					 | 
				
			||||||
                            icon: "verification_warning",
 | 
					 | 
				
			||||||
                            props: {kind: 'upgrade_encryption'},
 | 
					 | 
				
			||||||
                            component: sdk.getComponent("toasts.SetupEncryptionToast"),
 | 
					 | 
				
			||||||
                            priority: 40,
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        // No cross-signing or key backup on account (set up encryption)
 | 
					 | 
				
			||||||
                        ToastStore.sharedInstance().addOrReplaceToast({
 | 
					 | 
				
			||||||
                            key: THIS_DEVICE_TOAST_KEY,
 | 
					 | 
				
			||||||
                            title: _t("Set up encryption"),
 | 
					 | 
				
			||||||
                            icon: "verification_warning",
 | 
					 | 
				
			||||||
                            props: {kind: 'set_up_encryption'},
 | 
					 | 
				
			||||||
                            component: sdk.getComponent("toasts.SetupEncryptionToast"),
 | 
					 | 
				
			||||||
                            priority: 40,
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // cross-signing is ready, and we don't need to upgrade encryption
 | 
					                const backupInfo = await this._getKeyBackupInfo();
 | 
				
			||||||
                ToastStore.sharedInstance().dismissToast(THIS_DEVICE_TOAST_KEY);
 | 
					                if (backupInfo) {
 | 
				
			||||||
 | 
					                    // No cross-signing on account but key backup available (upgrade encryption)
 | 
				
			||||||
 | 
					                    showSetupEncryptionToast(Kind.UPGRADE_ENCRYPTION);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // No cross-signing or key backup on account (set up encryption)
 | 
				
			||||||
 | 
					                    showSetupEncryptionToast(Kind.SET_UP_ENCRYPTION);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -261,36 +240,20 @@ export default class DeviceListener {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Display or hide the batch toast for old unverified sessions
 | 
					        // Display or hide the batch toast for old unverified sessions
 | 
				
			||||||
        if (oldUnverifiedDeviceIds.size > 0) {
 | 
					        if (oldUnverifiedDeviceIds.size > 0) {
 | 
				
			||||||
            ToastStore.sharedInstance().addOrReplaceToast({
 | 
					            showBulkUnverifiedSessionsToast(oldUnverifiedDeviceIds);
 | 
				
			||||||
                key: OTHER_DEVICES_TOAST_KEY,
 | 
					 | 
				
			||||||
                title: _t("Review where you’re logged in"),
 | 
					 | 
				
			||||||
                icon: "verification_warning",
 | 
					 | 
				
			||||||
                props: {
 | 
					 | 
				
			||||||
                    deviceIds: oldUnverifiedDeviceIds,
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                component: sdk.getComponent("toasts.BulkUnverifiedSessionsToast"),
 | 
					 | 
				
			||||||
                priority: 50,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            ToastStore.sharedInstance().dismissToast(OTHER_DEVICES_TOAST_KEY);
 | 
					            hideBulkUnverifiedSessionsToast();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Show toasts for new unverified devices if they aren't already there
 | 
					        // Show toasts for new unverified devices if they aren't already there
 | 
				
			||||||
        for (const deviceId of newUnverifiedDeviceIds) {
 | 
					        for (const deviceId of newUnverifiedDeviceIds) {
 | 
				
			||||||
            ToastStore.sharedInstance().addOrReplaceToast({
 | 
					            showUnverifiedSessionsToast(deviceId);
 | 
				
			||||||
                key: toastKey(deviceId),
 | 
					 | 
				
			||||||
                title: _t("New login. Was this you?"),
 | 
					 | 
				
			||||||
                icon: "verification_warning",
 | 
					 | 
				
			||||||
                props: { deviceId },
 | 
					 | 
				
			||||||
                component: sdk.getComponent("toasts.UnverifiedSessionToast"),
 | 
					 | 
				
			||||||
                priority: 80,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // ...and hide any we don't need any more
 | 
					        // ...and hide any we don't need any more
 | 
				
			||||||
        for (const deviceId of this.displayingToastsForDeviceIds) {
 | 
					        for (const deviceId of this.displayingToastsForDeviceIds) {
 | 
				
			||||||
            if (!newUnverifiedDeviceIds.has(deviceId)) {
 | 
					            if (!newUnverifiedDeviceIds.has(deviceId)) {
 | 
				
			||||||
                ToastStore.sharedInstance().dismissToast(toastKey(deviceId));
 | 
					                hideUnverifiedSessionsToast(deviceId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,56 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
Copyright 2020 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 React from 'react';
 | 
					 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import { _t } from '../../../languageHandler';
 | 
					 | 
				
			||||||
import dis from "../../../dispatcher/dispatcher";
 | 
					 | 
				
			||||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
 | 
					 | 
				
			||||||
import DeviceListener from '../../../DeviceListener';
 | 
					 | 
				
			||||||
import FormButton from '../elements/FormButton';
 | 
					 | 
				
			||||||
import { replaceableComponent } from '../../../utils/replaceableComponent';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@replaceableComponent("views.toasts.BulkUnverifiedSessionsToast")
 | 
					 | 
				
			||||||
export default class BulkUnverifiedSessionsToast extends React.PureComponent {
 | 
					 | 
				
			||||||
    static propTypes = {
 | 
					 | 
				
			||||||
        deviceIds: PropTypes.array,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _onLaterClick = () => {
 | 
					 | 
				
			||||||
        DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _onReviewClick = async () => {
 | 
					 | 
				
			||||||
        DeviceListener.sharedInstance().dismissUnverifiedSessions(this.props.deviceIds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dis.dispatch({
 | 
					 | 
				
			||||||
            action: 'view_user_info',
 | 
					 | 
				
			||||||
            userId: MatrixClientPeg.get().getUserId(),
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render() {
 | 
					 | 
				
			||||||
        return (<div>
 | 
					 | 
				
			||||||
            <div className="mx_Toast_description">
 | 
					 | 
				
			||||||
                {_t("Verify all your sessions to ensure your account & messages are safe")}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div className="mx_Toast_buttons" aria-live="off">
 | 
					 | 
				
			||||||
                <FormButton label={_t("Later")} kind="danger" onClick={this._onLaterClick} />
 | 
					 | 
				
			||||||
                <FormButton label={_t("Review")} onClick={this._onReviewClick} />
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										42
									
								
								src/components/views/toasts/GenericToast.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/components/views/toasts/GenericToast.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2020 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 React, {ReactChild} from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import FormButton from "../elements/FormButton";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IProps {
 | 
				
			||||||
 | 
					    description: ReactChild;
 | 
				
			||||||
 | 
					    acceptLabel: string;
 | 
				
			||||||
 | 
					    rejectLabel?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onAccept();
 | 
				
			||||||
 | 
					    onReject?();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GenericToast: React.FC<IProps> = ({description, acceptLabel, rejectLabel, onAccept, onReject}) => {
 | 
				
			||||||
 | 
					    return <div>
 | 
				
			||||||
 | 
					        <div className="mx_Toast_description">
 | 
				
			||||||
 | 
					            { description }
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div className="mx_Toast_buttons" aria-live="off">
 | 
				
			||||||
 | 
					            {onReject && rejectLabel && <FormButton label={rejectLabel} kind="danger" onClick={onReject} /> }
 | 
				
			||||||
 | 
					            <FormButton label={acceptLabel} onClick={onAccept} />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default GenericToast;
 | 
				
			||||||
@@ -1,88 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
Copyright 2020 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 React from 'react';
 | 
					 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import Modal from '../../../Modal';
 | 
					 | 
				
			||||||
import * as sdk from "../../../index";
 | 
					 | 
				
			||||||
import { _t } from '../../../languageHandler';
 | 
					 | 
				
			||||||
import DeviceListener from '../../../DeviceListener';
 | 
					 | 
				
			||||||
import SetupEncryptionDialog from "../dialogs/SetupEncryptionDialog";
 | 
					 | 
				
			||||||
import { accessSecretStorage } from '../../../CrossSigningManager';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default class SetupEncryptionToast extends React.PureComponent {
 | 
					 | 
				
			||||||
    static propTypes = {
 | 
					 | 
				
			||||||
        toastKey: PropTypes.string.isRequired,
 | 
					 | 
				
			||||||
        kind: PropTypes.oneOf([
 | 
					 | 
				
			||||||
            'set_up_encryption',
 | 
					 | 
				
			||||||
            'verify_this_session',
 | 
					 | 
				
			||||||
            'upgrade_encryption',
 | 
					 | 
				
			||||||
        ]).isRequired,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _onLaterClick = () => {
 | 
					 | 
				
			||||||
        DeviceListener.sharedInstance().dismissEncryptionSetup();
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _onSetupClick = async () => {
 | 
					 | 
				
			||||||
        if (this.props.kind === "verify_this_session") {
 | 
					 | 
				
			||||||
            Modal.createTrackedDialog('Verify session', 'Verify session', SetupEncryptionDialog,
 | 
					 | 
				
			||||||
                {}, null, /* priority = */ false, /* static = */ true);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            const Spinner = sdk.getComponent("elements.Spinner");
 | 
					 | 
				
			||||||
            const modal = Modal.createDialog(
 | 
					 | 
				
			||||||
                Spinner, null, 'mx_Dialog_spinner', /* priority */ false, /* static */ true,
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                await accessSecretStorage();
 | 
					 | 
				
			||||||
            } finally {
 | 
					 | 
				
			||||||
                modal.close();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    getDescription() {
 | 
					 | 
				
			||||||
        switch (this.props.kind) {
 | 
					 | 
				
			||||||
            case 'set_up_encryption':
 | 
					 | 
				
			||||||
            case 'upgrade_encryption':
 | 
					 | 
				
			||||||
                return _t('Verify yourself & others to keep your chats safe');
 | 
					 | 
				
			||||||
            case 'verify_this_session':
 | 
					 | 
				
			||||||
                return _t('Other users may not trust it');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    getSetupCaption() {
 | 
					 | 
				
			||||||
        switch (this.props.kind) {
 | 
					 | 
				
			||||||
            case 'set_up_encryption':
 | 
					 | 
				
			||||||
                return _t('Set up');
 | 
					 | 
				
			||||||
            case 'upgrade_encryption':
 | 
					 | 
				
			||||||
                return _t('Upgrade');
 | 
					 | 
				
			||||||
            case 'verify_this_session':
 | 
					 | 
				
			||||||
                return _t('Verify');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render() {
 | 
					 | 
				
			||||||
        const FormButton = sdk.getComponent("elements.FormButton");
 | 
					 | 
				
			||||||
        return (<div>
 | 
					 | 
				
			||||||
            <div className="mx_Toast_description">{this.getDescription()}</div>
 | 
					 | 
				
			||||||
            <div className="mx_Toast_buttons" aria-live="off">
 | 
					 | 
				
			||||||
                <FormButton label={_t("Later")} kind="danger" onClick={this._onLaterClick} />
 | 
					 | 
				
			||||||
                <FormButton label={this.getSetupCaption()} onClick={this._onSetupClick} />
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,66 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
Copyright 2020 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 React from 'react';
 | 
					 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import { _t } from '../../../languageHandler';
 | 
					 | 
				
			||||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
 | 
					 | 
				
			||||||
import Modal from '../../../Modal';
 | 
					 | 
				
			||||||
import DeviceListener from '../../../DeviceListener';
 | 
					 | 
				
			||||||
import NewSessionReviewDialog from '../dialogs/NewSessionReviewDialog';
 | 
					 | 
				
			||||||
import FormButton from '../elements/FormButton';
 | 
					 | 
				
			||||||
import { replaceableComponent } from '../../../utils/replaceableComponent';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@replaceableComponent("views.toasts.UnverifiedSessionToast")
 | 
					 | 
				
			||||||
export default class UnverifiedSessionToast extends React.PureComponent {
 | 
					 | 
				
			||||||
    static propTypes = {
 | 
					 | 
				
			||||||
        deviceId: PropTypes.string,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _onLaterClick = () => {
 | 
					 | 
				
			||||||
        DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _onReviewClick = async () => {
 | 
					 | 
				
			||||||
        const cli = MatrixClientPeg.get();
 | 
					 | 
				
			||||||
        Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, {
 | 
					 | 
				
			||||||
            userId: cli.getUserId(),
 | 
					 | 
				
			||||||
            device: cli.getStoredDevice(cli.getUserId(), this.props.deviceId),
 | 
					 | 
				
			||||||
            onFinished: (r) => {
 | 
					 | 
				
			||||||
                if (!r) {
 | 
					 | 
				
			||||||
                    /* This'll come back false if the user clicks "this wasn't me" and saw a warning dialog */
 | 
					 | 
				
			||||||
                    DeviceListener.sharedInstance().dismissUnverifiedSessions([this.props.deviceId]);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        }, null, /* priority = */ false, /* static = */ true);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render() {
 | 
					 | 
				
			||||||
        const cli = MatrixClientPeg.get();
 | 
					 | 
				
			||||||
        const device = cli.getStoredDevice(cli.getUserId(), this.props.deviceId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return (<div>
 | 
					 | 
				
			||||||
            <div className="mx_Toast_description">
 | 
					 | 
				
			||||||
                {_t(
 | 
					 | 
				
			||||||
                    "Verify the new login accessing your account: %(name)s", { name: device.getDisplayName()})}
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div className="mx_Toast_buttons" aria-live="off">
 | 
					 | 
				
			||||||
                <FormButton label={_t("Later")} kind="danger" onClick={this._onLaterClick} />
 | 
					 | 
				
			||||||
                <FormButton label={_t("Verify")} onClick={this._onReviewClick} />
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
 | 
				
			|||||||
limitations under the License.
 | 
					limitations under the License.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import React from 'react';
 | 
					import React from "react";
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					
 | 
				
			||||||
import * as sdk from "../../../index";
 | 
					import * as sdk from "../../../index";
 | 
				
			||||||
import { _t } from '../../../languageHandler';
 | 
					import { _t } from '../../../languageHandler';
 | 
				
			||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
 | 
					import {MatrixClientPeg} from '../../../MatrixClientPeg';
 | 
				
			||||||
@@ -24,8 +24,23 @@ import {userLabelForEventRoom} from "../../../utils/KeyVerificationStateObserver
 | 
				
			|||||||
import dis from "../../../dispatcher/dispatcher";
 | 
					import dis from "../../../dispatcher/dispatcher";
 | 
				
			||||||
import ToastStore from "../../../stores/ToastStore";
 | 
					import ToastStore from "../../../stores/ToastStore";
 | 
				
			||||||
import Modal from "../../../Modal";
 | 
					import Modal from "../../../Modal";
 | 
				
			||||||
 | 
					import GenericToast from "./GenericToast";
 | 
				
			||||||
 | 
					import {VerificationRequest} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
 | 
				
			||||||
 | 
					import {DeviceInfo} from "matrix-js-sdk/src/crypto/deviceinfo";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IProps {
 | 
				
			||||||
 | 
					    toastKey: string;
 | 
				
			||||||
 | 
					    request: VerificationRequest;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IState {
 | 
				
			||||||
 | 
					    counter: number;
 | 
				
			||||||
 | 
					    device?: DeviceInfo;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class VerificationRequestToast extends React.PureComponent<IProps, IState> {
 | 
				
			||||||
 | 
					    private intervalHandle: NodeJS.Timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class VerificationRequestToast extends React.PureComponent {
 | 
					 | 
				
			||||||
    constructor(props) {
 | 
					    constructor(props) {
 | 
				
			||||||
        super(props);
 | 
					        super(props);
 | 
				
			||||||
        this.state = {counter: Math.ceil(props.request.timeout / 1000)};
 | 
					        this.state = {counter: Math.ceil(props.request.timeout / 1000)};
 | 
				
			||||||
@@ -34,7 +49,7 @@ export default class VerificationRequestToast extends React.PureComponent {
 | 
				
			|||||||
    async componentDidMount() {
 | 
					    async componentDidMount() {
 | 
				
			||||||
        const {request} = this.props;
 | 
					        const {request} = this.props;
 | 
				
			||||||
        if (request.timeout && request.timeout > 0) {
 | 
					        if (request.timeout && request.timeout > 0) {
 | 
				
			||||||
            this._intervalHandle = setInterval(() => {
 | 
					            this.intervalHandle = setInterval(() => {
 | 
				
			||||||
                let {counter} = this.state;
 | 
					                let {counter} = this.state;
 | 
				
			||||||
                counter = Math.max(0, counter - 1);
 | 
					                counter = Math.max(0, counter - 1);
 | 
				
			||||||
                this.setState({counter});
 | 
					                this.setState({counter});
 | 
				
			||||||
@@ -56,7 +71,7 @@ export default class VerificationRequestToast extends React.PureComponent {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentWillUnmount() {
 | 
					    componentWillUnmount() {
 | 
				
			||||||
        clearInterval(this._intervalHandle);
 | 
					        clearInterval(this.intervalHandle);
 | 
				
			||||||
        const {request} = this.props;
 | 
					        const {request} = this.props;
 | 
				
			||||||
        request.off("change", this._checkRequestIsPending);
 | 
					        request.off("change", this._checkRequestIsPending);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -110,7 +125,6 @@ export default class VerificationRequestToast extends React.PureComponent {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const FormButton = sdk.getComponent("elements.FormButton");
 | 
					 | 
				
			||||||
        const {request} = this.props;
 | 
					        const {request} = this.props;
 | 
				
			||||||
        let nameLabel;
 | 
					        let nameLabel;
 | 
				
			||||||
        if (request.isSelfVerification) {
 | 
					        if (request.isSelfVerification) {
 | 
				
			||||||
@@ -133,20 +147,16 @@ export default class VerificationRequestToast extends React.PureComponent {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const declineLabel = this.state.counter == 0 ?
 | 
					        const declineLabel = this.state.counter === 0 ?
 | 
				
			||||||
            _t("Decline") :
 | 
					            _t("Decline") :
 | 
				
			||||||
            _t("Decline (%(counter)s)", {counter: this.state.counter});
 | 
					            _t("Decline (%(counter)s)", {counter: this.state.counter});
 | 
				
			||||||
        return (<div>
 | 
					
 | 
				
			||||||
            <div className="mx_Toast_description">{nameLabel}</div>
 | 
					        return <GenericToast
 | 
				
			||||||
            <div className="mx_Toast_buttons" aria-live="off">
 | 
					            description={nameLabel}
 | 
				
			||||||
                <FormButton label={declineLabel} kind="danger" onClick={this.cancel} />
 | 
					            acceptLabel={_t("Accept")}
 | 
				
			||||||
                <FormButton label={_t("Accept")} onClick={this.accept} />
 | 
					            onAccept={this.accept}
 | 
				
			||||||
            </div>
 | 
					            rejectLabel={declineLabel}
 | 
				
			||||||
        </div>);
 | 
					            onReject={this.cancel}
 | 
				
			||||||
 | 
					        />;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
VerificationRequestToast.propTypes = {
 | 
					 | 
				
			||||||
    request: PropTypes.object.isRequired,
 | 
					 | 
				
			||||||
    toastKey: PropTypes.string.isRequired,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										58
									
								
								src/toasts/BulkUnverifiedSessionsToast.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/toasts/BulkUnverifiedSessionsToast.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2020 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 { _t } from '../languageHandler';
 | 
				
			||||||
 | 
					import dis from "../dispatcher/dispatcher";
 | 
				
			||||||
 | 
					import { MatrixClientPeg } from '../MatrixClientPeg';
 | 
				
			||||||
 | 
					import DeviceListener from '../DeviceListener';
 | 
				
			||||||
 | 
					import GenericToast from "../components/views/toasts/GenericToast";
 | 
				
			||||||
 | 
					import ToastStore from "../stores/ToastStore";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TOAST_KEY = "reviewsessions";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const showToast = (deviceIds: Set<string>) => {
 | 
				
			||||||
 | 
					    const onAccept = () => {
 | 
				
			||||||
 | 
					        DeviceListener.sharedInstance().dismissUnverifiedSessions(deviceIds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dis.dispatch({
 | 
				
			||||||
 | 
					            action: 'view_user_info',
 | 
				
			||||||
 | 
					            userId: MatrixClientPeg.get().getUserId(),
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onReject = () => {
 | 
				
			||||||
 | 
					        DeviceListener.sharedInstance().dismissUnverifiedSessions(deviceIds);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ToastStore.sharedInstance().addOrReplaceToast({
 | 
				
			||||||
 | 
					        key: TOAST_KEY,
 | 
				
			||||||
 | 
					        title: _t("Review where you’re logged in"),
 | 
				
			||||||
 | 
					        icon: "verification_warning",
 | 
				
			||||||
 | 
					        props: {
 | 
				
			||||||
 | 
					            description: _t("Verify all your sessions to ensure your account & messages are safe"),
 | 
				
			||||||
 | 
					            acceptLabel: _t("Review"),
 | 
				
			||||||
 | 
					            onAccept,
 | 
				
			||||||
 | 
					            rejectLabel: _t("Later"),
 | 
				
			||||||
 | 
					            onReject,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        component: GenericToast,
 | 
				
			||||||
 | 
					        priority: 50,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const hideToast = () => {
 | 
				
			||||||
 | 
					    ToastStore.sharedInstance().dismissToast(TOAST_KEY);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										106
									
								
								src/toasts/SetupEncryptionToast.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/toasts/SetupEncryptionToast.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2020 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 * as sdk from "../index";
 | 
				
			||||||
 | 
					import { _t } from "../languageHandler";
 | 
				
			||||||
 | 
					import DeviceListener from "../DeviceListener";
 | 
				
			||||||
 | 
					import SetupEncryptionDialog from "../components/views/dialogs/SetupEncryptionDialog";
 | 
				
			||||||
 | 
					import { accessSecretStorage } from "../CrossSigningManager";
 | 
				
			||||||
 | 
					import ToastStore from "../stores/ToastStore";
 | 
				
			||||||
 | 
					import GenericToast from "../components/views/toasts/GenericToast";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TOAST_KEY = "setupencryption";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getTitle = (kind: Kind) => {
 | 
				
			||||||
 | 
					    switch (kind) {
 | 
				
			||||||
 | 
					        case Kind.SET_UP_ENCRYPTION:
 | 
				
			||||||
 | 
					            return _t("Set up encryption");
 | 
				
			||||||
 | 
					        case Kind.UPGRADE_ENCRYPTION:
 | 
				
			||||||
 | 
					            return _t("Encryption upgrade available");
 | 
				
			||||||
 | 
					        case Kind.VERIFY_THIS_SESSION:
 | 
				
			||||||
 | 
					            return _t("Verify this session");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getSetupCaption = (kind: Kind) => {
 | 
				
			||||||
 | 
					    switch (kind) {
 | 
				
			||||||
 | 
					        case Kind.SET_UP_ENCRYPTION:
 | 
				
			||||||
 | 
					            return _t("Set up");
 | 
				
			||||||
 | 
					        case Kind.UPGRADE_ENCRYPTION:
 | 
				
			||||||
 | 
					            return _t("Upgrade");
 | 
				
			||||||
 | 
					        case Kind.VERIFY_THIS_SESSION:
 | 
				
			||||||
 | 
					            return _t("Verify");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getDescription = (kind: Kind) => {
 | 
				
			||||||
 | 
					    switch (kind) {
 | 
				
			||||||
 | 
					        case Kind.SET_UP_ENCRYPTION:
 | 
				
			||||||
 | 
					        case Kind.UPGRADE_ENCRYPTION:
 | 
				
			||||||
 | 
					            return _t("Verify yourself & others to keep your chats safe");
 | 
				
			||||||
 | 
					        case Kind.VERIFY_THIS_SESSION:
 | 
				
			||||||
 | 
					            return _t("Other users may not trust it");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export enum Kind {
 | 
				
			||||||
 | 
					    SET_UP_ENCRYPTION = "set_up_encryption",
 | 
				
			||||||
 | 
					    UPGRADE_ENCRYPTION = "upgrade_encryption",
 | 
				
			||||||
 | 
					    VERIFY_THIS_SESSION = "verify_this_session",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onReject = () => {
 | 
				
			||||||
 | 
					    DeviceListener.sharedInstance().dismissEncryptionSetup();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const showToast = (kind: Kind) => {
 | 
				
			||||||
 | 
					    const onAccept = async () => {
 | 
				
			||||||
 | 
					        if (kind === Kind.VERIFY_THIS_SESSION) {
 | 
				
			||||||
 | 
					            Modal.createTrackedDialog("Verify session", "Verify session", SetupEncryptionDialog,
 | 
				
			||||||
 | 
					                {}, null, /* priority = */ false, /* static = */ true);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            const Spinner = sdk.getComponent("elements.Spinner");
 | 
				
			||||||
 | 
					            const modal = Modal.createDialog(
 | 
				
			||||||
 | 
					                Spinner, null, "mx_Dialog_spinner", /* priority */ false, /* static */ true,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                await accessSecretStorage();
 | 
				
			||||||
 | 
					            } finally {
 | 
				
			||||||
 | 
					                modal.close();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ToastStore.sharedInstance().addOrReplaceToast({
 | 
				
			||||||
 | 
					        key: TOAST_KEY,
 | 
				
			||||||
 | 
					        title: getTitle(kind),
 | 
				
			||||||
 | 
					        icon: "verification_warning",
 | 
				
			||||||
 | 
					        props: {
 | 
				
			||||||
 | 
					            description: getDescription(kind),
 | 
				
			||||||
 | 
					            acceptLabel: getSetupCaption(kind),
 | 
				
			||||||
 | 
					            onAccept,
 | 
				
			||||||
 | 
					            rejectLabel: _t("Later"),
 | 
				
			||||||
 | 
					            onReject,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        component: GenericToast,
 | 
				
			||||||
 | 
					        priority: kind === Kind.VERIFY_THIS_SESSION ? 95 : 40,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const hideToast = () => {
 | 
				
			||||||
 | 
					    ToastStore.sharedInstance().dismissToast(TOAST_KEY);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										70
									
								
								src/toasts/UnverifiedSessionToast.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/toasts/UnverifiedSessionToast.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2020 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 { _t } from '../languageHandler';
 | 
				
			||||||
 | 
					import { MatrixClientPeg } from '../MatrixClientPeg';
 | 
				
			||||||
 | 
					import Modal from '../Modal';
 | 
				
			||||||
 | 
					import DeviceListener from '../DeviceListener';
 | 
				
			||||||
 | 
					import NewSessionReviewDialog from '../components/views/dialogs/NewSessionReviewDialog';
 | 
				
			||||||
 | 
					import ToastStore from "../stores/ToastStore";
 | 
				
			||||||
 | 
					import GenericToast from "../components/views/toasts/GenericToast";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toastKey(deviceId: string) {
 | 
				
			||||||
 | 
					    return "unverified_session_" + deviceId;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const showToast = (deviceId: string) => {
 | 
				
			||||||
 | 
					    const cli = MatrixClientPeg.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onAccept = () => {
 | 
				
			||||||
 | 
					        Modal.createTrackedDialog('New Session Review', 'Starting dialog', NewSessionReviewDialog, {
 | 
				
			||||||
 | 
					            userId: cli.getUserId(),
 | 
				
			||||||
 | 
					            device: cli.getStoredDevice(cli.getUserId(), deviceId),
 | 
				
			||||||
 | 
					            onFinished: (r) => {
 | 
				
			||||||
 | 
					                if (!r) {
 | 
				
			||||||
 | 
					                    /* This'll come back false if the user clicks "this wasn't me" and saw a warning dialog */
 | 
				
			||||||
 | 
					                    DeviceListener.sharedInstance().dismissUnverifiedSessions([deviceId]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }, null, /* priority = */ false, /* static = */ true);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onReject = () => {
 | 
				
			||||||
 | 
					        DeviceListener.sharedInstance().dismissUnverifiedSessions([deviceId]);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const device = cli.getStoredDevice(cli.getUserId(), deviceId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ToastStore.sharedInstance().addOrReplaceToast({
 | 
				
			||||||
 | 
					        key: toastKey(deviceId),
 | 
				
			||||||
 | 
					        title: _t("New login. Was this you?"),
 | 
				
			||||||
 | 
					        icon: "verification_warning",
 | 
				
			||||||
 | 
					        props: {
 | 
				
			||||||
 | 
					            description: _t(
 | 
				
			||||||
 | 
					                "Verify the new login accessing your account: %(name)s", { name: device.getDisplayName()}),
 | 
				
			||||||
 | 
					            acceptLabel: _t("Verify"),
 | 
				
			||||||
 | 
					            onAccept,
 | 
				
			||||||
 | 
					            rejectLabel: _t("Later"),
 | 
				
			||||||
 | 
					            onReject,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        component: GenericToast,
 | 
				
			||||||
 | 
					        priority: 80,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const hideToast = (deviceId: string) => {
 | 
				
			||||||
 | 
					    ToastStore.sharedInstance().dismissToast(deviceId);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Reference in New Issue
	
	Block a user