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 
			
		
		
		
	Merge pull request #6315 from matrix-org/gsouquet/ts-1
This commit is contained in:
		
							
								
								
									
										2
									
								
								src/@types/global.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/@types/global.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -46,6 +46,7 @@ import { VoiceRecordingStore } from "../stores/VoiceRecordingStore";
 | 
				
			|||||||
import PerformanceMonitor from "../performance";
 | 
					import PerformanceMonitor from "../performance";
 | 
				
			||||||
import UIStore from "../stores/UIStore";
 | 
					import UIStore from "../stores/UIStore";
 | 
				
			||||||
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
 | 
					import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
 | 
				
			||||||
 | 
					import { RoomScrollStateStore } from "../stores/RoomScrollStateStore";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
declare global {
 | 
					declare global {
 | 
				
			||||||
    interface Window {
 | 
					    interface Window {
 | 
				
			||||||
@@ -87,6 +88,7 @@ declare global {
 | 
				
			|||||||
        mxPerformanceEntryNames: any;
 | 
					        mxPerformanceEntryNames: any;
 | 
				
			||||||
        mxUIStore: UIStore;
 | 
					        mxUIStore: UIStore;
 | 
				
			||||||
        mxSetupEncryptionStore?: SetupEncryptionStore;
 | 
					        mxSetupEncryptionStore?: SetupEncryptionStore;
 | 
				
			||||||
 | 
					        mxRoomScrollStateStore?: RoomScrollStateStore;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    interface Document {
 | 
					    interface Document {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,7 @@ import eventSearch, { searchPagination } from '../../Searching';
 | 
				
			|||||||
import MainSplit from './MainSplit';
 | 
					import MainSplit from './MainSplit';
 | 
				
			||||||
import RightPanel from './RightPanel';
 | 
					import RightPanel from './RightPanel';
 | 
				
			||||||
import RoomViewStore from '../../stores/RoomViewStore';
 | 
					import RoomViewStore from '../../stores/RoomViewStore';
 | 
				
			||||||
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
 | 
					import RoomScrollStateStore, { ScrollState } from '../../stores/RoomScrollStateStore';
 | 
				
			||||||
import WidgetEchoStore from '../../stores/WidgetEchoStore';
 | 
					import WidgetEchoStore from '../../stores/WidgetEchoStore';
 | 
				
			||||||
import SettingsStore from "../../settings/SettingsStore";
 | 
					import SettingsStore from "../../settings/SettingsStore";
 | 
				
			||||||
import { Layout } from "../../settings/Layout";
 | 
					import { Layout } from "../../settings/Layout";
 | 
				
			||||||
@@ -1577,7 +1577,7 @@ export default class RoomView extends React.Component<IProps, IState> {
 | 
				
			|||||||
    // get the current scroll position of the room, so that it can be
 | 
					    // get the current scroll position of the room, so that it can be
 | 
				
			||||||
    // restored when we switch back to it.
 | 
					    // restored when we switch back to it.
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    private getScrollState() {
 | 
					    private getScrollState(): ScrollState {
 | 
				
			||||||
        const messagePanel = this.messagePanel;
 | 
					        const messagePanel = this.messagePanel;
 | 
				
			||||||
        if (!messagePanel) return null;
 | 
					        if (!messagePanel) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,39 +15,42 @@ limitations under the License.
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import { _t } from '../../../languageHandler';
 | 
					import { _t } from '../../../languageHandler';
 | 
				
			||||||
import * as sdk from '../../../index';
 | 
					import * as sdk from '../../../index';
 | 
				
			||||||
import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
 | 
					import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
 | 
				
			||||||
import SetupEncryptionBody from "./SetupEncryptionBody";
 | 
					import SetupEncryptionBody from "./SetupEncryptionBody";
 | 
				
			||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("structures.auth.CompleteSecurity")
 | 
					interface IProps {
 | 
				
			||||||
export default class CompleteSecurity extends React.Component {
 | 
					    onFinished: () => void;
 | 
				
			||||||
    static propTypes = {
 | 
					}
 | 
				
			||||||
        onFinished: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					interface IState {
 | 
				
			||||||
        super();
 | 
					    phase: Phase;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@replaceableComponent("structures.auth.CompleteSecurity")
 | 
				
			||||||
 | 
					export default class CompleteSecurity extends React.Component<IProps, IState> {
 | 
				
			||||||
 | 
					    constructor(props: IProps) {
 | 
				
			||||||
 | 
					        super(props);
 | 
				
			||||||
        const store = SetupEncryptionStore.sharedInstance();
 | 
					        const store = SetupEncryptionStore.sharedInstance();
 | 
				
			||||||
        store.on("update", this._onStoreUpdate);
 | 
					        store.on("update", this.onStoreUpdate);
 | 
				
			||||||
        store.start();
 | 
					        store.start();
 | 
				
			||||||
        this.state = { phase: store.phase };
 | 
					        this.state = { phase: store.phase };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _onStoreUpdate = () => {
 | 
					    private onStoreUpdate = (): void => {
 | 
				
			||||||
        const store = SetupEncryptionStore.sharedInstance();
 | 
					        const store = SetupEncryptionStore.sharedInstance();
 | 
				
			||||||
        this.setState({ phase: store.phase });
 | 
					        this.setState({ phase: store.phase });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentWillUnmount() {
 | 
					    public componentWillUnmount(): void {
 | 
				
			||||||
        const store = SetupEncryptionStore.sharedInstance();
 | 
					        const store = SetupEncryptionStore.sharedInstance();
 | 
				
			||||||
        store.off("update", this._onStoreUpdate);
 | 
					        store.off("update", this.onStoreUpdate);
 | 
				
			||||||
        store.stop();
 | 
					        store.stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    public render() {
 | 
				
			||||||
        const AuthPage = sdk.getComponent("auth.AuthPage");
 | 
					        const AuthPage = sdk.getComponent("auth.AuthPage");
 | 
				
			||||||
        const CompleteSecurityBody = sdk.getComponent("auth.CompleteSecurityBody");
 | 
					        const CompleteSecurityBody = sdk.getComponent("auth.CompleteSecurityBody");
 | 
				
			||||||
        const { phase } = this.state;
 | 
					        const { phase } = this.state;
 | 
				
			||||||
@@ -15,20 +15,19 @@ limitations under the License.
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import AuthPage from '../../views/auth/AuthPage';
 | 
					import AuthPage from '../../views/auth/AuthPage';
 | 
				
			||||||
import CompleteSecurityBody from '../../views/auth/CompleteSecurityBody';
 | 
					import CompleteSecurityBody from '../../views/auth/CompleteSecurityBody';
 | 
				
			||||||
import CreateCrossSigningDialog from '../../views/dialogs/security/CreateCrossSigningDialog';
 | 
					import CreateCrossSigningDialog from '../../views/dialogs/security/CreateCrossSigningDialog';
 | 
				
			||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("structures.auth.E2eSetup")
 | 
					interface IProps {
 | 
				
			||||||
export default class E2eSetup extends React.Component {
 | 
					    onFinished: () => void;
 | 
				
			||||||
    static propTypes = {
 | 
					    accountPassword?: string;
 | 
				
			||||||
        onFinished: PropTypes.func.isRequired,
 | 
					    tokenLogin?: boolean;
 | 
				
			||||||
        accountPassword: PropTypes.string,
 | 
					}
 | 
				
			||||||
        tokenLogin: PropTypes.bool,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@replaceableComponent("structures.auth.E2eSetup")
 | 
				
			||||||
 | 
					export default class E2eSetup extends React.Component<IProps> {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <AuthPage>
 | 
					            <AuthPage>
 | 
				
			||||||
@@ -17,7 +17,6 @@ limitations under the License.
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import { _t, _td } from '../../../languageHandler';
 | 
					import { _t, _td } from '../../../languageHandler';
 | 
				
			||||||
import * as sdk from '../../../index';
 | 
					import * as sdk from '../../../index';
 | 
				
			||||||
import Modal from "../../../Modal";
 | 
					import Modal from "../../../Modal";
 | 
				
			||||||
@@ -31,27 +30,50 @@ import PassphraseField from '../../views/auth/PassphraseField';
 | 
				
			|||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
import { PASSWORD_MIN_SCORE } from '../../views/auth/RegistrationForm';
 | 
					import { PASSWORD_MIN_SCORE } from '../../views/auth/RegistrationForm';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Phases
 | 
					import { IValidationResult } from "../../views/elements/Validation";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum Phase {
 | 
				
			||||||
    // Show the forgot password inputs
 | 
					    // Show the forgot password inputs
 | 
				
			||||||
const PHASE_FORGOT = 1;
 | 
					    Forgot = 1,
 | 
				
			||||||
    // Email is in the process of being sent
 | 
					    // Email is in the process of being sent
 | 
				
			||||||
const PHASE_SENDING_EMAIL = 2;
 | 
					    SendingEmail = 2,
 | 
				
			||||||
    // Email has been sent
 | 
					    // Email has been sent
 | 
				
			||||||
const PHASE_EMAIL_SENT = 3;
 | 
					    EmailSent = 3,
 | 
				
			||||||
    // User has clicked the link in email and completed reset
 | 
					    // User has clicked the link in email and completed reset
 | 
				
			||||||
const PHASE_DONE = 4;
 | 
					    Done = 4,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IProps {
 | 
				
			||||||
 | 
					    serverConfig: ValidatedServerConfig;
 | 
				
			||||||
 | 
					    onServerConfigChange: () => void;
 | 
				
			||||||
 | 
					    onLoginClick?: () => void;
 | 
				
			||||||
 | 
					    onComplete: () => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IState {
 | 
				
			||||||
 | 
					    phase: Phase;
 | 
				
			||||||
 | 
					    email: string;
 | 
				
			||||||
 | 
					    password: string;
 | 
				
			||||||
 | 
					    password2: string;
 | 
				
			||||||
 | 
					    errorText: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // We perform liveliness checks later, but for now suppress the errors.
 | 
				
			||||||
 | 
					    // We also track the server dead errors independently of the regular errors so
 | 
				
			||||||
 | 
					    // that we can render it differently, and override any other error the user may
 | 
				
			||||||
 | 
					    // be seeing.
 | 
				
			||||||
 | 
					    serverIsAlive: boolean;
 | 
				
			||||||
 | 
					    serverErrorIsFatal: boolean;
 | 
				
			||||||
 | 
					    serverDeadError: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    passwordFieldValid: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("structures.auth.ForgotPassword")
 | 
					@replaceableComponent("structures.auth.ForgotPassword")
 | 
				
			||||||
export default class ForgotPassword extends React.Component {
 | 
					export default class ForgotPassword extends React.Component<IProps, IState> {
 | 
				
			||||||
    static propTypes = {
 | 
					    private reset: PasswordReset;
 | 
				
			||||||
        serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired,
 | 
					 | 
				
			||||||
        onServerConfigChange: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
        onLoginClick: PropTypes.func,
 | 
					 | 
				
			||||||
        onComplete: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state = {
 | 
					    state = {
 | 
				
			||||||
        phase: PHASE_FORGOT,
 | 
					        phase: Phase.Forgot,
 | 
				
			||||||
        email: "",
 | 
					        email: "",
 | 
				
			||||||
        password: "",
 | 
					        password: "",
 | 
				
			||||||
        password2: "",
 | 
					        password2: "",
 | 
				
			||||||
@@ -64,30 +86,31 @@ export default class ForgotPassword extends React.Component {
 | 
				
			|||||||
        serverIsAlive: true,
 | 
					        serverIsAlive: true,
 | 
				
			||||||
        serverErrorIsFatal: false,
 | 
					        serverErrorIsFatal: false,
 | 
				
			||||||
        serverDeadError: "",
 | 
					        serverDeadError: "",
 | 
				
			||||||
 | 
					        passwordFieldValid: false,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(props) {
 | 
					    constructor(props: IProps) {
 | 
				
			||||||
        super(props);
 | 
					        super(props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CountlyAnalytics.instance.track("onboarding_forgot_password_begin");
 | 
					        CountlyAnalytics.instance.track("onboarding_forgot_password_begin");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentDidMount() {
 | 
					    public componentDidMount() {
 | 
				
			||||||
        this.reset = null;
 | 
					        this.reset = null;
 | 
				
			||||||
        this._checkServerLiveliness(this.props.serverConfig);
 | 
					        this.checkServerLiveliness(this.props.serverConfig);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
 | 
					    // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
 | 
				
			||||||
    // eslint-disable-next-line camelcase
 | 
					    // eslint-disable-next-line camelcase
 | 
				
			||||||
    UNSAFE_componentWillReceiveProps(newProps) {
 | 
					    public UNSAFE_componentWillReceiveProps(newProps: IProps): void {
 | 
				
			||||||
        if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl &&
 | 
					        if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl &&
 | 
				
			||||||
            newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return;
 | 
					            newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Do a liveliness check on the new URLs
 | 
					        // Do a liveliness check on the new URLs
 | 
				
			||||||
        this._checkServerLiveliness(newProps.serverConfig);
 | 
					        this.checkServerLiveliness(newProps.serverConfig);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async _checkServerLiveliness(serverConfig) {
 | 
					    private async checkServerLiveliness(serverConfig): Promise<void> {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
 | 
					            await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
 | 
				
			||||||
                serverConfig.hsUrl,
 | 
					                serverConfig.hsUrl,
 | 
				
			||||||
@@ -98,28 +121,28 @@ export default class ForgotPassword extends React.Component {
 | 
				
			|||||||
                serverIsAlive: true,
 | 
					                serverIsAlive: true,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
            this.setState(AutoDiscoveryUtils.authComponentStateForError(e, "forgot_password"));
 | 
					            this.setState(AutoDiscoveryUtils.authComponentStateForError(e, "forgot_password") as IState);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    submitPasswordReset(email, password) {
 | 
					    public submitPasswordReset(email: string, password: string): void {
 | 
				
			||||||
        this.setState({
 | 
					        this.setState({
 | 
				
			||||||
            phase: PHASE_SENDING_EMAIL,
 | 
					            phase: Phase.SendingEmail,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        this.reset = new PasswordReset(this.props.serverConfig.hsUrl, this.props.serverConfig.isUrl);
 | 
					        this.reset = new PasswordReset(this.props.serverConfig.hsUrl, this.props.serverConfig.isUrl);
 | 
				
			||||||
        this.reset.resetPassword(email, password).then(() => {
 | 
					        this.reset.resetPassword(email, password).then(() => {
 | 
				
			||||||
            this.setState({
 | 
					            this.setState({
 | 
				
			||||||
                phase: PHASE_EMAIL_SENT,
 | 
					                phase: Phase.EmailSent,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }, (err) => {
 | 
					        }, (err) => {
 | 
				
			||||||
            this.showErrorDialog(_t('Failed to send email') + ": " + err.message);
 | 
					            this.showErrorDialog(_t('Failed to send email') + ": " + err.message);
 | 
				
			||||||
            this.setState({
 | 
					            this.setState({
 | 
				
			||||||
                phase: PHASE_FORGOT,
 | 
					                phase: Phase.Forgot,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onVerify = async ev => {
 | 
					    private onVerify = async (ev: React.MouseEvent): Promise<void> => {
 | 
				
			||||||
        ev.preventDefault();
 | 
					        ev.preventDefault();
 | 
				
			||||||
        if (!this.reset) {
 | 
					        if (!this.reset) {
 | 
				
			||||||
            console.error("onVerify called before submitPasswordReset!");
 | 
					            console.error("onVerify called before submitPasswordReset!");
 | 
				
			||||||
@@ -127,17 +150,17 @@ export default class ForgotPassword extends React.Component {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            await this.reset.checkEmailLinkClicked();
 | 
					            await this.reset.checkEmailLinkClicked();
 | 
				
			||||||
            this.setState({ phase: PHASE_DONE });
 | 
					            this.setState({ phase: Phase.Done });
 | 
				
			||||||
        } catch (err) {
 | 
					        } catch (err) {
 | 
				
			||||||
            this.showErrorDialog(err.message);
 | 
					            this.showErrorDialog(err.message);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onSubmitForm = async ev => {
 | 
					    private onSubmitForm = async (ev: React.FormEvent): Promise<void> => {
 | 
				
			||||||
        ev.preventDefault();
 | 
					        ev.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // refresh the server errors, just in case the server came back online
 | 
					        // refresh the server errors, just in case the server came back online
 | 
				
			||||||
        await this._checkServerLiveliness(this.props.serverConfig);
 | 
					        await this.checkServerLiveliness(this.props.serverConfig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await this['password_field'].validate({ allowEmpty: false });
 | 
					        await this['password_field'].validate({ allowEmpty: false });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -172,27 +195,27 @@ export default class ForgotPassword extends React.Component {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onInputChanged = (stateKey, ev) => {
 | 
					    private onInputChanged = (stateKey: string, ev: React.FormEvent<HTMLInputElement>) => {
 | 
				
			||||||
        this.setState({
 | 
					        this.setState({
 | 
				
			||||||
            [stateKey]: ev.target.value,
 | 
					            [stateKey]: ev.currentTarget.value,
 | 
				
			||||||
        });
 | 
					        } as any);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onLoginClick = ev => {
 | 
					    private onLoginClick = (ev: React.MouseEvent): void => {
 | 
				
			||||||
        ev.preventDefault();
 | 
					        ev.preventDefault();
 | 
				
			||||||
        ev.stopPropagation();
 | 
					        ev.stopPropagation();
 | 
				
			||||||
        this.props.onLoginClick();
 | 
					        this.props.onLoginClick();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    showErrorDialog(body, title) {
 | 
					    public showErrorDialog(description: string, title?: string) {
 | 
				
			||||||
        const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
 | 
					        const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
 | 
				
			||||||
        Modal.createTrackedDialog('Forgot Password Error', '', ErrorDialog, {
 | 
					        Modal.createTrackedDialog('Forgot Password Error', '', ErrorDialog, {
 | 
				
			||||||
            title: title,
 | 
					            title,
 | 
				
			||||||
            description: body,
 | 
					            description,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onPasswordValidate(result) {
 | 
					    private onPasswordValidate(result: IValidationResult) {
 | 
				
			||||||
        this.setState({
 | 
					        this.setState({
 | 
				
			||||||
            passwordFieldValid: result.valid,
 | 
					            passwordFieldValid: result.valid,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@@ -316,16 +339,16 @@ export default class ForgotPassword extends React.Component {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let resetPasswordJsx;
 | 
					        let resetPasswordJsx;
 | 
				
			||||||
        switch (this.state.phase) {
 | 
					        switch (this.state.phase) {
 | 
				
			||||||
            case PHASE_FORGOT:
 | 
					            case Phase.Forgot:
 | 
				
			||||||
                resetPasswordJsx = this.renderForgot();
 | 
					                resetPasswordJsx = this.renderForgot();
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case PHASE_SENDING_EMAIL:
 | 
					            case Phase.SendingEmail:
 | 
				
			||||||
                resetPasswordJsx = this.renderSendingEmail();
 | 
					                resetPasswordJsx = this.renderSendingEmail();
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case PHASE_EMAIL_SENT:
 | 
					            case Phase.EmailSent:
 | 
				
			||||||
                resetPasswordJsx = this.renderEmailSent();
 | 
					                resetPasswordJsx = this.renderEmailSent();
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case PHASE_DONE:
 | 
					            case Phase.Done:
 | 
				
			||||||
                resetPasswordJsx = this.renderDone();
 | 
					                resetPasswordJsx = this.renderDone();
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -17,15 +17,25 @@ limitations under the License.
 | 
				
			|||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import { _t } from "../../../languageHandler";
 | 
					import { _t } from "../../../languageHandler";
 | 
				
			||||||
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
 | 
					import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
 | 
				
			||||||
 | 
					import { IntegrationManagerInstance } from "../../../integrations/IntegrationManagerInstance";
 | 
				
			||||||
import * as sdk from '../../../index';
 | 
					import * as sdk from '../../../index';
 | 
				
			||||||
import SettingsStore from "../../../settings/SettingsStore";
 | 
					import SettingsStore from "../../../settings/SettingsStore";
 | 
				
			||||||
import { SettingLevel } from "../../../settings/SettingLevel";
 | 
					import { SettingLevel } from "../../../settings/SettingLevel";
 | 
				
			||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IProps {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IState {
 | 
				
			||||||
 | 
					    currentManager: IntegrationManagerInstance;
 | 
				
			||||||
 | 
					    provisioningEnabled: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("views.settings.SetIntegrationManager")
 | 
					@replaceableComponent("views.settings.SetIntegrationManager")
 | 
				
			||||||
export default class SetIntegrationManager extends React.Component {
 | 
					export default class SetIntegrationManager extends React.Component<IProps, IState> {
 | 
				
			||||||
    constructor() {
 | 
					    constructor(props: IProps) {
 | 
				
			||||||
        super();
 | 
					        super(props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const currentManager = IntegrationManagers.sharedInstance().getPrimaryManager();
 | 
					        const currentManager = IntegrationManagers.sharedInstance().getPrimaryManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,7 +45,7 @@ export default class SetIntegrationManager extends React.Component {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onProvisioningToggled = () => {
 | 
					    private onProvisioningToggled = (): void => {
 | 
				
			||||||
        const current = this.state.provisioningEnabled;
 | 
					        const current = this.state.provisioningEnabled;
 | 
				
			||||||
        SettingsStore.setValue("integrationProvisioning", null, SettingLevel.ACCOUNT, !current).catch(err => {
 | 
					        SettingsStore.setValue("integrationProvisioning", null, SettingLevel.ACCOUNT, !current).catch(err => {
 | 
				
			||||||
            console.error("Error changing integration manager provisioning");
 | 
					            console.error("Error changing integration manager provisioning");
 | 
				
			||||||
@@ -46,7 +56,7 @@ export default class SetIntegrationManager extends React.Component {
 | 
				
			|||||||
        this.setState({ provisioningEnabled: !current });
 | 
					        this.setState({ provisioningEnabled: !current });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    public render(): React.ReactNode {
 | 
				
			||||||
        const ToggleSwitch = sdk.getComponent("views.elements.ToggleSwitch");
 | 
					        const ToggleSwitch = sdk.getComponent("views.elements.ToggleSwitch");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const currentManager = this.state.currentManager;
 | 
					        const currentManager = this.state.currentManager;
 | 
				
			||||||
@@ -15,39 +15,48 @@ limitations under the License.
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
import PropTypes from "prop-types";
 | 
					 | 
				
			||||||
import { _t, pickBestLanguage } from "../../../languageHandler";
 | 
					import { _t, pickBestLanguage } from "../../../languageHandler";
 | 
				
			||||||
import * as sdk from "../../..";
 | 
					import * as sdk from "../../..";
 | 
				
			||||||
import { objectClone } from "../../../utils/objects";
 | 
					import { objectClone } from "../../../utils/objects";
 | 
				
			||||||
import StyledCheckbox from "../elements/StyledCheckbox";
 | 
					import StyledCheckbox from "../elements/StyledCheckbox";
 | 
				
			||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IProps {
 | 
				
			||||||
 | 
					    policiesAndServicePairs: any[];
 | 
				
			||||||
 | 
					    onFinished: (string) => void;
 | 
				
			||||||
 | 
					    agreedUrls: string[]; // array of URLs the user has accepted
 | 
				
			||||||
 | 
					    introElement: Node;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IState {
 | 
				
			||||||
 | 
					    policies: Policy[];
 | 
				
			||||||
 | 
					    busy: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Policy {
 | 
				
			||||||
 | 
					    checked: boolean;
 | 
				
			||||||
 | 
					    url: string;
 | 
				
			||||||
 | 
					    name: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("views.terms.InlineTermsAgreement")
 | 
					@replaceableComponent("views.terms.InlineTermsAgreement")
 | 
				
			||||||
export default class InlineTermsAgreement extends React.Component {
 | 
					export default class InlineTermsAgreement extends React.Component<IProps, IState> {
 | 
				
			||||||
    static propTypes = {
 | 
					    constructor(props: IProps) {
 | 
				
			||||||
        policiesAndServicePairs: PropTypes.array.isRequired, // array of service/policy pairs
 | 
					        super(props);
 | 
				
			||||||
        agreedUrls: PropTypes.array.isRequired, // array of URLs the user has accepted
 | 
					 | 
				
			||||||
        onFinished: PropTypes.func.isRequired, // takes an argument of accepted URLs
 | 
					 | 
				
			||||||
        introElement: PropTypes.node,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    constructor() {
 | 
					 | 
				
			||||||
        super();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.state = {
 | 
					        this.state = {
 | 
				
			||||||
            policies: [],
 | 
					            policies: [],
 | 
				
			||||||
            busy: false,
 | 
					            busy: false,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentDidMount() {
 | 
					    public componentDidMount(): void {
 | 
				
			||||||
        // Build all the terms the user needs to accept
 | 
					        // Build all the terms the user needs to accept
 | 
				
			||||||
        const policies = []; // { checked, url, name }
 | 
					        const policies = []; // { checked, url, name }
 | 
				
			||||||
        for (const servicePolicies of this.props.policiesAndServicePairs) {
 | 
					        for (const servicePolicies of this.props.policiesAndServicePairs) {
 | 
				
			||||||
            const availablePolicies = Object.values(servicePolicies.policies);
 | 
					            const availablePolicies = Object.values(servicePolicies.policies);
 | 
				
			||||||
            for (const policy of availablePolicies) {
 | 
					            for (const policy of availablePolicies) {
 | 
				
			||||||
                const language = pickBestLanguage(Object.keys(policy).filter(p => p !== 'version'));
 | 
					                const language = pickBestLanguage(Object.keys(policy).filter(p => p !== 'version'));
 | 
				
			||||||
                const renderablePolicy = {
 | 
					                const renderablePolicy: Policy = {
 | 
				
			||||||
                    checked: false,
 | 
					                    checked: false,
 | 
				
			||||||
                    url: policy[language].url,
 | 
					                    url: policy[language].url,
 | 
				
			||||||
                    name: policy[language].name,
 | 
					                    name: policy[language].name,
 | 
				
			||||||
@@ -59,13 +68,13 @@ export default class InlineTermsAgreement extends React.Component {
 | 
				
			|||||||
        this.setState({ policies });
 | 
					        this.setState({ policies });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _togglePolicy = (index) => {
 | 
					    private togglePolicy = (index: number): void => {
 | 
				
			||||||
        const policies = objectClone(this.state.policies);
 | 
					        const policies = objectClone(this.state.policies);
 | 
				
			||||||
        policies[index].checked = !policies[index].checked;
 | 
					        policies[index].checked = !policies[index].checked;
 | 
				
			||||||
        this.setState({ policies });
 | 
					        this.setState({ policies });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _onContinue = () => {
 | 
					    private onContinue = (): void => {
 | 
				
			||||||
        const hasUnchecked = !!this.state.policies.some(p => !p.checked);
 | 
					        const hasUnchecked = !!this.state.policies.some(p => !p.checked);
 | 
				
			||||||
        if (hasUnchecked) return;
 | 
					        if (hasUnchecked) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,7 +82,7 @@ export default class InlineTermsAgreement extends React.Component {
 | 
				
			|||||||
        this.props.onFinished(this.state.policies.map(p => p.url));
 | 
					        this.props.onFinished(this.state.policies.map(p => p.url));
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _renderCheckboxes() {
 | 
					    private renderCheckboxes(): React.ReactNode[] {
 | 
				
			||||||
        const rendered = [];
 | 
					        const rendered = [];
 | 
				
			||||||
        for (let i = 0; i < this.state.policies.length; i++) {
 | 
					        for (let i = 0; i < this.state.policies.length; i++) {
 | 
				
			||||||
            const policy = this.state.policies[i];
 | 
					            const policy = this.state.policies[i];
 | 
				
			||||||
@@ -93,7 +102,7 @@ export default class InlineTermsAgreement extends React.Component {
 | 
				
			|||||||
                <div key={i} className='mx_InlineTermsAgreement_cbContainer'>
 | 
					                <div key={i} className='mx_InlineTermsAgreement_cbContainer'>
 | 
				
			||||||
                    <div>{introText}</div>
 | 
					                    <div>{introText}</div>
 | 
				
			||||||
                    <div className='mx_InlineTermsAgreement_checkbox'>
 | 
					                    <div className='mx_InlineTermsAgreement_checkbox'>
 | 
				
			||||||
                        <StyledCheckbox onChange={() => this._togglePolicy(i)} checked={policy.checked}>
 | 
					                        <StyledCheckbox onChange={() => this.togglePolicy(i)} checked={policy.checked}>
 | 
				
			||||||
                            {_t("Accept")}
 | 
					                            {_t("Accept")}
 | 
				
			||||||
                        </StyledCheckbox>
 | 
					                        </StyledCheckbox>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
@@ -103,16 +112,16 @@ export default class InlineTermsAgreement extends React.Component {
 | 
				
			|||||||
        return rendered;
 | 
					        return rendered;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    public render(): React.ReactNode {
 | 
				
			||||||
        const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
 | 
					        const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
 | 
				
			||||||
        const hasUnchecked = !!this.state.policies.some(p => !p.checked);
 | 
					        const hasUnchecked = !!this.state.policies.some(p => !p.checked);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div>
 | 
					            <div>
 | 
				
			||||||
                {this.props.introElement}
 | 
					                {this.props.introElement}
 | 
				
			||||||
                {this._renderCheckboxes()}
 | 
					                {this.renderCheckboxes()}
 | 
				
			||||||
                <AccessibleButton
 | 
					                <AccessibleButton
 | 
				
			||||||
                    onClick={this._onContinue}
 | 
					                    onClick={this.onContinue}
 | 
				
			||||||
                    disabled={hasUnchecked || this.state.busy}
 | 
					                    disabled={hasUnchecked || this.state.busy}
 | 
				
			||||||
                    kind="primary_sm"
 | 
					                    kind="primary_sm"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
@@ -15,18 +15,17 @@ 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 { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("views.verification.VerificationCancelled")
 | 
					interface IProps {
 | 
				
			||||||
export default class VerificationCancelled extends React.Component {
 | 
					    onDone: () => void;
 | 
				
			||||||
    static propTypes = {
 | 
					 | 
				
			||||||
        onDone: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					@replaceableComponent("views.verification.VerificationCancelled")
 | 
				
			||||||
 | 
					export default class VerificationCancelled extends React.Component<IProps> {
 | 
				
			||||||
 | 
					    public render(): React.ReactNode {
 | 
				
			||||||
        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
 | 
					        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
 | 
				
			||||||
        return <div>
 | 
					        return <div>
 | 
				
			||||||
            <p>{_t(
 | 
					            <p>{_t(
 | 
				
			||||||
@@ -15,18 +15,17 @@ 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 { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("views.verification.VerificationComplete")
 | 
					interface IProps {
 | 
				
			||||||
export default class VerificationComplete extends React.Component {
 | 
					    onDone: () => void;
 | 
				
			||||||
    static propTypes = {
 | 
					 | 
				
			||||||
        onDone: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					@replaceableComponent("views.verification.VerificationComplete")
 | 
				
			||||||
 | 
					export default class VerificationComplete extends React.Component<IProps> {
 | 
				
			||||||
 | 
					    public render(): React.ReactNode {
 | 
				
			||||||
        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
 | 
					        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
 | 
				
			||||||
        return <div>
 | 
					        return <div>
 | 
				
			||||||
            <h2>{_t("Verified!")}</h2>
 | 
					            <h2>{_t("Verified!")}</h2>
 | 
				
			||||||
@@ -1,68 +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 AccessibleButton from "../elements/AccessibleButton";
 | 
					 | 
				
			||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					 | 
				
			||||||
import VerificationQRCode from "../elements/crypto/VerificationQRCode";
 | 
					 | 
				
			||||||
import Spinner from "../elements/Spinner";
 | 
					 | 
				
			||||||
import { SCAN_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@replaceableComponent("views.verification.VerificationQREmojiOptions")
 | 
					 | 
				
			||||||
export default class VerificationQREmojiOptions extends React.Component {
 | 
					 | 
				
			||||||
    static propTypes = {
 | 
					 | 
				
			||||||
        request: PropTypes.object.isRequired,
 | 
					 | 
				
			||||||
        onCancel: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
        onStartEmoji: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render() {
 | 
					 | 
				
			||||||
        const { request } = this.props;
 | 
					 | 
				
			||||||
        const showQR = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let qrCode;
 | 
					 | 
				
			||||||
        if (showQR) {
 | 
					 | 
				
			||||||
            qrCode = <VerificationQRCode qrCodeData={request.qrCodeData} />;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            qrCode = <div className='mx_VerificationQREmojiOptions_noQR'><Spinner /></div>;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return (
 | 
					 | 
				
			||||||
            <div>
 | 
					 | 
				
			||||||
                {_t("Verify this session by completing one of the following:")}
 | 
					 | 
				
			||||||
                <div className='mx_IncomingSasDialog_startOptions'>
 | 
					 | 
				
			||||||
                    <div className='mx_IncomingSasDialog_startOption'>
 | 
					 | 
				
			||||||
                        <p>{_t("Scan this unique code")}</p>
 | 
					 | 
				
			||||||
                        {qrCode}
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    <div className='mx_IncomingSasDialog_betweenText'>{_t("or")}</div>
 | 
					 | 
				
			||||||
                    <div className='mx_IncomingSasDialog_startOption'>
 | 
					 | 
				
			||||||
                        <p>{_t("Compare unique emoji")}</p>
 | 
					 | 
				
			||||||
                        <span className='mx_IncomingSasDialog_helpText'>{_t("Compare a unique set of emoji if you don't have a camera on either device")}</span>
 | 
					 | 
				
			||||||
                        <AccessibleButton onClick={this.props.onStartEmoji} kind='primary'>
 | 
					 | 
				
			||||||
                            {_t("Start")}
 | 
					 | 
				
			||||||
                        </AccessibleButton>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <AccessibleButton onClick={this.props.onCancel} kind='danger'>
 | 
					 | 
				
			||||||
                    {_t("Cancel")}
 | 
					 | 
				
			||||||
                </AccessibleButton>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -15,7 +15,8 @@ limitations under the License.
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import { SAS } from "matrix-js-sdk/src/crypto/verification/SAS";
 | 
				
			||||||
 | 
					import { DeviceInfo } from "matrix-js-sdk/src//crypto/deviceinfo";
 | 
				
			||||||
import { _t, _td } from '../../../languageHandler';
 | 
					import { _t, _td } from '../../../languageHandler';
 | 
				
			||||||
import { PendingActionSpinner } from "../right_panel/EncryptionInfo";
 | 
					import { PendingActionSpinner } from "../right_panel/EncryptionInfo";
 | 
				
			||||||
import AccessibleButton from "../elements/AccessibleButton";
 | 
					import AccessibleButton from "../elements/AccessibleButton";
 | 
				
			||||||
@@ -23,24 +24,29 @@ import DialogButtons from "../elements/DialogButtons";
 | 
				
			|||||||
import { fixupColorFonts } from '../../../utils/FontManager';
 | 
					import { fixupColorFonts } from '../../../utils/FontManager';
 | 
				
			||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
					import { replaceableComponent } from "../../../utils/replaceableComponent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IProps {
 | 
				
			||||||
 | 
					    pending?: boolean;
 | 
				
			||||||
 | 
					    displayName?: string; // required if pending is true
 | 
				
			||||||
 | 
					    device?: DeviceInfo;
 | 
				
			||||||
 | 
					    onDone: () => void;
 | 
				
			||||||
 | 
					    onCancel: () => void;
 | 
				
			||||||
 | 
					    sas: SAS.sas;
 | 
				
			||||||
 | 
					    isSelf?: boolean;
 | 
				
			||||||
 | 
					    inDialog?: boolean; // whether this component is being shown in a dialog and to use DialogButtons
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IState {
 | 
				
			||||||
 | 
					    pending: boolean;
 | 
				
			||||||
 | 
					    cancelling?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function capFirst(s) {
 | 
					function capFirst(s) {
 | 
				
			||||||
    return s.charAt(0).toUpperCase() + s.slice(1);
 | 
					    return s.charAt(0).toUpperCase() + s.slice(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@replaceableComponent("views.verification.VerificationShowSas")
 | 
					@replaceableComponent("views.verification.VerificationShowSas")
 | 
				
			||||||
export default class VerificationShowSas extends React.Component {
 | 
					export default class VerificationShowSas extends React.Component<IProps, IState> {
 | 
				
			||||||
    static propTypes = {
 | 
					    constructor(props: IProps) {
 | 
				
			||||||
        pending: PropTypes.bool,
 | 
					 | 
				
			||||||
        displayName: PropTypes.string, // required if pending is true
 | 
					 | 
				
			||||||
        device: PropTypes.object,
 | 
					 | 
				
			||||||
        onDone: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
        onCancel: PropTypes.func.isRequired,
 | 
					 | 
				
			||||||
        sas: PropTypes.object.isRequired,
 | 
					 | 
				
			||||||
        isSelf: PropTypes.bool,
 | 
					 | 
				
			||||||
        inDialog: PropTypes.bool, // whether this component is being shown in a dialog and to use DialogButtons
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    constructor(props) {
 | 
					 | 
				
			||||||
        super(props);
 | 
					        super(props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.state = {
 | 
					        this.state = {
 | 
				
			||||||
@@ -48,19 +54,19 @@ export default class VerificationShowSas extends React.Component {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentWillMount() {
 | 
					    public componentWillMount(): void {
 | 
				
			||||||
        // As this component is also used before login (during complete security),
 | 
					        // As this component is also used before login (during complete security),
 | 
				
			||||||
        // also make sure we have a working emoji font to display the SAS emojis here.
 | 
					        // also make sure we have a working emoji font to display the SAS emojis here.
 | 
				
			||||||
        // This is also done from LoggedInView.
 | 
					        // This is also done from LoggedInView.
 | 
				
			||||||
        fixupColorFonts();
 | 
					        fixupColorFonts();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onMatchClick = () => {
 | 
					    private onMatchClick = (): void => {
 | 
				
			||||||
        this.setState({ pending: true });
 | 
					        this.setState({ pending: true });
 | 
				
			||||||
        this.props.onDone();
 | 
					        this.props.onDone();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onDontMatchClick = () => {
 | 
					    private onDontMatchClick = (): void => {
 | 
				
			||||||
        this.setState({ cancelling: true });
 | 
					        this.setState({ cancelling: true });
 | 
				
			||||||
        this.props.onCancel();
 | 
					        this.props.onCancel();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -923,12 +923,6 @@
 | 
				
			|||||||
    "You've successfully verified this user.": "You've successfully verified this user.",
 | 
					    "You've successfully verified this user.": "You've successfully verified this user.",
 | 
				
			||||||
    "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.",
 | 
					    "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.": "Secure messages with this user are end-to-end encrypted and not able to be read by third parties.",
 | 
				
			||||||
    "Got It": "Got It",
 | 
					    "Got It": "Got It",
 | 
				
			||||||
    "Verify this session by completing one of the following:": "Verify this session by completing one of the following:",
 | 
					 | 
				
			||||||
    "Scan this unique code": "Scan this unique code",
 | 
					 | 
				
			||||||
    "or": "or",
 | 
					 | 
				
			||||||
    "Compare unique emoji": "Compare unique emoji",
 | 
					 | 
				
			||||||
    "Compare a unique set of emoji if you don't have a camera on either device": "Compare a unique set of emoji if you don't have a camera on either device",
 | 
					 | 
				
			||||||
    "Start": "Start",
 | 
					 | 
				
			||||||
    "Confirm the emoji below are displayed on both sessions, in the same order:": "Confirm the emoji below are displayed on both sessions, in the same order:",
 | 
					    "Confirm the emoji below are displayed on both sessions, in the same order:": "Confirm the emoji below are displayed on both sessions, in the same order:",
 | 
				
			||||||
    "Verify this user by confirming the following emoji appear on their screen.": "Verify this user by confirming the following emoji appear on their screen.",
 | 
					    "Verify this user by confirming the following emoji appear on their screen.": "Verify this user by confirming the following emoji appear on their screen.",
 | 
				
			||||||
    "Verify this session by confirming the following number appears on its screen.": "Verify this session by confirming the following number appears on its screen.",
 | 
					    "Verify this session by confirming the following number appears on its screen.": "Verify this session by confirming the following number appears on its screen.",
 | 
				
			||||||
@@ -1833,6 +1827,12 @@
 | 
				
			|||||||
    "Edit devices": "Edit devices",
 | 
					    "Edit devices": "Edit devices",
 | 
				
			||||||
    "Security": "Security",
 | 
					    "Security": "Security",
 | 
				
			||||||
    "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.",
 | 
					    "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.",
 | 
				
			||||||
 | 
					    "Scan this unique code": "Scan this unique code",
 | 
				
			||||||
 | 
					    "Compare unique emoji": "Compare unique emoji",
 | 
				
			||||||
 | 
					    "Compare a unique set of emoji if you don't have a camera on either device": "Compare a unique set of emoji if you don't have a camera on either device",
 | 
				
			||||||
 | 
					    "Start": "Start",
 | 
				
			||||||
 | 
					    "or": "or",
 | 
				
			||||||
 | 
					    "Verify this session by completing one of the following:": "Verify this session by completing one of the following:",
 | 
				
			||||||
    "Verify by scanning": "Verify by scanning",
 | 
					    "Verify by scanning": "Verify by scanning",
 | 
				
			||||||
    "Ask %(displayName)s to scan your code:": "Ask %(displayName)s to scan your code:",
 | 
					    "Ask %(displayName)s to scan your code:": "Ask %(displayName)s to scan your code:",
 | 
				
			||||||
    "If you can't scan the code above, verify by comparing unique emoji.": "If you can't scan the code above, verify by comparing unique emoji.",
 | 
					    "If you can't scan the code above, verify by comparing unique emoji.": "If you can't scan the code above, verify by comparing unique emoji.",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,15 +20,25 @@ import { StandardActions } from "./StandardActions";
 | 
				
			|||||||
import { PushRuleVectorState } from "./PushRuleVectorState";
 | 
					import { PushRuleVectorState } from "./PushRuleVectorState";
 | 
				
			||||||
import { NotificationUtils } from "./NotificationUtils";
 | 
					import { NotificationUtils } from "./NotificationUtils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IProps {
 | 
				
			||||||
 | 
					    kind: Kind;
 | 
				
			||||||
 | 
					    description: string;
 | 
				
			||||||
 | 
					    vectorStateToActions: Action;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VectorPushRuleDefinition {
 | 
					class VectorPushRuleDefinition {
 | 
				
			||||||
    constructor(opts) {
 | 
					    private kind: Kind;
 | 
				
			||||||
 | 
					    private description: string;
 | 
				
			||||||
 | 
					    private vectorStateToActions: Action;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(opts: IProps) {
 | 
				
			||||||
        this.kind = opts.kind;
 | 
					        this.kind = opts.kind;
 | 
				
			||||||
        this.description = opts.description;
 | 
					        this.description = opts.description;
 | 
				
			||||||
        this.vectorStateToActions = opts.vectorStateToActions;
 | 
					        this.vectorStateToActions = opts.vectorStateToActions;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Translate the rule actions and its enabled value into vector state
 | 
					    // Translate the rule actions and its enabled value into vector state
 | 
				
			||||||
    ruleToVectorState(rule) {
 | 
					    public ruleToVectorState(rule): VectorPushRuleDefinition {
 | 
				
			||||||
        let enabled = false;
 | 
					        let enabled = false;
 | 
				
			||||||
        if (rule) {
 | 
					        if (rule) {
 | 
				
			||||||
            enabled = rule.enabled;
 | 
					            enabled = rule.enabled;
 | 
				
			||||||
@@ -63,13 +73,24 @@ class VectorPushRuleDefinition {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum Kind {
 | 
				
			||||||
 | 
					    Override = "override",
 | 
				
			||||||
 | 
					    Underride = "underride",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Action {
 | 
				
			||||||
 | 
					    on: StandardActions;
 | 
				
			||||||
 | 
					    loud: StandardActions;
 | 
				
			||||||
 | 
					    off: StandardActions;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The descriptions of rules managed by the Vector UI.
 | 
					 * The descriptions of rules managed by the Vector UI.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const VectorPushRulesDefinitions = {
 | 
					export const VectorPushRulesDefinitions = {
 | 
				
			||||||
    // Messages containing user's display name
 | 
					    // Messages containing user's display name
 | 
				
			||||||
    ".m.rule.contains_display_name": new VectorPushRuleDefinition({
 | 
					    ".m.rule.contains_display_name": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "override",
 | 
					        kind: Kind.Override,
 | 
				
			||||||
        description: _td("Messages containing my display name"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Messages containing my display name"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
					        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -80,7 +101,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Messages containing user's username (localpart/MXID)
 | 
					    // Messages containing user's username (localpart/MXID)
 | 
				
			||||||
    ".m.rule.contains_user_name": new VectorPushRuleDefinition({
 | 
					    ".m.rule.contains_user_name": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "override",
 | 
					        kind: Kind.Override,
 | 
				
			||||||
        description: _td("Messages containing my username"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Messages containing my username"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
					        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -91,7 +112,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Messages containing @room
 | 
					    // Messages containing @room
 | 
				
			||||||
    ".m.rule.roomnotif": new VectorPushRuleDefinition({
 | 
					    ".m.rule.roomnotif": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "override",
 | 
					        kind: Kind.Override,
 | 
				
			||||||
        description: _td("Messages containing @room"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Messages containing @room"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
					        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -102,7 +123,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Messages just sent to the user in a 1:1 room
 | 
					    // Messages just sent to the user in a 1:1 room
 | 
				
			||||||
    ".m.rule.room_one_to_one": new VectorPushRuleDefinition({
 | 
					    ".m.rule.room_one_to_one": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "underride",
 | 
					        kind: Kind.Underride,
 | 
				
			||||||
        description: _td("Messages in one-to-one chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Messages in one-to-one chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: {
 | 
					        vectorStateToActions: {
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -113,7 +134,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Encrypted messages just sent to the user in a 1:1 room
 | 
					    // Encrypted messages just sent to the user in a 1:1 room
 | 
				
			||||||
    ".m.rule.encrypted_room_one_to_one": new VectorPushRuleDefinition({
 | 
					    ".m.rule.encrypted_room_one_to_one": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "underride",
 | 
					        kind: Kind.Underride,
 | 
				
			||||||
        description: _td("Encrypted messages in one-to-one chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Encrypted messages in one-to-one chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: {
 | 
					        vectorStateToActions: {
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -126,7 +147,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
    // 1:1 room messages are catched by the .m.rule.room_one_to_one rule if any defined
 | 
					    // 1:1 room messages are catched by the .m.rule.room_one_to_one rule if any defined
 | 
				
			||||||
    // By opposition, all other room messages are from group chat rooms.
 | 
					    // By opposition, all other room messages are from group chat rooms.
 | 
				
			||||||
    ".m.rule.message": new VectorPushRuleDefinition({
 | 
					    ".m.rule.message": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "underride",
 | 
					        kind: Kind.Underride,
 | 
				
			||||||
        description: _td("Messages in group chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Messages in group chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: {
 | 
					        vectorStateToActions: {
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -139,7 +160,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
    // Encrypted 1:1 room messages are catched by the .m.rule.encrypted_room_one_to_one rule if any defined
 | 
					    // Encrypted 1:1 room messages are catched by the .m.rule.encrypted_room_one_to_one rule if any defined
 | 
				
			||||||
    // By opposition, all other room messages are from group chat rooms.
 | 
					    // By opposition, all other room messages are from group chat rooms.
 | 
				
			||||||
    ".m.rule.encrypted": new VectorPushRuleDefinition({
 | 
					    ".m.rule.encrypted": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "underride",
 | 
					        kind: Kind.Underride,
 | 
				
			||||||
        description: _td("Encrypted messages in group chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Encrypted messages in group chats"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: {
 | 
					        vectorStateToActions: {
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -150,7 +171,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Invitation for the user
 | 
					    // Invitation for the user
 | 
				
			||||||
    ".m.rule.invite_for_me": new VectorPushRuleDefinition({
 | 
					    ".m.rule.invite_for_me": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "underride",
 | 
					        kind: Kind.Underride,
 | 
				
			||||||
        description: _td("When I'm invited to a room"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("When I'm invited to a room"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: {
 | 
					        vectorStateToActions: {
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -161,7 +182,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Incoming call
 | 
					    // Incoming call
 | 
				
			||||||
    ".m.rule.call": new VectorPushRuleDefinition({
 | 
					    ".m.rule.call": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "underride",
 | 
					        kind: Kind.Underride,
 | 
				
			||||||
        description: _td("Call invitation"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Call invitation"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: {
 | 
					        vectorStateToActions: {
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -172,7 +193,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Notifications from bots
 | 
					    // Notifications from bots
 | 
				
			||||||
    ".m.rule.suppress_notices": new VectorPushRuleDefinition({
 | 
					    ".m.rule.suppress_notices": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "override",
 | 
					        kind: Kind.Override,
 | 
				
			||||||
        description: _td("Messages sent by bot"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("Messages sent by bot"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: {
 | 
					        vectorStateToActions: {
 | 
				
			||||||
            // .m.rule.suppress_notices is a "negative" rule, we have to invert its enabled value for vector UI
 | 
					            // .m.rule.suppress_notices is a "negative" rule, we have to invert its enabled value for vector UI
 | 
				
			||||||
@@ -184,7 +205,7 @@ export const VectorPushRulesDefinitions = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Room upgrades (tombstones)
 | 
					    // Room upgrades (tombstones)
 | 
				
			||||||
    ".m.rule.tombstone": new VectorPushRuleDefinition({
 | 
					    ".m.rule.tombstone": new VectorPushRuleDefinition({
 | 
				
			||||||
        kind: "override",
 | 
					        kind: Kind.Override,
 | 
				
			||||||
        description: _td("When rooms are upgraded"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
					        description: _td("When rooms are upgraded"), // passed through _t() translation in src/components/views/settings/Notifications.js
 | 
				
			||||||
        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
					        vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
 | 
				
			||||||
            on: StandardActions.ACTION_NOTIFY,
 | 
					            on: StandardActions.ACTION_NOTIFY,
 | 
				
			||||||
@@ -1,50 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
Copyright 2017 New Vector Ltd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Stores where the user has scrolled to in each room
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class RoomScrollStateStore {
 | 
					 | 
				
			||||||
    constructor() {
 | 
					 | 
				
			||||||
        // A map from room id to scroll state.
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        // If there is no special scroll state (ie, we are following the live
 | 
					 | 
				
			||||||
        // timeline), the scroll state is null. Otherwise, it is an object with
 | 
					 | 
				
			||||||
        // the following properties:
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        //    focussedEvent: the ID of the 'focussed' event. Typically this is
 | 
					 | 
				
			||||||
        //        the last event fully visible in the viewport, though if we
 | 
					 | 
				
			||||||
        //        have done an explicit scroll to an explicit event, it will be
 | 
					 | 
				
			||||||
        //        that event.
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        //    pixelOffset: the number of pixels the window is scrolled down
 | 
					 | 
				
			||||||
        //        from the focussedEvent.
 | 
					 | 
				
			||||||
        this._scrollStateMap = {};
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    getScrollState(roomId) {
 | 
					 | 
				
			||||||
        return this._scrollStateMap[roomId];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setScrollState(roomId, scrollState) {
 | 
					 | 
				
			||||||
        this._scrollStateMap[roomId] = scrollState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (global.mx_RoomScrollStateStore === undefined) {
 | 
					 | 
				
			||||||
    global.mx_RoomScrollStateStore = new RoomScrollStateStore();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export default global.mx_RoomScrollStateStore;
 | 
					 | 
				
			||||||
							
								
								
									
										53
									
								
								src/stores/RoomScrollStateStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/stores/RoomScrollStateStore.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 New Vector Ltd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ScrollState {
 | 
				
			||||||
 | 
					    focussedEvent: string;
 | 
				
			||||||
 | 
					    pixelOffset: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Stores where the user has scrolled to in each room
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export class RoomScrollStateStore {
 | 
				
			||||||
 | 
					    // A map from room id to scroll state.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // If there is no special scroll state (ie, we are following the live
 | 
				
			||||||
 | 
					    // timeline), the scroll state is null. Otherwise, it is an object with
 | 
				
			||||||
 | 
					    // the following properties:
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    //    focussedEvent: the ID of the 'focussed' event. Typically this is
 | 
				
			||||||
 | 
					    //        the last event fully visible in the viewport, though if we
 | 
				
			||||||
 | 
					    //        have done an explicit scroll to an explicit event, it will be
 | 
				
			||||||
 | 
					    //        that event.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    //    pixelOffset: the number of pixels the window is scrolled down
 | 
				
			||||||
 | 
					    //        from the focussedEvent.
 | 
				
			||||||
 | 
					    private scrollStateMap = new Map<string, ScrollState>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public getScrollState(roomId: string): ScrollState {
 | 
				
			||||||
 | 
					        return this.scrollStateMap.get(roomId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setScrollState(roomId: string, scrollState: ScrollState): void {
 | 
				
			||||||
 | 
					        this.scrollStateMap.set(roomId, scrollState);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (window.mxRoomScrollStateStore === undefined) {
 | 
				
			||||||
 | 
					    window.mxRoomScrollStateStore = new RoomScrollStateStore();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export default window.mxRoomScrollStateStore;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user