Remove various remaining bits of ILAG flows
TypeScript helpfully pointed me towards this dead code, which has been floating around unused for a while. If we want to bring back ILAG in the future, we can always revive it from history.
This commit is contained in:
parent
1b255e42c3
commit
f2b72efe39
13 changed files with 40 additions and 877 deletions
|
@ -7,7 +7,6 @@ src/components/structures/SearchBox.js
|
||||||
src/components/structures/UploadBar.js
|
src/components/structures/UploadBar.js
|
||||||
src/components/views/avatars/MemberAvatar.js
|
src/components/views/avatars/MemberAvatar.js
|
||||||
src/components/views/create_room/RoomAlias.js
|
src/components/views/create_room/RoomAlias.js
|
||||||
src/components/views/dialogs/SetPasswordDialog.js
|
|
||||||
src/components/views/elements/AddressSelector.js
|
src/components/views/elements/AddressSelector.js
|
||||||
src/components/views/elements/DirectorySearchBox.js
|
src/components/views/elements/DirectorySearchBox.js
|
||||||
src/components/views/elements/MemberEventListSummary.js
|
src/components/views/elements/MemberEventListSummary.js
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
|
||||||
Copyright 2017 Vector Creations 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.mx_SetMxIdDialog .mx_Dialog_title {
|
|
||||||
padding-right: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SetMxIdDialog_input_group {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SetMxIdDialog_input {
|
|
||||||
border-radius: 3px;
|
|
||||||
border: 1px solid $input-border-color;
|
|
||||||
padding: 9px;
|
|
||||||
color: $primary-fg-color;
|
|
||||||
background-color: $primary-bg-color;
|
|
||||||
font-size: $font-15px;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 280px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SetMxIdDialog_input.error,
|
|
||||||
.mx_SetMxIdDialog_input.error:focus {
|
|
||||||
border: 1px solid $warning-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SetMxIdDialog_input_group .mx_Spinner {
|
|
||||||
height: 37px;
|
|
||||||
padding-left: 10px;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SetMxIdDialog .success {
|
|
||||||
color: $accent-color;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.mx_SetPasswordDialog_change_password input {
|
|
||||||
border-radius: 3px;
|
|
||||||
border: 1px solid $input-border-color;
|
|
||||||
padding: 9px;
|
|
||||||
color: $primary-fg-color;
|
|
||||||
background-color: $primary-bg-color;
|
|
||||||
font-size: $font-15px;
|
|
||||||
max-width: 280px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SetPasswordDialog_change_password_button {
|
|
||||||
margin-top: 68px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SetPasswordDialog .mx_Dialog_content {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
|
@ -512,19 +512,8 @@ async function _doSetLoggedIn(
|
||||||
if (localStorage) {
|
if (localStorage) {
|
||||||
try {
|
try {
|
||||||
_persistCredentialsToLocalStorage(credentials);
|
_persistCredentialsToLocalStorage(credentials);
|
||||||
|
|
||||||
// make sure we don't think that it's a fresh login any more
|
// make sure we don't think that it's a fresh login any more
|
||||||
sessionStorage.removeItem("mx_fresh_login");
|
sessionStorage.removeItem("mx_fresh_login");
|
||||||
|
|
||||||
// The user registered as a PWLU (PassWord-Less User), the generated password
|
|
||||||
// is cached here such that the user can change it at a later time.
|
|
||||||
if (credentials.password) {
|
|
||||||
// Update SessionStore
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'cached_password',
|
|
||||||
cachedPassword: credentials.password,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Error using local storage: can't persist session!", e);
|
console.warn("Error using local storage: can't persist session!", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import dis from './dispatcher/dispatcher';
|
||||||
import * as sdk from './index';
|
import * as sdk from './index';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import { _t } from './languageHandler';
|
import { _t } from './languageHandler';
|
||||||
// import {MatrixClientPeg} from './MatrixClientPeg';
|
|
||||||
|
|
||||||
// Regex for what a "safe" or "Matrix-looking" localpart would be.
|
// Regex for what a "safe" or "Matrix-looking" localpart would be.
|
||||||
// TODO: Update as needed for https://github.com/matrix-org/matrix-doc/issues/1514
|
// TODO: Update as needed for https://github.com/matrix-org/matrix-doc/issues/1514
|
||||||
|
@ -44,29 +43,6 @@ export const SAFE_LOCALPART_REGEX = /^[a-z0-9=_\-./]+$/;
|
||||||
*/
|
*/
|
||||||
export async function startAnyRegistrationFlow(options) {
|
export async function startAnyRegistrationFlow(options) {
|
||||||
if (options === undefined) options = {};
|
if (options === undefined) options = {};
|
||||||
// look for an ILAG compatible flow. We define this as one
|
|
||||||
// which has only dummy or recaptcha flows. In practice it
|
|
||||||
// would support any stage InteractiveAuth supports, just not
|
|
||||||
// ones like email & msisdn which require the user to supply
|
|
||||||
// the relevant details in advance. We err on the side of
|
|
||||||
// caution though.
|
|
||||||
|
|
||||||
// XXX: ILAG is disabled for now,
|
|
||||||
// see https://github.com/vector-im/element-web/issues/8222
|
|
||||||
|
|
||||||
// const flows = await _getRegistrationFlows();
|
|
||||||
// const hasIlagFlow = flows.some((flow) => {
|
|
||||||
// return flow.stages.every((stage) => {
|
|
||||||
// return ['m.login.dummy', 'm.login.recaptcha', 'm.login.terms'].includes(stage);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// if (hasIlagFlow) {
|
|
||||||
// dis.dispatch({
|
|
||||||
// action: 'view_set_mxid',
|
|
||||||
// go_home_on_cancel: options.go_home_on_cancel,
|
|
||||||
// });
|
|
||||||
//} else {
|
|
||||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
const modal = Modal.createTrackedDialog('Registration required', '', QuestionDialog, {
|
const modal = Modal.createTrackedDialog('Registration required', '', QuestionDialog, {
|
||||||
hasCancelButton: true,
|
hasCancelButton: true,
|
||||||
|
@ -90,24 +66,4 @@ export async function startAnyRegistrationFlow(options) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// async function _getRegistrationFlows() {
|
|
||||||
// try {
|
|
||||||
// await MatrixClientPeg.get().register(
|
|
||||||
// null,
|
|
||||||
// null,
|
|
||||||
// undefined,
|
|
||||||
// {},
|
|
||||||
// {},
|
|
||||||
// );
|
|
||||||
// console.log("Register request succeeded when it should have returned 401!");
|
|
||||||
// } catch (e) {
|
|
||||||
// if (e.httpStatus === 401) {
|
|
||||||
// return e.data.flows;
|
|
||||||
// }
|
|
||||||
// throw e;
|
|
||||||
// }
|
|
||||||
// throw new Error("Register request succeeded when it should have returned 401!");
|
|
||||||
// }
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ import CallMediaHandler from '../../CallMediaHandler';
|
||||||
import { fixupColorFonts } from '../../utils/FontManager';
|
import { fixupColorFonts } from '../../utils/FontManager';
|
||||||
import * as sdk from '../../index';
|
import * as sdk from '../../index';
|
||||||
import dis from '../../dispatcher/dispatcher';
|
import dis from '../../dispatcher/dispatcher';
|
||||||
import sessionStore from '../../stores/SessionStore';
|
|
||||||
import {MatrixClientPeg, IMatrixClientCreds} from '../../MatrixClientPeg';
|
import {MatrixClientPeg, IMatrixClientCreds} from '../../MatrixClientPeg';
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
|
|
||||||
|
@ -41,10 +40,6 @@ import HomePage from "./HomePage";
|
||||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||||
import PlatformPeg from "../../PlatformPeg";
|
import PlatformPeg from "../../PlatformPeg";
|
||||||
import { DefaultTagID } from "../../stores/room-list/models";
|
import { DefaultTagID } from "../../stores/room-list/models";
|
||||||
import {
|
|
||||||
showToast as showSetPasswordToast,
|
|
||||||
hideToast as hideSetPasswordToast,
|
|
||||||
} from "../../toasts/SetPasswordToast";
|
|
||||||
import {
|
import {
|
||||||
showToast as showServerLimitToast,
|
showToast as showServerLimitToast,
|
||||||
hideToast as hideServerLimitToast,
|
hideToast as hideServerLimitToast,
|
||||||
|
@ -149,8 +144,6 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
protected readonly _matrixClient: MatrixClient;
|
protected readonly _matrixClient: MatrixClient;
|
||||||
protected readonly _roomView: React.RefObject<any>;
|
protected readonly _roomView: React.RefObject<any>;
|
||||||
protected readonly _resizeContainer: React.RefObject<ResizeHandle>;
|
protected readonly _resizeContainer: React.RefObject<ResizeHandle>;
|
||||||
protected readonly _sessionStore: sessionStore;
|
|
||||||
protected readonly _sessionStoreToken: { remove: () => void };
|
|
||||||
protected readonly _compactLayoutWatcherRef: string;
|
protected readonly _compactLayoutWatcherRef: string;
|
||||||
protected resizer: Resizer;
|
protected resizer: Resizer;
|
||||||
|
|
||||||
|
@ -171,12 +164,6 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
document.addEventListener('keydown', this._onNativeKeyDown, false);
|
document.addEventListener('keydown', this._onNativeKeyDown, false);
|
||||||
|
|
||||||
this._sessionStore = sessionStore;
|
|
||||||
this._sessionStoreToken = this._sessionStore.addListener(
|
|
||||||
this._setStateFromSessionStore,
|
|
||||||
);
|
|
||||||
this._setStateFromSessionStore();
|
|
||||||
|
|
||||||
this._updateServerNoticeEvents();
|
this._updateServerNoticeEvents();
|
||||||
|
|
||||||
this._matrixClient.on("accountData", this.onAccountData);
|
this._matrixClient.on("accountData", this.onAccountData);
|
||||||
|
@ -205,9 +192,6 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
this._matrixClient.removeListener("sync", this.onSync);
|
this._matrixClient.removeListener("sync", this.onSync);
|
||||||
this._matrixClient.removeListener("RoomState.events", this.onRoomStateEvents);
|
this._matrixClient.removeListener("RoomState.events", this.onRoomStateEvents);
|
||||||
SettingsStore.unwatchSetting(this._compactLayoutWatcherRef);
|
SettingsStore.unwatchSetting(this._compactLayoutWatcherRef);
|
||||||
if (this._sessionStoreToken) {
|
|
||||||
this._sessionStoreToken.remove();
|
|
||||||
}
|
|
||||||
this.resizer.detach();
|
this.resizer.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,14 +212,6 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
return this._roomView.current.canResetTimeline();
|
return this._roomView.current.canResetTimeline();
|
||||||
};
|
};
|
||||||
|
|
||||||
_setStateFromSessionStore = () => {
|
|
||||||
if (this._sessionStore.getCachedPassword()) {
|
|
||||||
showSetPasswordToast();
|
|
||||||
} else {
|
|
||||||
hideSetPasswordToast();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_createResizer() {
|
_createResizer() {
|
||||||
const classNames = {
|
const classNames = {
|
||||||
handle: "mx_ResizeHandle",
|
handle: "mx_ResizeHandle",
|
||||||
|
|
|
@ -670,9 +670,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
case 'view_home_page':
|
case 'view_home_page':
|
||||||
this.viewHome();
|
this.viewHome();
|
||||||
break;
|
break;
|
||||||
case 'view_set_mxid':
|
|
||||||
this.setMxId(payload);
|
|
||||||
break;
|
|
||||||
case 'view_start_chat_or_reuse':
|
case 'view_start_chat_or_reuse':
|
||||||
this.chatCreateOrReuse(payload.user_id);
|
this.chatCreateOrReuse(payload.user_id);
|
||||||
break;
|
break;
|
||||||
|
@ -985,36 +982,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setMxId(payload) {
|
|
||||||
const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
|
|
||||||
const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, {
|
|
||||||
homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(),
|
|
||||||
onFinished: (submitted, credentials) => {
|
|
||||||
if (!submitted) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'cancel_after_sync_prepared',
|
|
||||||
});
|
|
||||||
if (payload.go_home_on_cancel) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'view_home_page',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MatrixClientPeg.setJustRegisteredUserId(credentials.user_id);
|
|
||||||
this.onRegistered(credentials);
|
|
||||||
},
|
|
||||||
onDifferentServerClicked: (ev) => {
|
|
||||||
dis.dispatch({action: 'start_registration'});
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
onLoginClick: (ev) => {
|
|
||||||
dis.dispatch({action: 'start_login'});
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
}).close;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async createRoom(defaultPublic = false) {
|
private async createRoom(defaultPublic = false) {
|
||||||
const communityId = CommunityPrototypeStore.instance.getSelectedCommunityId();
|
const communityId = CommunityPrototypeStore.instance.getSelectedCommunityId();
|
||||||
if (communityId) {
|
if (communityId) {
|
||||||
|
|
|
@ -1090,42 +1090,7 @@ export default class RoomView extends React.Component<IProps, IState> {
|
||||||
room_id: this.getRoomId(),
|
room_id: this.getRoomId(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Don't peek whilst registering otherwise getPendingEventList complains
|
|
||||||
// Do this by indicating our intention to join
|
|
||||||
|
|
||||||
// XXX: ILAG is disabled for now,
|
|
||||||
// see https://github.com/vector-im/element-web/issues/8222
|
|
||||||
dis.dispatch({action: 'require_registration'});
|
dis.dispatch({action: 'require_registration'});
|
||||||
// dis.dispatch({
|
|
||||||
// action: 'will_join',
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog');
|
|
||||||
// const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, {
|
|
||||||
// homeserverUrl: cli.getHomeserverUrl(),
|
|
||||||
// onFinished: (submitted, credentials) => {
|
|
||||||
// if (submitted) {
|
|
||||||
// this.props.onRegistered(credentials);
|
|
||||||
// } else {
|
|
||||||
// dis.dispatch({
|
|
||||||
// action: 'cancel_after_sync_prepared',
|
|
||||||
// });
|
|
||||||
// dis.dispatch({
|
|
||||||
// action: 'cancel_join',
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// onDifferentServerClicked: (ev) => {
|
|
||||||
// dis.dispatch({action: 'start_registration'});
|
|
||||||
// close();
|
|
||||||
// },
|
|
||||||
// onLoginClick: (ev) => {
|
|
||||||
// dis.dispatch({action: 'start_login'});
|
|
||||||
// close();
|
|
||||||
// },
|
|
||||||
// }).close;
|
|
||||||
// return;
|
|
||||||
} else {
|
} else {
|
||||||
Promise.resolve().then(() => {
|
Promise.resolve().then(() => {
|
||||||
const signUrl = this.props.threepidInvite?.signUrl;
|
const signUrl = this.props.threepidInvite?.signUrl;
|
||||||
|
|
|
@ -1,304 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2016 OpenMarket Ltd
|
|
||||||
Copyright 2017 Vector Creations 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, {createRef} from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import * as sdk from '../../../index';
|
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { Key } from '../../../Keyboard';
|
|
||||||
import { _t } from '../../../languageHandler';
|
|
||||||
import { SAFE_LOCALPART_REGEX } from '../../../Registration';
|
|
||||||
|
|
||||||
// The amount of time to wait for further changes to the input username before
|
|
||||||
// sending a request to the server
|
|
||||||
const USERNAME_CHECK_DEBOUNCE_MS = 250;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prompt the user to set a display name.
|
|
||||||
*
|
|
||||||
* On success, `onFinished(true, newDisplayName)` is called.
|
|
||||||
*/
|
|
||||||
export default class SetMxIdDialog extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
onFinished: PropTypes.func.isRequired,
|
|
||||||
// Called when the user requests to register with a different homeserver
|
|
||||||
onDifferentServerClicked: PropTypes.func.isRequired,
|
|
||||||
// Called if the user wants to switch to login instead
|
|
||||||
onLoginClick: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this._input_value = createRef();
|
|
||||||
this._uiAuth = createRef();
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
// The entered username
|
|
||||||
username: '',
|
|
||||||
// Indicate ongoing work on the username
|
|
||||||
usernameBusy: false,
|
|
||||||
// Indicate error with username
|
|
||||||
usernameError: '',
|
|
||||||
// Assume the homeserver supports username checking until "M_UNRECOGNIZED"
|
|
||||||
usernameCheckSupport: true,
|
|
||||||
|
|
||||||
// Whether the auth UI is currently being used
|
|
||||||
doingUIAuth: false,
|
|
||||||
// Indicate error with auth
|
|
||||||
authError: '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this._input_value.current.select();
|
|
||||||
|
|
||||||
this._matrixClient = MatrixClientPeg.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
onValueChange = ev => {
|
|
||||||
this.setState({
|
|
||||||
username: ev.target.value,
|
|
||||||
usernameBusy: true,
|
|
||||||
usernameError: '',
|
|
||||||
}, () => {
|
|
||||||
if (!this.state.username || !this.state.usernameCheckSupport) {
|
|
||||||
this.setState({
|
|
||||||
usernameBusy: false,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debounce the username check to limit number of requests sent
|
|
||||||
if (this._usernameCheckTimeout) {
|
|
||||||
clearTimeout(this._usernameCheckTimeout);
|
|
||||||
}
|
|
||||||
this._usernameCheckTimeout = setTimeout(() => {
|
|
||||||
this._doUsernameCheck().finally(() => {
|
|
||||||
this.setState({
|
|
||||||
usernameBusy: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, USERNAME_CHECK_DEBOUNCE_MS);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onKeyUp = ev => {
|
|
||||||
if (ev.key === Key.ENTER) {
|
|
||||||
this.onSubmit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onSubmit = ev => {
|
|
||||||
if (this._uiAuth.current) {
|
|
||||||
this._uiAuth.current.tryContinue();
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
doingUIAuth: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_doUsernameCheck() {
|
|
||||||
// We do a quick check ahead of the username availability API to ensure the
|
|
||||||
// user ID roughly looks okay from a Matrix perspective.
|
|
||||||
if (!SAFE_LOCALPART_REGEX.test(this.state.username)) {
|
|
||||||
this.setState({
|
|
||||||
usernameError: _t("A username can only contain lower case letters, numbers and '=_-./'"),
|
|
||||||
});
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if username is available
|
|
||||||
return this._matrixClient.isUsernameAvailable(this.state.username).then(
|
|
||||||
(isAvailable) => {
|
|
||||||
if (isAvailable) {
|
|
||||||
this.setState({usernameError: ''});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
// Indicate whether the homeserver supports username checking
|
|
||||||
const newState = {
|
|
||||||
usernameCheckSupport: err.errcode !== "M_UNRECOGNIZED",
|
|
||||||
};
|
|
||||||
console.error('Error whilst checking username availability: ', err);
|
|
||||||
switch (err.errcode) {
|
|
||||||
case "M_USER_IN_USE":
|
|
||||||
newState.usernameError = _t('Username not available');
|
|
||||||
break;
|
|
||||||
case "M_INVALID_USERNAME":
|
|
||||||
newState.usernameError = _t(
|
|
||||||
'Username invalid: %(errMessage)s',
|
|
||||||
{ errMessage: err.message},
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "M_UNRECOGNIZED":
|
|
||||||
// This homeserver doesn't support username checking, assume it's
|
|
||||||
// fine and rely on the error appearing in registration step.
|
|
||||||
newState.usernameError = '';
|
|
||||||
break;
|
|
||||||
case undefined:
|
|
||||||
newState.usernameError = _t('Something went wrong!');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
newState.usernameError = _t(
|
|
||||||
'An error occurred: %(error_string)s',
|
|
||||||
{ error_string: err.message },
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.setState(newState);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_generatePassword() {
|
|
||||||
return Math.random().toString(36).slice(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_makeRegisterRequest = auth => {
|
|
||||||
// Not upgrading - changing mxids
|
|
||||||
const guestAccessToken = null;
|
|
||||||
if (!this._generatedPassword) {
|
|
||||||
this._generatedPassword = this._generatePassword();
|
|
||||||
}
|
|
||||||
return this._matrixClient.register(
|
|
||||||
this.state.username,
|
|
||||||
this._generatedPassword,
|
|
||||||
undefined, // session id: included in the auth dict already
|
|
||||||
auth,
|
|
||||||
{},
|
|
||||||
guestAccessToken,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
_onUIAuthFinished = (success, response) => {
|
|
||||||
this.setState({
|
|
||||||
doingUIAuth: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
this.setState({ authError: response.message });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.onFinished(true, {
|
|
||||||
userId: response.user_id,
|
|
||||||
deviceId: response.device_id,
|
|
||||||
homeserverUrl: this._matrixClient.getHomeserverUrl(),
|
|
||||||
identityServerUrl: this._matrixClient.getIdentityServerUrl(),
|
|
||||||
accessToken: response.access_token,
|
|
||||||
password: this._generatedPassword,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
|
||||||
const InteractiveAuth = sdk.getComponent('structures.InteractiveAuth');
|
|
||||||
|
|
||||||
let auth;
|
|
||||||
if (this.state.doingUIAuth) {
|
|
||||||
auth = <InteractiveAuth
|
|
||||||
matrixClient={this._matrixClient}
|
|
||||||
makeRequest={this._makeRegisterRequest}
|
|
||||||
onAuthFinished={this._onUIAuthFinished}
|
|
||||||
inputs={{}}
|
|
||||||
poll={true}
|
|
||||||
ref={this._uiAuth}
|
|
||||||
continueIsManaged={true}
|
|
||||||
/>;
|
|
||||||
}
|
|
||||||
const inputClasses = classnames({
|
|
||||||
"mx_SetMxIdDialog_input": true,
|
|
||||||
"error": Boolean(this.state.usernameError),
|
|
||||||
});
|
|
||||||
|
|
||||||
let usernameIndicator = null;
|
|
||||||
if (this.state.usernameBusy) {
|
|
||||||
usernameIndicator = <div>{_t("Checking...")}</div>;
|
|
||||||
} else {
|
|
||||||
const usernameAvailable = this.state.username &&
|
|
||||||
this.state.usernameCheckSupport && !this.state.usernameError;
|
|
||||||
const usernameIndicatorClasses = classnames({
|
|
||||||
"error": Boolean(this.state.usernameError),
|
|
||||||
"success": usernameAvailable,
|
|
||||||
});
|
|
||||||
usernameIndicator = <div className={usernameIndicatorClasses} role="alert">
|
|
||||||
{ usernameAvailable ? _t('Username available') : this.state.usernameError }
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let authErrorIndicator = null;
|
|
||||||
if (this.state.authError) {
|
|
||||||
authErrorIndicator = <div className="error" role="alert">
|
|
||||||
{ this.state.authError }
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const canContinue = this.state.username &&
|
|
||||||
!this.state.usernameError &&
|
|
||||||
!this.state.usernameBusy;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<BaseDialog className="mx_SetMxIdDialog"
|
|
||||||
onFinished={this.props.onFinished}
|
|
||||||
title={_t('To get started, please pick a username!')}
|
|
||||||
contentId='mx_Dialog_content'
|
|
||||||
>
|
|
||||||
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
|
||||||
<div className="mx_SetMxIdDialog_input_group">
|
|
||||||
<input type="text" ref={this._input_value} value={this.state.username}
|
|
||||||
autoFocus={true}
|
|
||||||
onChange={this.onValueChange}
|
|
||||||
onKeyUp={this.onKeyUp}
|
|
||||||
size="30"
|
|
||||||
className={inputClasses}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{ usernameIndicator }
|
|
||||||
<p>
|
|
||||||
{ _t(
|
|
||||||
'This will be your account name on the <span></span> ' +
|
|
||||||
'homeserver, or you can pick a <a>different server</a>.',
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
'span': <span>{ this.props.homeserverUrl }</span>,
|
|
||||||
'a': (sub) => <a href="#" onClick={this.props.onDifferentServerClicked}>{ sub }</a>,
|
|
||||||
},
|
|
||||||
) }
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{ _t(
|
|
||||||
'If you already have a Matrix account you can <a>log in</a> instead.',
|
|
||||||
{},
|
|
||||||
{ 'a': (sub) => <a href="#" onClick={this.props.onLoginClick}>{ sub }</a> },
|
|
||||||
) }
|
|
||||||
</p>
|
|
||||||
{ auth }
|
|
||||||
{ authErrorIndicator }
|
|
||||||
</div>
|
|
||||||
<div className="mx_Dialog_buttons">
|
|
||||||
<input className="mx_Dialog_primary"
|
|
||||||
type="submit"
|
|
||||||
value={_t("Continue")}
|
|
||||||
onClick={this.onSubmit}
|
|
||||||
disabled={!canContinue}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</BaseDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,130 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
Copyright 2018 New Vector Ltd
|
|
||||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
|
||||||
|
|
||||||
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 * as sdk from '../../../index';
|
|
||||||
import { _t } from '../../../languageHandler';
|
|
||||||
import Modal from '../../../Modal';
|
|
||||||
|
|
||||||
const WarmFuzzy = function(props) {
|
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
|
||||||
let title = _t('You have successfully set a password!');
|
|
||||||
if (props.didSetEmail) {
|
|
||||||
title = _t('You have successfully set a password and an email address!');
|
|
||||||
}
|
|
||||||
const advice = _t('You can now return to your account after signing out, and sign in on other devices.');
|
|
||||||
let extraAdvice = null;
|
|
||||||
if (!props.didSetEmail) {
|
|
||||||
extraAdvice = _t('Remember, you can always set an email address in user settings if you change your mind.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return <BaseDialog className="mx_SetPasswordDialog"
|
|
||||||
onFinished={props.onFinished}
|
|
||||||
title={ title }
|
|
||||||
>
|
|
||||||
<div className="mx_Dialog_content">
|
|
||||||
<p>
|
|
||||||
{ advice }
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{ extraAdvice }
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="mx_Dialog_buttons">
|
|
||||||
<button
|
|
||||||
className="mx_Dialog_primary"
|
|
||||||
autoFocus={true}
|
|
||||||
onClick={props.onFinished}>
|
|
||||||
{ _t('Continue') }
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</BaseDialog>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prompt the user to set a password
|
|
||||||
*
|
|
||||||
* On success, `onFinished()` when finished
|
|
||||||
*/
|
|
||||||
export default class SetPasswordDialog extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
onFinished: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
error: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
_onPasswordChanged = res => {
|
|
||||||
Modal.createDialog(WarmFuzzy, {
|
|
||||||
didSetEmail: res.didSetEmail,
|
|
||||||
onFinished: () => {
|
|
||||||
this.props.onFinished();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_onPasswordChangeError = err => {
|
|
||||||
let errMsg = err.error || "";
|
|
||||||
if (err.httpStatus === 403) {
|
|
||||||
errMsg = _t('Failed to change password. Is your password correct?');
|
|
||||||
} else if (err.httpStatus) {
|
|
||||||
errMsg += ' ' + _t(
|
|
||||||
'(HTTP status %(httpStatus)s)',
|
|
||||||
{ httpStatus: err.httpStatus },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
error: errMsg,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
|
||||||
const ChangePassword = sdk.getComponent('views.settings.ChangePassword');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<BaseDialog className="mx_SetPasswordDialog"
|
|
||||||
onFinished={this.props.onFinished}
|
|
||||||
title={ _t('Please set a password!') }
|
|
||||||
>
|
|
||||||
<div className="mx_Dialog_content">
|
|
||||||
<p>
|
|
||||||
{ _t('This will allow you to return to your account after signing out, and sign in on other sessions.') }
|
|
||||||
</p>
|
|
||||||
<ChangePassword
|
|
||||||
className="mx_SetPasswordDialog_change_password"
|
|
||||||
rowClassName=""
|
|
||||||
buttonClassNames="mx_Dialog_primary mx_SetPasswordDialog_change_password_button"
|
|
||||||
buttonKind="primary"
|
|
||||||
confirm={false}
|
|
||||||
autoFocusNewPasswordInput={true}
|
|
||||||
shouldAskForEmail={true}
|
|
||||||
onError={this._onPasswordChangeError}
|
|
||||||
onFinished={this._onPasswordChanged}
|
|
||||||
buttonLabel={_t("Set Password")}
|
|
||||||
/>
|
|
||||||
<div className="error">
|
|
||||||
{ this.state.error }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</BaseDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,14 +19,12 @@ import Field from "../elements/Field";
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import Spinner from '../elements/Spinner';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import * as sdk from "../../../index";
|
import * as sdk from "../../../index";
|
||||||
import Modal from "../../../Modal";
|
import Modal from "../../../Modal";
|
||||||
|
|
||||||
import sessionStore from '../../../stores/SessionStore';
|
|
||||||
|
|
||||||
export default class ChangePassword extends React.Component {
|
export default class ChangePassword extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onFinished: PropTypes.func,
|
onFinished: PropTypes.func,
|
||||||
|
@ -66,33 +64,11 @@ export default class ChangePassword extends React.Component {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
phase: ChangePassword.Phases.Edit,
|
phase: ChangePassword.Phases.Edit,
|
||||||
cachedPassword: null,
|
|
||||||
oldPassword: "",
|
oldPassword: "",
|
||||||
newPassword: "",
|
newPassword: "",
|
||||||
newPasswordConfirm: "",
|
newPasswordConfirm: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this._sessionStore = sessionStore;
|
|
||||||
this._sessionStoreToken = this._sessionStore.addListener(
|
|
||||||
this._setStateFromSessionStore,
|
|
||||||
);
|
|
||||||
|
|
||||||
this._setStateFromSessionStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this._sessionStoreToken) {
|
|
||||||
this._sessionStoreToken.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_setStateFromSessionStore = () => {
|
|
||||||
this.setState({
|
|
||||||
cachedPassword: this._sessionStore.getCachedPassword(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
changePassword(oldPassword, newPassword) {
|
changePassword(oldPassword, newPassword) {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
|
@ -119,8 +95,11 @@ export default class ChangePassword extends React.Component {
|
||||||
</div>,
|
</div>,
|
||||||
button: _t("Continue"),
|
button: _t("Continue"),
|
||||||
extraButtons: [
|
extraButtons: [
|
||||||
<button className="mx_Dialog_primary"
|
<button
|
||||||
onClick={this._onExportE2eKeysClicked}>
|
key="exportRoomKeys"
|
||||||
|
className="mx_Dialog_primary"
|
||||||
|
onClick={this._onExportE2eKeysClicked}
|
||||||
|
>
|
||||||
{ _t('Export E2E room keys') }
|
{ _t('Export E2E room keys') }
|
||||||
</button>,
|
</button>,
|
||||||
],
|
],
|
||||||
|
@ -150,9 +129,6 @@ export default class ChangePassword extends React.Component {
|
||||||
});
|
});
|
||||||
|
|
||||||
cli.setPassword(authDict, newPassword).then(() => {
|
cli.setPassword(authDict, newPassword).then(() => {
|
||||||
// Notify SessionStore that the user's password was changed
|
|
||||||
dis.dispatch({action: 'password_changed'});
|
|
||||||
|
|
||||||
if (this.props.shouldAskForEmail) {
|
if (this.props.shouldAskForEmail) {
|
||||||
return this._optionallySetEmail().then((confirmed) => {
|
return this._optionallySetEmail().then((confirmed) => {
|
||||||
this.props.onFinished({
|
this.props.onFinished({
|
||||||
|
@ -212,7 +188,7 @@ export default class ChangePassword extends React.Component {
|
||||||
|
|
||||||
onClickChange = (ev) => {
|
onClickChange = (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const oldPassword = this.state.cachedPassword || this.state.oldPassword;
|
const oldPassword = this.state.oldPassword;
|
||||||
const newPassword = this.state.newPassword;
|
const newPassword = this.state.newPassword;
|
||||||
const confirmPassword = this.state.newPasswordConfirm;
|
const confirmPassword = this.state.newPasswordConfirm;
|
||||||
const err = this.props.onCheckPassword(
|
const err = this.props.onCheckPassword(
|
||||||
|
@ -231,9 +207,10 @@ export default class ChangePassword extends React.Component {
|
||||||
const rowClassName = this.props.rowClassName;
|
const rowClassName = this.props.rowClassName;
|
||||||
const buttonClassName = this.props.buttonClassName;
|
const buttonClassName = this.props.buttonClassName;
|
||||||
|
|
||||||
let currentPassword = null;
|
switch (this.state.phase) {
|
||||||
if (!this.state.cachedPassword) {
|
case ChangePassword.Phases.Edit:
|
||||||
currentPassword = (
|
return (
|
||||||
|
<form className={this.props.className} onSubmit={this.onClickChange}>
|
||||||
<div className={rowClassName}>
|
<div className={rowClassName}>
|
||||||
<Field
|
<Field
|
||||||
type="password"
|
type="password"
|
||||||
|
@ -242,20 +219,10 @@ export default class ChangePassword extends React.Component {
|
||||||
onChange={this.onChangeOldPassword}
|
onChange={this.onChangeOldPassword}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this.state.phase) {
|
|
||||||
case ChangePassword.Phases.Edit:
|
|
||||||
const passwordLabel = this.state.cachedPassword ?
|
|
||||||
_t('Password') : _t('New Password');
|
|
||||||
return (
|
|
||||||
<form className={this.props.className} onSubmit={this.onClickChange}>
|
|
||||||
{ currentPassword }
|
|
||||||
<div className={rowClassName}>
|
<div className={rowClassName}>
|
||||||
<Field
|
<Field
|
||||||
type="password"
|
type="password"
|
||||||
label={passwordLabel}
|
label={_t('New Password')}
|
||||||
value={this.state.newPassword}
|
value={this.state.newPassword}
|
||||||
autoFocus={this.props.autoFocusNewPasswordInput}
|
autoFocus={this.props.autoFocusNewPasswordInput}
|
||||||
onChange={this.onChangeNewPassword}
|
onChange={this.onChangeNewPassword}
|
||||||
|
@ -277,10 +244,9 @@ export default class ChangePassword extends React.Component {
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
case ChangePassword.Phases.Uploading:
|
case ChangePassword.Phases.Uploading:
|
||||||
var Loader = sdk.getComponent("elements.Spinner");
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_Dialog_content">
|
<div className="mx_Dialog_content">
|
||||||
<Loader />
|
<Spinner />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
Copyright 2019 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 dis from '../dispatcher/dispatcher';
|
|
||||||
import {Store} from 'flux/utils';
|
|
||||||
|
|
||||||
const INITIAL_STATE = {
|
|
||||||
cachedPassword: localStorage.getItem('mx_pass'),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for storing application state to do with the session. This is a simple flux
|
|
||||||
* store that listens for actions and updates its state accordingly, informing any
|
|
||||||
* listeners (views) of state changes.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* ```
|
|
||||||
* sessionStore.addListener(() => {
|
|
||||||
* this.setState({ cachedPassword: sessionStore.getCachedPassword() })
|
|
||||||
* })
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
class SessionStore extends Store {
|
|
||||||
constructor() {
|
|
||||||
super(dis);
|
|
||||||
|
|
||||||
// Initialise state
|
|
||||||
this._state = INITIAL_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_update() {
|
|
||||||
// Persist state to localStorage
|
|
||||||
if (this._state.cachedPassword) {
|
|
||||||
localStorage.setItem('mx_pass', this._state.cachedPassword);
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem('mx_pass', this._state.cachedPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.__emitChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
_setState(newState) {
|
|
||||||
this._state = Object.assign(this._state, newState);
|
|
||||||
this._update();
|
|
||||||
}
|
|
||||||
|
|
||||||
__onDispatch(payload) {
|
|
||||||
switch (payload.action) {
|
|
||||||
case 'cached_password':
|
|
||||||
this._setState({
|
|
||||||
cachedPassword: payload.cachedPassword,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'password_changed':
|
|
||||||
this._setState({
|
|
||||||
cachedPassword: null,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'on_client_not_viable':
|
|
||||||
case 'on_logged_out':
|
|
||||||
this._setState({
|
|
||||||
cachedPassword: null,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCachedPassword() {
|
|
||||||
return this._state.cachedPassword;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let singletonSessionStore = null;
|
|
||||||
if (!singletonSessionStore) {
|
|
||||||
singletonSessionStore = new SessionStore();
|
|
||||||
}
|
|
||||||
export default singletonSessionStore;
|
|
|
@ -1,47 +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 { _t } from "../languageHandler";
|
|
||||||
import Modal from "../Modal";
|
|
||||||
import SetPasswordDialog from "../components/views/dialogs/SetPasswordDialog";
|
|
||||||
import GenericToast from "../components/views/toasts/GenericToast";
|
|
||||||
import ToastStore from "../stores/ToastStore";
|
|
||||||
|
|
||||||
const onAccept = () => {
|
|
||||||
Modal.createTrackedDialog('Set Password Dialog', 'Password Nag Bar', SetPasswordDialog);
|
|
||||||
};
|
|
||||||
|
|
||||||
const TOAST_KEY = "setpassword";
|
|
||||||
|
|
||||||
export const showToast = () => {
|
|
||||||
ToastStore.sharedInstance().addOrReplaceToast({
|
|
||||||
key: TOAST_KEY,
|
|
||||||
title: _t("Set password"),
|
|
||||||
props: {
|
|
||||||
description: _t("To return to your account in future you need to set a password"),
|
|
||||||
acceptLabel: _t("Set Password"),
|
|
||||||
onAccept,
|
|
||||||
rejectLabel: _t("Later"),
|
|
||||||
onReject: hideToast, // it'll return on reload
|
|
||||||
},
|
|
||||||
component: GenericToast,
|
|
||||||
priority: 60,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const hideToast = () => {
|
|
||||||
ToastStore.sharedInstance().dismissToast(TOAST_KEY);
|
|
||||||
};
|
|
Loading…
Add table
Add a link
Reference in a new issue