Merge branch 'develop' of https://github.com/matrix-org/matrix-react-sdk into joriks/irc-ui
This commit is contained in:
commit
323d0762fc
189 changed files with 2091 additions and 976 deletions
|
@ -18,7 +18,7 @@ import React from 'react';
|
|||
import CustomRoomTagStore from '../../stores/CustomRoomTagStore';
|
||||
import AutoHideScrollbar from './AutoHideScrollbar';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import classNames from 'classnames';
|
||||
import * as FormattingUtils from '../../utils/FormattingUtils';
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import PropTypes from 'prop-types';
|
|||
import request from 'browser-request';
|
||||
import { _t } from '../../languageHandler';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import classnames from 'classnames';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
|
|
|
@ -21,7 +21,7 @@ import createReactClass from 'create-react-class';
|
|||
import PropTypes from 'prop-types';
|
||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import { getHostingLink } from '../../utils/HostingLink';
|
||||
import { sanitizedHtmlNode } from '../../HtmlUtils';
|
||||
import { _t, _td } from '../../languageHandler';
|
||||
|
|
|
@ -21,7 +21,7 @@ import { getHomePageUrl } from "../../utils/pages";
|
|||
import { _t } from "../../languageHandler";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import * as sdk from "../../index";
|
||||
import dis from "../../dispatcher";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
|
||||
const onClickSendDm = () => dis.dispatch({action: 'view_create_chat'});
|
||||
const onClickExplore = () => dis.dispatch({action: 'view_room_directory'});
|
||||
|
|
|
@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import classNames from 'classnames';
|
||||
import { Key } from '../../Keyboard';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import * as VectorConferenceHandler from '../../VectorConferenceHandler';
|
||||
import SettingsStore from '../../settings/SettingsStore';
|
||||
import {_t} from "../../languageHandler";
|
||||
|
|
|
@ -27,7 +27,7 @@ import PageTypes from '../../PageTypes';
|
|||
import CallMediaHandler from '../../CallMediaHandler';
|
||||
import { fixupColorFonts } from '../../utils/FontManager';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import sessionStore from '../../stores/SessionStore';
|
||||
import {MatrixClientPeg, MatrixClientCreds} from '../../MatrixClientPeg';
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
|
|
@ -17,12 +17,11 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, {createRef} from 'react';
|
||||
import {InvalidStoreError} from "matrix-js-sdk/src/errors";
|
||||
import {RoomMember} from "matrix-js-sdk/src/models/room-member";
|
||||
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
|
||||
import React, { createRef } from 'react';
|
||||
import { InvalidStoreError } from "matrix-js-sdk/src/errors";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { isCryptoAvailable } from 'matrix-js-sdk/src/crypto';
|
||||
|
||||
// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss
|
||||
import 'focus-visible';
|
||||
// what-input helps improve keyboard accessibility
|
||||
|
@ -30,17 +29,17 @@ import 'what-input';
|
|||
|
||||
import Analytics from "../../Analytics";
|
||||
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
|
||||
import {MatrixClientPeg} from "../../MatrixClientPeg";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import PlatformPeg from "../../PlatformPeg";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import * as RoomListSorter from "../../RoomListSorter";
|
||||
import dis from "../../dispatcher";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import Notifier from '../../Notifier';
|
||||
|
||||
import Modal from "../../Modal";
|
||||
import Tinter from "../../Tinter";
|
||||
import * as sdk from '../../index';
|
||||
import { showStartChatInviteDialog, showRoomInviteDialog } from '../../RoomInvite';
|
||||
import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
|
||||
import * as Rooms from '../../Rooms';
|
||||
import linkifyMatrix from "../../linkify-matrix";
|
||||
import * as Lifecycle from '../../Lifecycle';
|
||||
|
@ -52,21 +51,22 @@ import { getHomePageUrl } from '../../utils/pages';
|
|||
import createRoom from "../../createRoom";
|
||||
import KeyRequestHandler from '../../KeyRequestHandler';
|
||||
import { _t, getCurrentLanguage } from '../../languageHandler';
|
||||
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
|
||||
import SettingsStore, { SettingLevel } from "../../settings/SettingsStore";
|
||||
import ThemeController from "../../settings/controllers/ThemeController";
|
||||
import { startAnyRegistrationFlow } from "../../Registration.js";
|
||||
import { messageForSyncError } from '../../utils/ErrorUtils';
|
||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||
import { ValidatedServerConfig } from "../../utils/AutoDiscoveryUtils";
|
||||
import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils";
|
||||
import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../utils/AutoDiscoveryUtils";
|
||||
import DMRoomMap from '../../utils/DMRoomMap';
|
||||
import { countRoomsWithNotif } from '../../RoomNotifs';
|
||||
import { ThemeWatcher } from "../../theme";
|
||||
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
||||
import {defer, IDeferred} from "../../utils/promise";
|
||||
import { defer, IDeferred } from "../../utils/promise";
|
||||
import ToastStore from "../../stores/ToastStore";
|
||||
import * as StorageManager from "../../utils/StorageManager";
|
||||
import type LoggedInViewType from "./LoggedInView";
|
||||
import { ViewUserPayload } from "../../dispatcher/payloads/ViewUserPayload";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
|
||||
/** constants for MatrixChat.state.view */
|
||||
export enum Views {
|
||||
|
@ -107,7 +107,7 @@ export enum Views {
|
|||
// re-dispatched. NOTE: some actions are non-trivial and would require
|
||||
// re-factoring to be included in this list in future.
|
||||
const ONBOARDING_FLOW_STARTERS = [
|
||||
'view_user_settings',
|
||||
Action.ViewUserSettings,
|
||||
'view_create_chat',
|
||||
'view_create_room',
|
||||
'view_create_group',
|
||||
|
@ -613,7 +613,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
case 'view_indexed_room':
|
||||
this.viewIndexedRoom(payload.roomIndex);
|
||||
break;
|
||||
case 'view_user_settings': {
|
||||
case Action.ViewUserSettings: {
|
||||
const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
|
||||
Modal.createTrackedDialog('User settings', '', UserSettingsDialog, {},
|
||||
/*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
||||
|
@ -1621,9 +1621,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
action: 'view_create_room',
|
||||
});
|
||||
} else if (screen === 'settings') {
|
||||
dis.dispatch({
|
||||
action: 'view_user_settings',
|
||||
});
|
||||
dis.fire(Action.ViewUserSettings);
|
||||
} else if (screen === 'welcome') {
|
||||
dis.dispatch({
|
||||
action: 'view_welcome_page',
|
||||
|
@ -1755,8 +1753,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
|
||||
const member = new RoomMember(null, userId);
|
||||
if (!member) { return; }
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
dis.dispatch<ViewUserPayload>({
|
||||
action: Action.ViewUser,
|
||||
member: member,
|
||||
});
|
||||
}
|
||||
|
@ -1973,6 +1971,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
render() {
|
||||
// console.log(`Rendering MatrixChat with view ${this.state.view}`);
|
||||
|
||||
let fragmentAfterLogin = "";
|
||||
if (this.props.initialScreenAfterLogin) {
|
||||
fragmentAfterLogin = `/${this.props.initialScreenAfterLogin.screen}`;
|
||||
}
|
||||
|
||||
let view;
|
||||
|
||||
if (this.state.view === Views.LOADING) {
|
||||
|
@ -2052,7 +2055,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
} else if (this.state.view === Views.WELCOME) {
|
||||
const Welcome = sdk.getComponent('auth.Welcome');
|
||||
view = <Welcome {...this.getServerProperties()} />;
|
||||
view = <Welcome {...this.getServerProperties()} fragmentAfterLogin={fragmentAfterLogin} />;
|
||||
} else if (this.state.view === Views.REGISTER) {
|
||||
const Registration = sdk.getComponent('structures.auth.Registration');
|
||||
view = (
|
||||
|
@ -2091,6 +2094,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
|
||||
onForgotPasswordClick={this.onForgotPasswordClick}
|
||||
onServerConfigChange={this.onServerConfigChange}
|
||||
fragmentAfterLogin={fragmentAfterLogin}
|
||||
{...this.getServerProperties()}
|
||||
/>
|
||||
);
|
||||
|
@ -2100,6 +2104,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
<SoftLogout
|
||||
realQueryParams={this.props.realQueryParams}
|
||||
onTokenLoginCompleted={this.props.onTokenLoginCompleted}
|
||||
fragmentAfterLogin={fragmentAfterLogin}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -19,7 +19,7 @@ import React from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../index';
|
||||
import { _t } from '../../languageHandler';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import AccessibleButton from '../views/elements/AccessibleButton';
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "./AutoHideScrollbar";
|
||||
|
|
|
@ -22,7 +22,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import RateLimitedFunc from '../../ratelimitedfunc';
|
||||
import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
||||
import GroupStore from '../../stores/GroupStore';
|
||||
|
@ -30,6 +30,7 @@ import SettingsStore from "../../settings/SettingsStore";
|
|||
import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases";
|
||||
import RightPanelStore from "../../stores/RightPanelStore";
|
||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||
import {Action} from "../../dispatcher/actions";
|
||||
|
||||
export default class RightPanel extends React.Component {
|
||||
static get propTypes() {
|
||||
|
@ -237,7 +238,7 @@ export default class RightPanel extends React.Component {
|
|||
// within a room, so go back to the member panel if we were in the encryption panel,
|
||||
// or the member list if we were in the member panel... phew.
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ?
|
||||
this.state.member : null,
|
||||
});
|
||||
|
@ -266,7 +267,7 @@ export default class RightPanel extends React.Component {
|
|||
if (SettingsStore.getValue("feature_cross_signing")) {
|
||||
const onClose = () => {
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import {MatrixClientPeg} from "../../MatrixClientPeg";
|
||||
import * as sdk from "../../index";
|
||||
import dis from "../../dispatcher";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import Modal from "../../Modal";
|
||||
import { linkifyAndSanitizeHtml } from '../../HtmlUtils';
|
||||
import PropTypes from 'prop-types';
|
||||
|
|
|
@ -25,7 +25,7 @@ import * as sdk from '../../index';
|
|||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import Resend from '../../Resend';
|
||||
import * as cryptodevices from '../../cryptodevices';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import {messageForResourceLimitError, messageForSendError} from '../../utils/ErrorUtils';
|
||||
|
||||
const STATUS_BAR_HIDDEN = 0;
|
||||
|
|
|
@ -20,7 +20,7 @@ limitations under the License.
|
|||
import React, {createRef} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import * as Unread from '../../Unread';
|
||||
import * as RoomNotifs from '../../RoomNotifs';
|
||||
import * as FormattingUtils from '../../utils/FormattingUtils';
|
||||
|
|
|
@ -34,14 +34,14 @@ import ContentMessages from '../../ContentMessages';
|
|||
import Modal from '../../Modal';
|
||||
import * as sdk from '../../index';
|
||||
import CallHandler from '../../CallHandler';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import Tinter from '../../Tinter';
|
||||
import rate_limited_func from '../../ratelimitedfunc';
|
||||
import * as ObjectUtils from '../../ObjectUtils';
|
||||
import * as Rooms from '../../Rooms';
|
||||
import eventSearch from '../../Searching';
|
||||
|
||||
import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../Keyboard';
|
||||
import {isOnlyCtrlOrCmdIgnoreShiftKeyEvent, isOnlyCtrlOrCmdKeyEvent, Key} from '../../Keyboard';
|
||||
|
||||
import MainSplit from './MainSplit';
|
||||
import RightPanel from './RightPanel';
|
||||
|
@ -588,6 +588,18 @@ export default createReactClass({
|
|||
handled = true;
|
||||
}
|
||||
break;
|
||||
case Key.PAGE_UP:
|
||||
if (!ev.altKey && !ev.ctrlKey && ev.shiftKey && !ev.metaKey) {
|
||||
this.jumpToReadMarker();
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
case Key.U.toUpperCase():
|
||||
if (isOnlyCtrlOrCmdIgnoreShiftKeyEvent(ev) && ev.shiftKey) {
|
||||
dis.dispatch({ action: "upload_file" })
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
|
|
|
@ -19,7 +19,7 @@ import React, {createRef} from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Key } from '../../Keyboard';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import { throttle } from 'lodash';
|
||||
import AccessibleButton from '../../components/views/elements/AccessibleButton';
|
||||
import classNames from 'classnames';
|
||||
|
|
|
@ -22,7 +22,7 @@ import TagOrderStore from '../../stores/TagOrderStore';
|
|||
import GroupActions from '../../actions/GroupActions';
|
||||
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import { _t } from '../../languageHandler';
|
||||
|
||||
import { Droppable } from 'react-beautiful-dnd';
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../index';
|
||||
import dis from '../../dispatcher';
|
||||
import dis from '../../dispatcher/dispatcher';
|
||||
import Modal from '../../Modal';
|
||||
import { _t } from '../../languageHandler';
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import {MatrixClientPeg} from "../../MatrixClientPeg";
|
|||
import * as ObjectUtils from "../../ObjectUtils";
|
||||
import UserActivity from "../../UserActivity";
|
||||
import Modal from "../../Modal";
|
||||
import dis from "../../dispatcher";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import * as sdk from "../../index";
|
||||
import { Key } from '../../Keyboard';
|
||||
import Timer from '../../utils/Timer';
|
||||
|
|
|
@ -22,7 +22,7 @@ import BaseAvatar from '../views/avatars/BaseAvatar';
|
|||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||
import * as Avatar from '../../Avatar';
|
||||
import { _t } from '../../languageHandler';
|
||||
import dis from "../../dispatcher";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import {ContextMenu, ContextMenuButton} from "./ContextMenu";
|
||||
|
||||
const AVATAR_SIZE = 28;
|
||||
|
|
|
@ -19,7 +19,7 @@ import React from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import PropTypes from 'prop-types';
|
||||
import ContentMessages from '../../ContentMessages';
|
||||
import dis from "../../dispatcher";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import filesize from "filesize";
|
||||
import { _t } from '../../languageHandler';
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import {MatrixClientPeg} from "../../MatrixClientPeg";
|
|||
import * as sdk from "../../index";
|
||||
import Modal from '../../Modal';
|
||||
import { _t } from '../../languageHandler';
|
||||
import HomePage from "./HomePage";
|
||||
|
||||
export default class UserView extends React.Component {
|
||||
static get propTypes() {
|
||||
|
@ -79,7 +80,7 @@ export default class UserView extends React.Component {
|
|||
const RightPanel = sdk.getComponent('structures.RightPanel');
|
||||
const MainSplit = sdk.getComponent('structures.MainSplit');
|
||||
const panel = <RightPanel user={this.state.member} />;
|
||||
return (<MainSplit panel={panel}><div style={{flex: "1"}} /></MainSplit>);
|
||||
return (<MainSplit panel={panel}><HomePage /></MainSplit>);
|
||||
} else {
|
||||
return (<div />);
|
||||
}
|
||||
|
|
|
@ -355,7 +355,8 @@ export default createReactClass({
|
|||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
const ssoKind = step === 'm.login.sso' ? 'sso' : 'cas';
|
||||
PlatformPeg.get().startSingleSignOn(this._loginLogic.createTemporaryClient(), ssoKind);
|
||||
PlatformPeg.get().startSingleSignOn(this._loginLogic.createTemporaryClient(), ssoKind,
|
||||
this.props.fragmentAfterLogin);
|
||||
} else {
|
||||
// Don't intercept - just go through to the register page
|
||||
this.onRegisterClick(ev);
|
||||
|
@ -628,7 +629,9 @@ export default createReactClass({
|
|||
<SSOButton
|
||||
className="mx_Login_sso_link mx_Login_submit"
|
||||
matrixClient={this._loginLogic.createTemporaryClient()}
|
||||
loginType={loginType} />
|
||||
loginType={loginType}
|
||||
fragmentAfterLogin={this.props.fragmentAfterLogin}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -32,7 +32,7 @@ import * as Lifecycle from '../../../Lifecycle';
|
|||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import AuthPage from "../../views/auth/AuthPage";
|
||||
import Login from "../../../Login";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
|
||||
// Phases
|
||||
// Show controls to configure server details
|
||||
|
@ -243,10 +243,15 @@ export default createReactClass({
|
|||
});
|
||||
};
|
||||
try {
|
||||
await this._makeRegisterRequest({});
|
||||
// This should never succeed since we specified an empty
|
||||
// auth object.
|
||||
console.log("Expecting 401 from register request but got success!");
|
||||
// We do the first registration request ourselves to discover whether we need to
|
||||
// do SSO instead. If we've already started the UI Auth process though, we don't
|
||||
// need to.
|
||||
if (!this.state.doingUIAuth) {
|
||||
await this._makeRegisterRequest({});
|
||||
// This should never succeed since we specified an empty
|
||||
// auth object.
|
||||
console.log("Expecting 401 from register request but got success!");
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.httpStatus === 401) {
|
||||
this.setState({
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import {_t} from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as Lifecycle from '../../../Lifecycle';
|
||||
import Modal from '../../../Modal';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
|
@ -244,7 +244,9 @@ export default class SoftLogout extends React.Component {
|
|||
<p>{introText}</p>
|
||||
<SSOButton
|
||||
matrixClient={MatrixClientPeg.get()}
|
||||
loginType={this.state.loginView === LOGIN_VIEW.CAS ? "cas" : "sso"} />
|
||||
loginType={this.state.loginView === LOGIN_VIEW.CAS ? "cas" : "sso"}
|
||||
fragmentAfterLogin={this.props.fragmentAfterLogin}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -412,14 +412,14 @@ export const EmailIdentityAuthEntry = createReactClass({
|
|||
this.props.onPhaseChange(DEFAULT_PHASE);
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
requestingToken: false,
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.requestingToken) {
|
||||
// This component is now only displayed once the token has been requested,
|
||||
// so we know the email has been sent. It can also get loaded after the user
|
||||
// has clicked the validation link if the server takes a while to propagate
|
||||
// the validation internally. If we're in the session spawned from clicking
|
||||
// the validation link, we won't know the email address, so if we don't have it,
|
||||
// assume that the link has been clicked and the server will realise when we poll.
|
||||
if (this.props.inputs.emailAddress === undefined) {
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
return <Loader />;
|
||||
} else {
|
||||
|
|
125
src/components/views/auth/PassphraseField.tsx
Normal file
125
src/components/views/auth/PassphraseField.tsx
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
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, {PureComponent, RefCallback, RefObject} from "react";
|
||||
import classNames from "classnames";
|
||||
import zxcvbn from "zxcvbn";
|
||||
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import withValidation, {IFieldState, IValidationResult} from "../elements/Validation";
|
||||
import {_t, _td} from "../../../languageHandler";
|
||||
import Field from "../elements/Field";
|
||||
|
||||
interface IProps {
|
||||
autoFocus?: boolean;
|
||||
id?: string;
|
||||
className?: string;
|
||||
minScore: 0 | 1 | 2 | 3 | 4;
|
||||
value: string;
|
||||
fieldRef?: RefCallback<Field> | RefObject<Field>;
|
||||
|
||||
label?: string;
|
||||
labelEnterPassword?: string;
|
||||
labelStrongPassword?: string;
|
||||
labelAllowedButUnsafe?: string;
|
||||
|
||||
onChange(ev: KeyboardEvent);
|
||||
onValidate(result: IValidationResult);
|
||||
}
|
||||
|
||||
interface IState {
|
||||
complexity: zxcvbn.ZXCVBNResult;
|
||||
}
|
||||
|
||||
class PassphraseField extends PureComponent<IProps, IState> {
|
||||
static defaultProps = {
|
||||
label: _td("Password"),
|
||||
labelEnterPassword: _td("Enter password"),
|
||||
labelStrongPassword: _td("Nice, strong password!"),
|
||||
labelAllowedButUnsafe: _td("Password is allowed, but unsafe"),
|
||||
};
|
||||
|
||||
state = { complexity: null };
|
||||
|
||||
public readonly validate = withValidation<this>({
|
||||
description: function() {
|
||||
const complexity = this.state.complexity;
|
||||
const score = complexity ? complexity.score : 0;
|
||||
return <progress className="mx_PassphraseField_progress" max={4} value={score} />;
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
key: "required",
|
||||
test: ({ value, allowEmpty }) => allowEmpty || !!value,
|
||||
invalid: () => _t(this.props.labelEnterPassword),
|
||||
},
|
||||
{
|
||||
key: "complexity",
|
||||
test: async function({ value }) {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
const { scorePassword } = await import('../../../utils/PasswordScorer');
|
||||
const complexity = scorePassword(value);
|
||||
this.setState({ complexity });
|
||||
const safe = complexity.score >= this.props.minScore;
|
||||
const allowUnsafe = SdkConfig.get()["dangerously_allow_unsafe_and_insecure_passwords"];
|
||||
return allowUnsafe || safe;
|
||||
},
|
||||
valid: function() {
|
||||
// Unsafe passwords that are valid are only possible through a
|
||||
// configuration flag. We'll print some helper text to signal
|
||||
// to the user that their password is allowed, but unsafe.
|
||||
if (this.state.complexity.score >= this.props.minScore) {
|
||||
return _t(this.props.labelStrongPassword);
|
||||
}
|
||||
return _t(this.props.labelAllowedButUnsafe);
|
||||
},
|
||||
invalid: function() {
|
||||
const complexity = this.state.complexity;
|
||||
if (!complexity) {
|
||||
return null;
|
||||
}
|
||||
const { feedback } = complexity;
|
||||
return feedback.warning || feedback.suggestions[0] || _t("Keep going...");
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
onValidate = async (fieldState: IFieldState) => {
|
||||
const result = await this.validate(fieldState);
|
||||
this.props.onValidate(result);
|
||||
return result;
|
||||
};
|
||||
|
||||
render() {
|
||||
return <Field
|
||||
id={this.props.id}
|
||||
autoFocus={this.props.autoFocus}
|
||||
className={classNames("mx_PassphraseField", this.props.className)}
|
||||
ref={this.props.fieldRef}
|
||||
type="password"
|
||||
autoComplete="new-password"
|
||||
label={_t(this.props.label)}
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
onValidate={this.onValidate}
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
||||
export default PassphraseField;
|
|
@ -29,6 +29,7 @@ import SdkConfig from '../../../SdkConfig';
|
|||
import { SAFE_LOCALPART_REGEX } from '../../../Registration';
|
||||
import withValidation from '../elements/Validation';
|
||||
import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils";
|
||||
import PassphraseField from "./PassphraseField";
|
||||
|
||||
const FIELD_EMAIL = 'field_email';
|
||||
const FIELD_PHONE_NUMBER = 'field_phone_number';
|
||||
|
@ -78,7 +79,6 @@ export default createReactClass({
|
|||
password: this.props.defaultPassword || "",
|
||||
passwordConfirm: this.props.defaultPassword || "",
|
||||
passwordComplexity: null,
|
||||
passwordSafe: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -264,65 +264,10 @@ export default createReactClass({
|
|||
});
|
||||
},
|
||||
|
||||
async onPasswordValidate(fieldState) {
|
||||
const result = await this.validatePasswordRules(fieldState);
|
||||
onPasswordValidate(result) {
|
||||
this.markFieldValid(FIELD_PASSWORD, result.valid);
|
||||
return result;
|
||||
},
|
||||
|
||||
validatePasswordRules: withValidation({
|
||||
description: function() {
|
||||
const complexity = this.state.passwordComplexity;
|
||||
const score = complexity ? complexity.score : 0;
|
||||
return <progress
|
||||
className="mx_AuthBody_passwordScore"
|
||||
max={PASSWORD_MIN_SCORE}
|
||||
value={score}
|
||||
/>;
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
key: "required",
|
||||
test: ({ value, allowEmpty }) => allowEmpty || !!value,
|
||||
invalid: () => _t("Enter password"),
|
||||
},
|
||||
{
|
||||
key: "complexity",
|
||||
test: async function({ value }) {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
const { scorePassword } = await import('../../../utils/PasswordScorer');
|
||||
const complexity = scorePassword(value);
|
||||
const safe = complexity.score >= PASSWORD_MIN_SCORE;
|
||||
const allowUnsafe = SdkConfig.get()["dangerously_allow_unsafe_and_insecure_passwords"];
|
||||
this.setState({
|
||||
passwordComplexity: complexity,
|
||||
passwordSafe: safe,
|
||||
});
|
||||
return allowUnsafe || safe;
|
||||
},
|
||||
valid: function() {
|
||||
// Unsafe passwords that are valid are only possible through a
|
||||
// configuration flag. We'll print some helper text to signal
|
||||
// to the user that their password is allowed, but unsafe.
|
||||
if (!this.state.passwordSafe) {
|
||||
return _t("Password is allowed, but unsafe");
|
||||
}
|
||||
return _t("Nice, strong password!");
|
||||
},
|
||||
invalid: function() {
|
||||
const complexity = this.state.passwordComplexity;
|
||||
if (!complexity) {
|
||||
return null;
|
||||
}
|
||||
const { feedback } = complexity;
|
||||
return feedback.warning || feedback.suggestions[0] || _t("Keep going...");
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
onPasswordConfirmChange(ev) {
|
||||
this.setState({
|
||||
passwordConfirm: ev.target.value,
|
||||
|
@ -484,13 +429,10 @@ export default createReactClass({
|
|||
},
|
||||
|
||||
renderPassword() {
|
||||
const Field = sdk.getComponent('elements.Field');
|
||||
return <Field
|
||||
return <PassphraseField
|
||||
id="mx_RegistrationForm_password"
|
||||
ref={field => this[FIELD_PASSWORD] = field}
|
||||
type="password"
|
||||
autoComplete="new-password"
|
||||
label={_t("Password")}
|
||||
fieldRef={field => this[FIELD_PASSWORD] = field}
|
||||
minScore={PASSWORD_MIN_SCORE}
|
||||
value={this.state.password}
|
||||
onChange={this.onPasswordChange}
|
||||
onValidate={this.onPasswordValidate}
|
||||
|
|
|
@ -45,7 +45,8 @@ export default class Welcome extends React.PureComponent {
|
|||
idBaseUrl: isUrl,
|
||||
});
|
||||
const plaf = PlatformPeg.get();
|
||||
const callbackUrl = plaf.getSSOCallbackUrl(tmpClient.getHomeserverUrl(), tmpClient.getIdentityServerUrl());
|
||||
const callbackUrl = plaf.getSSOCallbackUrl(tmpClient.getHomeserverUrl(), tmpClient.getIdentityServerUrl(),
|
||||
this.props.fragmentAfterLogin);
|
||||
|
||||
return (
|
||||
<AuthPage>
|
||||
|
|
|
@ -20,7 +20,8 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
import * as Avatar from '../../../Avatar';
|
||||
import * as sdk from "../../../index";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'MemberAvatar',
|
||||
|
@ -33,7 +34,7 @@ export default createReactClass({
|
|||
resizeMethod: PropTypes.string,
|
||||
// The onClick to give the avatar
|
||||
onClick: PropTypes.func,
|
||||
// Whether the onClick of the avatar should be overriden to dispatch 'view_user'
|
||||
// Whether the onClick of the avatar should be overriden to dispatch `Action.ViewUser`
|
||||
viewUserOnClick: PropTypes.bool,
|
||||
title: PropTypes.string,
|
||||
},
|
||||
|
@ -85,7 +86,7 @@ export default createReactClass({
|
|||
if (viewUserOnClick) {
|
||||
onClick = () => {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
action: Action.ViewUser,
|
||||
member: this.props.member,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@ import createReactClass from 'create-react-class';
|
|||
import {EventStatus} from 'matrix-js-sdk';
|
||||
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import Modal from '../../../Modal';
|
||||
|
|
|
@ -24,7 +24,7 @@ import classNames from 'classnames';
|
|||
import * as sdk from '../../../index';
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||
import * as Rooms from '../../../Rooms';
|
||||
import * as RoomNotifs from '../../../RoomNotifs';
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import TagOrderActions from '../../../actions/TagOrderActions';
|
||||
import * as sdk from '../../../index';
|
||||
import {MenuItem} from "../../structures/ContextMenu";
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import LogoutDialog from "../dialogs/LogoutDialog";
|
||||
import Modal from "../../../Modal";
|
||||
|
@ -27,6 +27,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|||
import {MenuItem} from "../../structures/ContextMenu";
|
||||
import * as sdk from "../../../index";
|
||||
import {getHomePageUrl} from "../../../utils/pages";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default class TopLeftMenu extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -134,7 +135,7 @@ export default class TopLeftMenu extends React.Component {
|
|||
}
|
||||
|
||||
openSettings() {
|
||||
dis.dispatch({action: 'view_user_settings'});
|
||||
dis.fire(Action.ViewUserSettings);
|
||||
this.closeMenu();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import createReactClass from 'create-react-class';
|
|||
import { _t, _td } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { addressTypes, getAddressType } from '../../../UserAddress.js';
|
||||
import GroupStore from '../../../stores/GroupStore';
|
||||
import * as Email from '../../../email';
|
||||
|
@ -33,6 +33,7 @@ import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from '../../../
|
|||
import { abbreviateUrl } from '../../../utils/UrlUtils';
|
||||
import {sleep} from "../../../utils/promise";
|
||||
import {Key} from "../../../Keyboard";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
const TRUNCATE_QUERY_LIST = 40;
|
||||
const QUERY_USER_DIRECTORY_DEBOUNCE_MS = 200;
|
||||
|
@ -615,7 +616,7 @@ export default createReactClass({
|
|||
|
||||
onManageSettingsClick(e) {
|
||||
e.preventDefault();
|
||||
dis.dispatch({ action: 'view_user_settings' });
|
||||
dis.fire(Action.ViewUserSettings);
|
||||
this.onCancel();
|
||||
},
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import Modal from '../../../Modal';
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
shouldErase: false,
|
||||
errStr: null,
|
||||
authData: null, // for UIA
|
||||
authEnabled: true, // see usages for information
|
||||
|
||||
// A few strings that are passed to InteractiveAuth for design or are displayed
|
||||
// next to the InteractiveAuth component.
|
||||
|
@ -42,21 +43,7 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
continueKind: null,
|
||||
};
|
||||
|
||||
MatrixClientPeg.get().deactivateAccount(null, false).then(r => {
|
||||
// If we got here, oops. The server didn't require any auth.
|
||||
// Our application lifecycle will catch the error and do the logout bits.
|
||||
// We'll try to log something in an vain attempt to record what happened (storage
|
||||
// is also obliterated on logout).
|
||||
console.warn("User's account got deactivated without confirmation: Server had no auth");
|
||||
this.setState({errStr: _t("Server did not require any authentication")});
|
||||
}).catch(e => {
|
||||
if (e && e.httpStatus === 401 && e.data) {
|
||||
// Valid UIA response
|
||||
this.setState({authData: e.data});
|
||||
} else {
|
||||
this.setState({errStr: _t("Server did not return valid authentication information.")});
|
||||
}
|
||||
});
|
||||
this._initAuth(/* shouldErase= */false);
|
||||
}
|
||||
|
||||
_onStagePhaseChange = (stage, phase) => {
|
||||
|
@ -124,13 +111,40 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
_onEraseFieldChange = (ev) => {
|
||||
this.setState({
|
||||
shouldErase: ev.target.checked,
|
||||
|
||||
// Disable the auth form because we're going to have to reinitialize the auth
|
||||
// information. We do this because we can't modify the parameters in the UIA
|
||||
// session, and the user will have selected something which changes the request.
|
||||
// Therefore, we throw away the last auth session and try a new one.
|
||||
authEnabled: false,
|
||||
});
|
||||
|
||||
// As mentioned above, set up for auth again to get updated UIA session info
|
||||
this._initAuth(/* shouldErase= */ev.target.checked);
|
||||
};
|
||||
|
||||
_onCancel() {
|
||||
this.props.onFinished(false);
|
||||
}
|
||||
|
||||
_initAuth(shouldErase) {
|
||||
MatrixClientPeg.get().deactivateAccount(null, shouldErase).then(r => {
|
||||
// If we got here, oops. The server didn't require any auth.
|
||||
// Our application lifecycle will catch the error and do the logout bits.
|
||||
// We'll try to log something in an vain attempt to record what happened (storage
|
||||
// is also obliterated on logout).
|
||||
console.warn("User's account got deactivated without confirmation: Server had no auth");
|
||||
this.setState({errStr: _t("Server did not require any authentication")});
|
||||
}).catch(e => {
|
||||
if (e && e.httpStatus === 401 && e.data) {
|
||||
// Valid UIA response
|
||||
this.setState({authData: e.data, authEnabled: true});
|
||||
} else {
|
||||
this.setState({errStr: _t("Server did not return valid authentication information.")});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
|
||||
|
@ -142,7 +156,7 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
}
|
||||
|
||||
let auth = <div>{_t("Loading...")}</div>;
|
||||
if (this.state.authData) {
|
||||
if (this.state.authData && this.state.authEnabled) {
|
||||
auth = (
|
||||
<div>
|
||||
{this.state.bodyText}
|
||||
|
|
|
@ -25,7 +25,7 @@ import * as FormattingUtils from '../../../utils/FormattingUtils';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
||||
import {ensureDMExists} from "../../../createRoom";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import SettingsStore from '../../../settings/SettingsStore';
|
||||
import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
||||
import VerificationQREmojiOptions from "../verification/VerificationQREmojiOptions";
|
||||
|
|
|
@ -18,7 +18,8 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import {_t} from "../../../languageHandler";
|
||||
import * as sdk from "../../../index";
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default class IntegrationsDisabledDialog extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -31,7 +32,7 @@ export default class IntegrationsDisabledDialog extends React.Component {
|
|||
|
||||
_onOpenSettingsClick = () => {
|
||||
this.props.onFinished();
|
||||
dis.dispatch({action: "view_user_settings"});
|
||||
dis.fire(Action.ViewUserSettings);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
@ -27,7 +27,7 @@ import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
|
|||
import * as Email from "../../../email";
|
||||
import {getDefaultIdentityServerUrl, useDefaultIdentityServer} from "../../../utils/IdentityServerUtils";
|
||||
import {abbreviateUrl} from "../../../utils/UrlUtils";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import IdentityAuthClient from "../../../IdentityAuthClient";
|
||||
import Modal from "../../../Modal";
|
||||
import {humanizeTime} from "../../../utils/humanize";
|
||||
|
@ -36,6 +36,7 @@ import {inviteMultipleToRoom} from "../../../RoomInvite";
|
|||
import SettingsStore from '../../../settings/SettingsStore';
|
||||
import RoomListStore, {TAG_DM} from "../../../stores/RoomListStore";
|
||||
import {Key} from "../../../Keyboard";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export const KIND_DM = "dm";
|
||||
export const KIND_INVITE = "invite";
|
||||
|
@ -902,7 +903,7 @@ export default class InviteDialog extends React.PureComponent {
|
|||
|
||||
_onManageSettingsClick = (e) => {
|
||||
e.preventDefault();
|
||||
dis.dispatch({ action: 'view_user_settings' });
|
||||
dis.fire(Action.ViewUserSettings);
|
||||
this.props.onFinished();
|
||||
};
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import Modal from '../../../Modal';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsT
|
|||
import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab";
|
||||
import * as sdk from "../../../index";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
||||
export default class RoomSettingsDialog extends React.Component {
|
||||
|
|
|
@ -24,7 +24,7 @@ import {RoomMember} from "matrix-js-sdk/src/models/room-member";
|
|||
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import QRCode from 'qrcode-react';
|
||||
import QRCode from "../elements/QRCode";
|
||||
import {RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink} from "../../../utils/permalinks/Permalinks";
|
||||
import * as ContextMenu from "../../structures/ContextMenu";
|
||||
import {toRightOf} from "../../structures/ContextMenu";
|
||||
|
@ -221,7 +221,7 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
|||
|
||||
<div className="mx_ShareDialog_split">
|
||||
<div className="mx_ShareDialog_qrcode_container">
|
||||
<QRCode value={matrixToUrl} size={256} logoWidth={48} logo={require("../../../../res/img/matrix-m.svg")} />
|
||||
<QRCode data={matrixToUrl} width={256} />
|
||||
</div>
|
||||
<div className="mx_ShareDialog_social_container">
|
||||
{ socials.map((social) => (
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import AccessibleButton from './AccessibleButton';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as sdk from '../../../index';
|
||||
import Analytics from '../../../Analytics';
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import AppPermission from './AppPermission';
|
|||
import AppWarning from './AppWarning';
|
||||
import MessageSpinner from './MessageSpinner';
|
||||
import WidgetUtils from '../../../utils/WidgetUtils';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
||||
import classNames from 'classnames';
|
||||
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import FlairStore from '../../../stores/FlairStore';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
|
|||
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
|
||||
// Shamelessly ripped off Modal.js. There's probably a better way
|
||||
// of doing reusable widgets like dialog boxes & menus where we go and
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import classNames from 'classnames';
|
||||
import { Room, RoomMember } from 'matrix-js-sdk';
|
||||
import PropTypes from 'prop-types';
|
||||
|
@ -26,6 +26,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|||
import FlairStore from "../../../stores/FlairStore";
|
||||
import {getPrimaryPermalinkEntity} from "../../../utils/permalinks/Permalinks";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
// For URLs of matrix.to links in the timeline which have been reformatted by
|
||||
// HttpUtils transformTags to relative links. This excludes event URLs (with `[^\/]*`)
|
||||
|
@ -191,7 +192,7 @@ const Pill = createReactClass({
|
|||
|
||||
onUserPillClicked: function() {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
action: Action.ViewUser,
|
||||
member: this.state.member,
|
||||
});
|
||||
},
|
||||
|
|
51
src/components/views/elements/QRCode.tsx
Normal file
51
src/components/views/elements/QRCode.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
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 * as React from "react";
|
||||
import {toDataURL, QRCodeSegment, QRCodeToDataURLOptions} from "qrcode";
|
||||
import classNames from "classnames";
|
||||
|
||||
import {_t} from "../../../languageHandler";
|
||||
import Spinner from "./Spinner";
|
||||
|
||||
interface IProps extends QRCodeToDataURLOptions {
|
||||
data: string | QRCodeSegment[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const defaultOptions: QRCodeToDataURLOptions = {
|
||||
errorCorrectionLevel: 'L', // we want it as trivial-looking as possible
|
||||
};
|
||||
|
||||
const QRCode: React.FC<IProps> = ({data, className, ...options}) => {
|
||||
const [dataUri, setUri] = React.useState<string>(null);
|
||||
React.useEffect(() => {
|
||||
let cancelled = false;
|
||||
toDataURL(data, {...defaultOptions, ...options}).then(uri => {
|
||||
if (cancelled) return;
|
||||
setUri(uri);
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [JSON.stringify(data), options]);
|
||||
|
||||
return <div className={classNames("mx_QRCode", className)}>
|
||||
{ dataUri ? <img src={dataUri} className="mx_VerificationQRCode" alt={_t("QR Code")} /> : <Spinner /> }
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default QRCode;
|
|
@ -19,7 +19,7 @@ import React from 'react';
|
|||
import * as sdk from '../../../index';
|
||||
import {_t} from '../../../languageHandler';
|
||||
import PropTypes from 'prop-types';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import {wantsDateSeparator} from '../../../DateUtils';
|
||||
import {MatrixEvent} from 'matrix-js-sdk';
|
||||
import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks";
|
||||
|
|
|
@ -21,9 +21,9 @@ import PlatformPeg from "../../../PlatformPeg";
|
|||
import AccessibleButton from "./AccessibleButton";
|
||||
import {_t} from "../../../languageHandler";
|
||||
|
||||
const SSOButton = ({matrixClient, loginType, ...props}) => {
|
||||
const SSOButton = ({matrixClient, loginType, fragmentAfterLogin, ...props}) => {
|
||||
const onClick = () => {
|
||||
PlatformPeg.get().startSingleSignOn(matrixClient, loginType);
|
||||
PlatformPeg.get().startSingleSignOn(matrixClient, loginType, fragmentAfterLogin);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -36,6 +36,7 @@ const SSOButton = ({matrixClient, loginType, ...props}) => {
|
|||
SSOButton.propTypes = {
|
||||
matrixClient: PropTypes.object.isRequired, // does not use context as may use a temporary client
|
||||
loginType: PropTypes.oneOf(["sso", "cas"]), // defaults to "sso" in base-apis
|
||||
fragmentAfterLogin: PropTypes.string,
|
||||
};
|
||||
|
||||
export default SSOButton;
|
||||
|
|
|
@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
import classNames from 'classnames';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { isOnlyCtrlOrCmdIgnoreShiftKeyEvent } from '../../../Keyboard';
|
||||
import * as FormattingUtils from '../../../utils/FormattingUtils';
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const MIN_TOOLTIP_HEIGHT = 25;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
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.
|
||||
|
@ -15,11 +16,39 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
/* eslint-disable babel/no-invalid-this */
|
||||
import React from "react";
|
||||
import classNames from "classnames";
|
||||
|
||||
import classNames from 'classnames';
|
||||
type Data = Pick<IFieldState, "value" | "allowEmpty">;
|
||||
|
||||
interface IRule<T> {
|
||||
key: string;
|
||||
final?: boolean;
|
||||
skip?(this: T, data: Data): boolean;
|
||||
test(this: T, data: Data): boolean | Promise<boolean>;
|
||||
valid?(this: T): string;
|
||||
invalid?(this: T): string;
|
||||
}
|
||||
|
||||
interface IArgs<T> {
|
||||
rules: IRule<T>[];
|
||||
description(this: T): React.ReactChild;
|
||||
}
|
||||
|
||||
export interface IFieldState {
|
||||
value: string;
|
||||
focused: boolean;
|
||||
allowEmpty: boolean;
|
||||
}
|
||||
|
||||
export interface IValidationResult {
|
||||
valid?: boolean;
|
||||
feedback?: React.ReactChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a validation function from a set of rules describing what to validate.
|
||||
* Generic T is the "this" type passed to the rule methods
|
||||
*
|
||||
* @param {Function} description
|
||||
* Function that returns a string summary of the kind of value that will
|
||||
|
@ -37,8 +66,8 @@ import classNames from 'classnames';
|
|||
* A validation function that takes in the current input value and returns
|
||||
* the overall validity and a feedback UI that can be rendered for more detail.
|
||||
*/
|
||||
export default function withValidation({ description, rules }) {
|
||||
return async function onValidate({ value, focused, allowEmpty = true }) {
|
||||
export default function withValidation<T = undefined>({ description, rules }: IArgs<T>) {
|
||||
return async function onValidate({ value, focused, allowEmpty = true }: IFieldState): Promise<IValidationResult> {
|
||||
if (!value && allowEmpty) {
|
||||
return {
|
||||
valid: null,
|
|
@ -17,8 +17,7 @@ limitations under the License.
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import {replaceableComponent} from "../../../../utils/replaceableComponent";
|
||||
import Spinner from "../Spinner";
|
||||
import * as QRCode from "qrcode";
|
||||
import QRCode from "../QRCode";
|
||||
|
||||
@replaceableComponent("views.elements.crypto.VerificationQRCode")
|
||||
export default class VerificationQRCode extends React.PureComponent {
|
||||
|
@ -26,33 +25,12 @@ export default class VerificationQRCode extends React.PureComponent {
|
|||
qrCodeData: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dataUri: null,
|
||||
};
|
||||
this.generateQrCode();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps): void {
|
||||
if (JSON.stringify(this.props) === JSON.stringify(prevProps)) return; // No prop change
|
||||
|
||||
this.generateQRCode();
|
||||
}
|
||||
|
||||
async generateQrCode() {
|
||||
// Now actually assemble the QR code's data URI
|
||||
const uri = await QRCode.toDataURL([{data: this.props.qrCodeData.buffer, mode: 'byte'}], {
|
||||
errorCorrectionLevel: 'L', // we want it as trivial-looking as possible
|
||||
});
|
||||
this.setState({dataUri: uri});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.dataUri) {
|
||||
return <div className='mx_VerificationQRCode'><Spinner /></div>;
|
||||
}
|
||||
|
||||
return <img src={this.state.dataUri} className='mx_VerificationQRCode' />;
|
||||
return (
|
||||
<QRCode
|
||||
data={[{data: this.props.qrCodeData.buffer, mode: 'byte'}]}
|
||||
className="mx_VerificationQRCode"
|
||||
width={196} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import Analytics from '../../../Analytics';
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import {_t} from '../../../languageHandler';
|
||||
import classNames from 'classnames';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
@ -28,6 +28,7 @@ import GroupStore from '../../../stores/GroupStore';
|
|||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'GroupMemberInfo',
|
||||
|
@ -103,7 +104,7 @@ export default createReactClass({
|
|||
).then(() => {
|
||||
// return to the user list
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
}).catch((e) => {
|
||||
|
@ -124,7 +125,7 @@ export default createReactClass({
|
|||
_onCancel: function(e) {
|
||||
// Go back to the user list
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -19,7 +19,7 @@ import React from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import GroupStore from '../../../stores/GroupStore';
|
||||
import PropTypes from 'prop-types';
|
||||
import { showGroupInviteDialog } from '../../../GroupAddressPicker';
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { GroupMemberType } from '../../../groups';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { GroupRoomType } from '../../../groups';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
import { Draggable, Droppable } from 'react-beautiful-dnd';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import FlairStore from '../../../stores/FlairStore';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import * as sdk from '../../../index';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import {getNameForEventRoom, userLabelForEventRoom}
|
||||
from '../../../utils/KeyVerificationStateObserver';
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
||||
|
||||
export default class MKeyVerificationRequest extends React.Component {
|
||||
|
|
|
@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
|
|||
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import {aboveLeftOf, ContextMenu, ContextMenuButton, useContextMenu} from '../../structures/ContextMenu';
|
||||
import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
|
||||
|
|
|
@ -19,7 +19,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
|
|
|
@ -25,7 +25,7 @@ import * as HtmlUtils from '../../../HtmlUtils';
|
|||
import {formatDate} from '../../../DateUtils';
|
||||
import * as sdk from '../../../index';
|
||||
import Modal from '../../../Modal';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as ContextMenu from '../../structures/ContextMenu';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
|
|
|
@ -23,6 +23,8 @@ import { _t } from '../../../languageHandler';
|
|||
import HeaderButton from './HeaderButton';
|
||||
import HeaderButtons, {HEADER_KIND_GROUP} from './HeaderButtons';
|
||||
import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
import {ActionPayload} from "../../../dispatcher/payloads";
|
||||
|
||||
const GROUP_PHASES = [
|
||||
RIGHT_PANEL_PHASES.GroupMemberInfo,
|
||||
|
@ -40,10 +42,10 @@ export default class GroupHeaderButtons extends HeaderButtons {
|
|||
this._onRoomsClicked = this._onRoomsClicked.bind(this);
|
||||
}
|
||||
|
||||
onAction(payload) {
|
||||
onAction(payload: ActionPayload) {
|
||||
super.onAction(payload);
|
||||
|
||||
if (payload.action === "view_user") {
|
||||
if (payload.action === Action.ViewUser) {
|
||||
if (payload.member) {
|
||||
this.setPhase(RIGHT_PANEL_PHASES.RoomMemberInfo, {member: payload.member});
|
||||
} else {
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import RightPanelStore from "../../../stores/RightPanelStore";
|
||||
|
||||
export const HEADER_KIND_ROOM = "room";
|
||||
|
|
|
@ -23,6 +23,8 @@ import { _t } from '../../../languageHandler';
|
|||
import HeaderButton from './HeaderButton';
|
||||
import HeaderButtons, {HEADER_KIND_ROOM} from './HeaderButtons';
|
||||
import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
import {ActionPayload} from "../../../dispatcher/payloads";
|
||||
|
||||
const MEMBER_PHASES = [
|
||||
RIGHT_PANEL_PHASES.RoomMemberList,
|
||||
|
@ -39,9 +41,9 @@ export default class RoomHeaderButtons extends HeaderButtons {
|
|||
this._onNotificationsClicked = this._onNotificationsClicked.bind(this);
|
||||
}
|
||||
|
||||
onAction(payload) {
|
||||
onAction(payload: ActionPayload) {
|
||||
super.onAction(payload);
|
||||
if (payload.action === "view_user") {
|
||||
if (payload.action === Action.ViewUser) {
|
||||
if (payload.member) {
|
||||
this.setPhase(RIGHT_PANEL_PHASES.RoomMemberInfo, {member: payload.member});
|
||||
} else {
|
||||
|
|
|
@ -21,7 +21,7 @@ import React, {useCallback, useMemo, useState, useEffect, useContext} from 'reac
|
|||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import {Group, RoomMember, User} from 'matrix-js-sdk';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
@ -44,6 +44,7 @@ import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
|
|||
import EncryptionPanel from "./EncryptionPanel";
|
||||
import { useAsyncMemo } from '../../../hooks/useAsyncMemo';
|
||||
import { verifyUser, legacyVerifyUser, verifyDevice } from '../../../verification';
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
const _disambiguateDevices = (devices) => {
|
||||
const names = Object.create(null);
|
||||
|
@ -841,7 +842,7 @@ const GroupAdminToolsSection = ({children, groupId, groupMember, startUpdating,
|
|||
cli.removeUserFromGroup(groupId, groupMember.userId).then(() => {
|
||||
// return to the user list
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
}).catch((e) => {
|
||||
|
|
|
@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
|
||||
import Tinter from '../../../Tinter';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
|
||||
const ROOM_COLORS = [
|
||||
|
|
|
@ -23,8 +23,9 @@ import createReactClass from 'create-react-class';
|
|||
import * as sdk from "../../../index";
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
|
||||
export default createReactClass({
|
||||
|
@ -37,7 +38,7 @@ export default createReactClass({
|
|||
_onClickUserSettings: (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dis.dispatch({action: 'view_user_settings'});
|
||||
dis.fire(Action.ViewUserSettings);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
|
|
@ -21,7 +21,7 @@ import createReactClass from 'create-react-class';
|
|||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import AppTile from '../elements/AppTile';
|
||||
import Modal from '../../../Modal';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as sdk from '../../../index';
|
||||
import * as ScalarMessaging from '../../../ScalarMessaging';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
|
|
@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import * as sdk from '../../../index';
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import * as ObjectUtils from '../../../ObjectUtils';
|
||||
import AppsDrawer from './AppsDrawer';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from 'react';
|
|||
import * as sdk from '../../../index';
|
||||
import {_t} from '../../../languageHandler';
|
||||
import PropTypes from 'prop-types';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import EditorModel from '../../../editor/model';
|
||||
import {getCaretOffsetAndText} from '../../../editor/dom';
|
||||
import {htmlSerializeIfNeeded, textSerialize, containsEmote, stripEmoteCommand} from '../../../editor/serialize';
|
||||
|
|
|
@ -25,7 +25,7 @@ import classNames from "classnames";
|
|||
import { _t, _td } from '../../../languageHandler';
|
||||
import * as TextForEvent from "../../../TextForEvent";
|
||||
import * as sdk from "../../../index";
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import {EventStatus} from 'matrix-js-sdk';
|
||||
import {formatTime} from "../../../DateUtils";
|
||||
|
|
|
@ -19,7 +19,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import {Key} from '../../../Keyboard';
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import classNames from 'classnames';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
@ -48,6 +48,7 @@ import E2EIcon from "./E2EIcon";
|
|||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'MemberInfo',
|
||||
|
@ -724,7 +725,7 @@ export default createReactClass({
|
|||
|
||||
onCancel: function(e) {
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
action: Action.ViewUser,
|
||||
member: null,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import createReactClass from 'create-react-class';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import {isValid3pidInvite} from "../../../RoomInvite";
|
||||
import rate_limited_func from "../../../ratelimitedfunc";
|
||||
|
|
|
@ -20,9 +20,10 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from "../../../index";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import {Action} from "../../../dispatcher/actions";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'MemberTile',
|
||||
|
@ -185,7 +186,7 @@ export default createReactClass({
|
|||
|
||||
onClick: function(e) {
|
||||
dis.dispatch({
|
||||
action: 'view_user',
|
||||
action: Action.ViewUser,
|
||||
member: this.props.member,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -20,7 +20,7 @@ import { _t } from '../../../languageHandler';
|
|||
import CallHandler from '../../../CallHandler';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||
import Stickerpicker from './Stickerpicker';
|
||||
import { makeRoomPermalink } from '../../../utils/permalinks/Permalinks';
|
||||
|
@ -114,8 +114,19 @@ class UploadButton extends React.Component {
|
|||
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
|
||||
|
||||
this._uploadInput = createRef();
|
||||
this._dispatcherRef = dis.register(this.onAction);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
dis.unregister(this._dispatcherRef);
|
||||
}
|
||||
|
||||
onAction = payload => {
|
||||
if (payload.action === "upload_file") {
|
||||
this.onUploadClick();
|
||||
}
|
||||
};
|
||||
|
||||
onUploadClick(ev) {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
dis.dispatch({action: 'require_registration'});
|
||||
|
@ -128,7 +139,7 @@ class UploadButton extends React.Component {
|
|||
if (ev.target.files.length === 0) return;
|
||||
|
||||
// take a copy so we can safely reset the value of the form control
|
||||
// (Note it is a FileList: we can't use slice or sesnible iteration).
|
||||
// (Note it is a FileList: we can't use slice or sensible iteration).
|
||||
const tfiles = [];
|
||||
for (let i = 0; i < ev.target.files.length; ++i) {
|
||||
tfiles.push(ev.target.files[i]);
|
||||
|
|
|
@ -18,7 +18,7 @@ import React from "react";
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import MessageEvent from "../messages/MessageEvent";
|
||||
import MemberAvatar from "../avatars/MemberAvatar";
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React, {createRef} from "react";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import React from 'react';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import PropTypes from 'prop-types';
|
||||
|
|
|
@ -35,7 +35,7 @@ import GroupStore from '../../../stores/GroupStore';
|
|||
import RoomSubList from '../../structures/RoomSubList';
|
||||
import ResizeHandle from '../elements/ResizeHandle';
|
||||
import CallHandler from "../../../CallHandler";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import * as sdk from "../../../index";
|
||||
import * as Receipt from "../../../utils/Receipt";
|
||||
import {Resizer} from '../../../resizer';
|
||||
|
@ -785,6 +785,7 @@ export default createReactClass({
|
|||
label: _t('Rooms'),
|
||||
incomingCall: incomingCallIfTaggedAs('im.vector.fake.recent'),
|
||||
onAddRoom: () => {dis.dispatch({action: 'view_create_room'});},
|
||||
addRoomLabel: _t("Create room"),
|
||||
},
|
||||
];
|
||||
const tagSubLists = Object.keys(this.state.lists)
|
||||
|
|
|
@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import createReactClass from 'create-react-class';
|
||||
import * as sdk from '../../../index';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import classNames from 'classnames';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import IdentityAuthClient from '../../../IdentityAuthClient';
|
||||
|
|
|
@ -21,7 +21,7 @@ import React, {createRef} from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import classNames from 'classnames';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||
import * as sdk from '../../../index';
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import EditorModel from '../../../editor/model';
|
||||
import {
|
||||
htmlSerializeIfNeeded,
|
||||
|
|
|
@ -18,7 +18,7 @@ import {_t, _td} from '../../../languageHandler';
|
|||
import AppTile from '../elements/AppTile';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import * as sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import WidgetUtils from '../../../utils/WidgetUtils';
|
||||
import ActiveWidgetStore from '../../../stores/ActiveWidgetStore';
|
||||
|
|
|
@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
|
|||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import {MatrixEvent} from "matrix-js-sdk";
|
||||
import {_t} from "../../../languageHandler";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import * as sdk from "../../../index";
|
||||
import Modal from "../../../Modal";
|
||||
import {isValid3pidInvite} from "../../../RoomInvite";
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import * as sdk from "../../../index";
|
||||
|
|
|
@ -36,7 +36,6 @@ export default class CrossSigningPanel extends React.PureComponent {
|
|||
userSigningPrivateKeyCached: false,
|
||||
sessionBackupKeyCached: false,
|
||||
secretStorageKeyInAccount: false,
|
||||
secretStorageKeyNeedsUpgrade: null,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -88,7 +87,6 @@ export default class CrossSigningPanel extends React.PureComponent {
|
|||
const homeserverSupportsCrossSigning =
|
||||
await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing");
|
||||
const crossSigningReady = await cli.isCrossSigningReady();
|
||||
const secretStorageKeyNeedsUpgrade = await cli.secretStorageKeyNeedsUpgrade();
|
||||
|
||||
this.setState({
|
||||
crossSigningPublicKeysOnDevice,
|
||||
|
@ -100,7 +98,6 @@ export default class CrossSigningPanel extends React.PureComponent {
|
|||
secretStorageKeyInAccount,
|
||||
homeserverSupportsCrossSigning,
|
||||
crossSigningReady,
|
||||
secretStorageKeyNeedsUpgrade,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -150,7 +147,6 @@ export default class CrossSigningPanel extends React.PureComponent {
|
|||
secretStorageKeyInAccount,
|
||||
homeserverSupportsCrossSigning,
|
||||
crossSigningReady,
|
||||
secretStorageKeyNeedsUpgrade,
|
||||
} = this.state;
|
||||
|
||||
let errorSection;
|
||||
|
@ -259,10 +255,6 @@ export default class CrossSigningPanel extends React.PureComponent {
|
|||
<td>{_t("Homeserver feature support:")}</td>
|
||||
<td>{homeserverSupportsCrossSigning ? _t("exists") : _t("not found")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{_t("Secret Storage key format:")}</td>
|
||||
<td>{secretStorageKeyNeedsUpgrade ? _t("outdated") : _t("up to date")}</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</details>
|
||||
{errorSection}
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
import React from "react";
|
||||
import createReactClass from 'create-react-class';
|
||||
import Notifier from "../../../Notifier";
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
export default createReactClass({
|
||||
|
|
|
@ -19,7 +19,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import * as sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import dis from '../../../dispatcher';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import {Key} from "../../../Keyboard";
|
||||
|
||||
export default class IntegrationManager extends React.Component {
|
||||
|
|
|
@ -21,7 +21,7 @@ import {_t} from "../../../languageHandler";
|
|||
import * as sdk from '../../../index';
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import Modal from '../../../Modal';
|
||||
import dis from "../../../dispatcher";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { getThreepidsWithBindStatus } from '../../../boundThreepids';
|
||||
import IdentityAuthClient from "../../../IdentityAuthClient";
|
||||
import {abbreviateUrl, unabbreviateUrl} from "../../../utils/UrlUtils";
|
||||
|
|
|
@ -21,7 +21,7 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
|||
import * as sdk from "../../../../..";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import Modal from "../../../../../Modal";
|
||||
import dis from "../../../../../dispatcher";
|
||||
import dis from "../../../../../dispatcher/dispatcher";
|
||||
|
||||
export default class AdvancedRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -20,7 +20,7 @@ import {_t} from "../../../../../languageHandler";
|
|||
import RoomProfileSettings from "../../../room_settings/RoomProfileSettings";
|
||||
import * as sdk from "../../../../..";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import dis from "../../../../../dispatcher";
|
||||
import dis from "../../../../../dispatcher/dispatcher";
|
||||
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
|
||||
|
||||
export default class GeneralRoomSettingsTab extends React.Component {
|
||||
|
|
|
@ -32,7 +32,7 @@ import PlatformPeg from "../../../../../PlatformPeg";
|
|||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import * as sdk from "../../../../..";
|
||||
import Modal from "../../../../../Modal";
|
||||
import dis from "../../../../../dispatcher";
|
||||
import dis from "../../../../../dispatcher/dispatcher";
|
||||
import {Service, startTermsFlow} from "../../../../../Terms";
|
||||
import {SERVICE_TYPES} from "matrix-js-sdk";
|
||||
import IdentityAuthClient from "../../../../../IdentityAuthClient";
|
||||
|
@ -348,7 +348,7 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
// For newer homeservers with separate 3PID add and bind methods (MSC2290),
|
||||
// there is no such concern, so we can always show the HS account 3PIDs.
|
||||
if (this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true) {
|
||||
const emails = this.state.loading3pids || true
|
||||
const emails = this.state.loading3pids
|
||||
? <Spinner />
|
||||
: <EmailAddresses
|
||||
emails={this.state.emails}
|
||||
|
|
|
@ -25,7 +25,7 @@ import Analytics from "../../../../../Analytics";
|
|||
import Modal from "../../../../../Modal";
|
||||
import * as sdk from "../../../../..";
|
||||
import {sleep} from "../../../../../utils/promise";
|
||||
import dis from "../../../../../dispatcher";
|
||||
import dis from "../../../../../dispatcher/dispatcher";
|
||||
|
||||
export class IgnoredUser extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue