Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into kegan/hide-join-part
This commit is contained in:
commit
a097357baf
36 changed files with 1741 additions and 307 deletions
|
@ -186,7 +186,7 @@ module.exports = React.createClass({
|
|||
componentWillMount: function() {
|
||||
SdkConfig.put(this.props.config);
|
||||
|
||||
RoomViewStore.addListener(this._onRoomViewStoreUpdated);
|
||||
this._roomViewStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdated);
|
||||
this._onRoomViewStoreUpdated();
|
||||
|
||||
if (!UserSettingsStore.getLocalSetting('analyticsOptOut', false)) Analytics.enable();
|
||||
|
@ -263,10 +263,22 @@ module.exports = React.createClass({
|
|||
window.addEventListener('resize', this.handleResize);
|
||||
this.handleResize();
|
||||
|
||||
if (this.props.config.teamServerConfig &&
|
||||
this.props.config.teamServerConfig.teamServerURL
|
||||
) {
|
||||
Lifecycle.initRtsClient(this.props.config.teamServerConfig.teamServerURL);
|
||||
const teamServerConfig = this.props.config.teamServerConfig || {};
|
||||
Lifecycle.initRtsClient(teamServerConfig.teamServerURL);
|
||||
|
||||
// if the user has followed a login or register link, don't reanimate
|
||||
// the old creds, but rather go straight to the relevant page
|
||||
|
||||
const firstScreen = this.state.screenAfterLogin ?
|
||||
this.state.screenAfterLogin.screen : null;
|
||||
|
||||
if (firstScreen === 'login' ||
|
||||
firstScreen === 'register' ||
|
||||
firstScreen === 'forgot_password') {
|
||||
this.props.onLoadCompleted();
|
||||
this.setState({loading: false});
|
||||
this._showScreenAfterLogin();
|
||||
return;
|
||||
}
|
||||
|
||||
// the extra q() ensures that synchronous exceptions hit the same codepath as
|
||||
|
@ -295,6 +307,7 @@ module.exports = React.createClass({
|
|||
UDEHandler.stopListening();
|
||||
window.removeEventListener("focus", this.onFocus);
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
this._roomViewStoreToken.remove();
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
|
@ -839,14 +852,6 @@ module.exports = React.createClass({
|
|||
_onLoadCompleted: function() {
|
||||
this.props.onLoadCompleted();
|
||||
this.setState({loading: false});
|
||||
|
||||
// Show screens (like 'register') that need to be shown without _onLoggedIn
|
||||
// being called. 'register' needs to be routed here when the email confirmation
|
||||
// link is clicked on.
|
||||
if (this.state.screenAfterLogin &&
|
||||
['register'].indexOf(this.state.screenAfterLogin.screen) !== -1) {
|
||||
this._showScreenAfterLogin();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -945,6 +950,7 @@ module.exports = React.createClass({
|
|||
this.state.screenAfterLogin.screen,
|
||||
this.state.screenAfterLogin.params,
|
||||
);
|
||||
// XXX: is this necessary? `showScreen` should do it for us.
|
||||
this.notifyNewScreen(this.state.screenAfterLogin.screen);
|
||||
this.setState({screenAfterLogin: null});
|
||||
} else if (localStorage && localStorage.getItem('mx_last_room_id')) {
|
||||
|
@ -1228,6 +1234,8 @@ module.exports = React.createClass({
|
|||
onReturnToGuestClick: function() {
|
||||
// reanimate our guest login
|
||||
if (this.state.guestCreds) {
|
||||
// TODO: this is probably a bit broken - we don't want to be
|
||||
// clearing storage when we reanimate the guest creds.
|
||||
Lifecycle.setLoggedIn(this.state.guestCreds);
|
||||
this.setState({guestCreds: null});
|
||||
}
|
||||
|
|
|
@ -170,6 +170,25 @@ module.exports = React.createClass({
|
|||
isInitialEventHighlighted: RoomViewStore.isInitialEventHighlighted(),
|
||||
};
|
||||
|
||||
// Temporary logging to diagnose https://github.com/vector-im/riot-web/issues/4307
|
||||
console.log(
|
||||
'RVS update:',
|
||||
newState.roomId,
|
||||
newState.roomAlias,
|
||||
'loading?', newState.roomLoading,
|
||||
'joining?', newState.joining,
|
||||
);
|
||||
|
||||
// finished joining, start waiting for a room and show a spinner. See onRoom.
|
||||
newState.waitingForRoom = this.state.joining && !newState.joining &&
|
||||
!RoomViewStore.getJoinError();
|
||||
|
||||
// NB: This does assume that the roomID will not change for the lifetime of
|
||||
// the RoomView instance
|
||||
if (initial) {
|
||||
newState.room = MatrixClientPeg.get().getRoom(newState.roomId);
|
||||
}
|
||||
|
||||
// Clear the search results when clicking a search result (which changes the
|
||||
// currently scrolled to event, this.state.initialEventId).
|
||||
if (this.state.initialEventId !== newState.initialEventId) {
|
||||
|
@ -185,8 +204,9 @@ module.exports = React.createClass({
|
|||
this.setState(newState, () => {
|
||||
// At this point, this.state.roomId could be null (e.g. the alias might not
|
||||
// have been resolved yet) so anything called here must handle this case.
|
||||
this._onHaveRoom();
|
||||
this.onRoom(MatrixClientPeg.get().getRoom(this.state.roomId));
|
||||
if (initial) {
|
||||
this._onHaveRoom();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -202,25 +222,20 @@ module.exports = React.createClass({
|
|||
// which must be by alias or invite wherever possible (peeking currently does
|
||||
// not work over federation).
|
||||
|
||||
// NB. We peek if we are not in the room, although if we try to peek into
|
||||
// a room in which we have a member event (ie. we've left) synapse will just
|
||||
// send us the same data as we get in the sync (ie. the last events we saw).
|
||||
const room = MatrixClientPeg.get().getRoom(this.state.roomId);
|
||||
let isUserJoined = null;
|
||||
// NB. We peek if we have never seen the room before (i.e. js-sdk does not know
|
||||
// about it). We don't peek in the historical case where we were joined but are
|
||||
// now not joined because the js-sdk peeking API will clobber our historical room,
|
||||
// making it impossible to indicate a newly joined room.
|
||||
const room = this.state.room;
|
||||
if (room) {
|
||||
isUserJoined = room.hasMembershipState(
|
||||
MatrixClientPeg.get().credentials.userId, 'join',
|
||||
);
|
||||
|
||||
this._updateAutoComplete(room);
|
||||
this.tabComplete.loadEntries(room);
|
||||
}
|
||||
if (!isUserJoined && !this.state.joining && this.state.roomId) {
|
||||
if (!this.state.joining && this.state.roomId) {
|
||||
if (this.props.autoJoin) {
|
||||
this.onJoinButtonClicked();
|
||||
} else if (this.state.roomId) {
|
||||
} else if (!room) {
|
||||
console.log("Attempting to peek into room %s", this.state.roomId);
|
||||
|
||||
this.setState({
|
||||
peekLoading: true,
|
||||
});
|
||||
|
@ -244,7 +259,8 @@ module.exports = React.createClass({
|
|||
}
|
||||
}).done();
|
||||
}
|
||||
} else if (isUserJoined) {
|
||||
} else if (room) {
|
||||
// Stop peeking because we have joined this room previously
|
||||
MatrixClientPeg.get().stopPeeking();
|
||||
this.setState({
|
||||
unsentMessageError: this._getUnsentMessageError(room),
|
||||
|
@ -607,6 +623,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
this.setState({
|
||||
room: room,
|
||||
waitingForRoom: false,
|
||||
}, () => {
|
||||
this._onRoomLoaded(room);
|
||||
});
|
||||
|
@ -662,7 +679,14 @@ module.exports = React.createClass({
|
|||
|
||||
onRoomMemberMembership: function(ev, member, oldMembership) {
|
||||
if (member.userId == MatrixClientPeg.get().credentials.userId) {
|
||||
this.forceUpdate();
|
||||
|
||||
if (member.membership === 'join') {
|
||||
this.setState({
|
||||
waitingForRoom: false,
|
||||
});
|
||||
} else {
|
||||
this.forceUpdate();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1416,6 +1440,10 @@ module.exports = React.createClass({
|
|||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
|
||||
|
||||
// Whether the preview bar spinner should be shown. We do this when joining or
|
||||
// when waiting for a room to be returned by js-sdk when joining
|
||||
const previewBarSpinner = this.state.joining || this.state.waitingForRoom;
|
||||
|
||||
if (!this.state.room) {
|
||||
if (this.state.roomLoading || this.state.peekLoading) {
|
||||
return (
|
||||
|
@ -1449,7 +1477,7 @@ module.exports = React.createClass({
|
|||
onRejectClick={ this.onRejectThreepidInviteButtonClicked }
|
||||
canPreview={ false } error={ this.state.roomLoadError }
|
||||
roomAlias={room_alias}
|
||||
spinner={this.state.joining}
|
||||
spinner={previewBarSpinner}
|
||||
inviterName={inviterName}
|
||||
invitedEmail={invitedEmail}
|
||||
room={this.state.room}
|
||||
|
@ -1492,7 +1520,7 @@ module.exports = React.createClass({
|
|||
onRejectClick={ this.onRejectButtonClicked }
|
||||
inviterName={ inviterName }
|
||||
canPreview={ false }
|
||||
spinner={this.state.joining}
|
||||
spinner={previewBarSpinner}
|
||||
room={this.state.room}
|
||||
/>
|
||||
</div>
|
||||
|
@ -1568,7 +1596,7 @@ module.exports = React.createClass({
|
|||
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
|
||||
onForgetClick={ this.onForgetClick }
|
||||
onRejectClick={this.onRejectThreepidInviteButtonClicked}
|
||||
spinner={this.state.joining}
|
||||
spinner={previewBarSpinner}
|
||||
inviterName={inviterName}
|
||||
invitedEmail={invitedEmail}
|
||||
canPreview={this.state.canPeek}
|
||||
|
|
|
@ -352,13 +352,14 @@ module.exports = React.createClass({
|
|||
const tile = tiles[backwards ? i : tiles.length - 1 - i];
|
||||
// Subtract height of tile as if it were unpaginated
|
||||
excessHeight -= tile.clientHeight;
|
||||
//If removing the tile would lead to future pagination, break before setting scroll token
|
||||
if (tile.clientHeight > excessHeight) {
|
||||
break;
|
||||
}
|
||||
// The tile may not have a scroll token, so guard it
|
||||
if (tile.dataset.scrollTokens) {
|
||||
markerScrollToken = tile.dataset.scrollTokens.split(',')[0];
|
||||
}
|
||||
if (tile.clientHeight > excessHeight) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (markerScrollToken) {
|
||||
|
|
|
@ -114,6 +114,13 @@ const ANALYTICS_SETTINGS_LABELS = [
|
|||
},
|
||||
];
|
||||
|
||||
const WEBRTC_SETTINGS_LABELS = [
|
||||
{
|
||||
id: 'webRtcForceTURN',
|
||||
label: 'Disable Peer-to-Peer for 1:1 calls',
|
||||
},
|
||||
];
|
||||
|
||||
// Warning: Each "label" string below must be added to i18n/strings/en_EN.json,
|
||||
// since they will be translated when rendered.
|
||||
const CRYPTO_SETTINGS_LABELS = [
|
||||
|
@ -949,16 +956,13 @@ module.exports = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
_renderWebRtcSettings: function() {
|
||||
_renderWebRtcDeviceSettings: function() {
|
||||
if (this.state.mediaDevices === false) {
|
||||
return <div>
|
||||
<h3>{_t('VoIP')}</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
<p className="mx_UserSettings_link" onClick={this._requestMediaPermissions}>
|
||||
{_t('Missing Media Permissions, click here to request.')}
|
||||
</p>
|
||||
</div>
|
||||
</div>;
|
||||
return (
|
||||
<p className="mx_UserSettings_link" onClick={this._requestMediaPermissions}>
|
||||
{_t('Missing Media Permissions, click here to request.')}
|
||||
</p>
|
||||
);
|
||||
} else if (!this.state.mediaDevices) return;
|
||||
|
||||
const Dropdown = sdk.getComponent('elements.Dropdown');
|
||||
|
@ -1012,10 +1016,17 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
return <div>
|
||||
<h3>{_t('VoIP')}</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
{microphoneDropdown}
|
||||
{webcamDropdown}
|
||||
</div>;
|
||||
},
|
||||
|
||||
_renderWebRtcSettings: function() {
|
||||
return <div>
|
||||
<h3>{_t('VoIP')}</h3>
|
||||
<div className="mx_UserSettings_section">
|
||||
{ WEBRTC_SETTINGS_LABELS.map(this._renderLocalSetting) }
|
||||
{ this._renderWebRtcDeviceSettings() }
|
||||
</div>
|
||||
</div>;
|
||||
},
|
||||
|
|
|
@ -24,6 +24,7 @@ import DMRoomMap from '../../../utils/DMRoomMap';
|
|||
import Modal from '../../../Modal';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import q from 'q';
|
||||
import dis from '../../../dispatcher';
|
||||
|
||||
const TRUNCATE_QUERY_LIST = 40;
|
||||
const QUERY_USER_DIRECTORY_DEBOUNCE_MS = 200;
|
||||
|
@ -102,7 +103,7 @@ module.exports = React.createClass({
|
|||
const ChatCreateOrReuseDialog = sdk.getComponent(
|
||||
"views.dialogs.ChatCreateOrReuseDialog",
|
||||
);
|
||||
Modal.createDialog(ChatCreateOrReuseDialog, {
|
||||
const close = Modal.createDialog(ChatCreateOrReuseDialog, {
|
||||
userId: userId,
|
||||
onFinished: (success) => {
|
||||
this.props.onFinished(success);
|
||||
|
@ -112,14 +113,16 @@ module.exports = React.createClass({
|
|||
action: 'start_chat',
|
||||
user_id: userId,
|
||||
});
|
||||
close(true);
|
||||
},
|
||||
onExistingRoomSelected: (roomId) => {
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
user_id: roomId,
|
||||
room_id: roomId,
|
||||
});
|
||||
close(true);
|
||||
},
|
||||
});
|
||||
}).close;
|
||||
} else {
|
||||
this._startChat(inviteList);
|
||||
}
|
||||
|
@ -238,6 +241,11 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().searchUserDirectory({
|
||||
term: query,
|
||||
}).then((resp) => {
|
||||
// The query might have changed since we sent the request, so ignore
|
||||
// responses for anything other than the latest query.
|
||||
if (this.state.query !== query) {
|
||||
return;
|
||||
}
|
||||
this._processResults(resp.results, query);
|
||||
}).catch((err) => {
|
||||
console.error('Error whilst searching user directory: ', err);
|
||||
|
|
164
src/components/views/dialogs/SetEmailDialog.js
Normal file
164
src/components/views/dialogs/SetEmailDialog.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
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 from 'react';
|
||||
import sdk from '../../../index';
|
||||
import Email from '../../../email';
|
||||
import AddThreepid from '../../../AddThreepid';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import Modal from '../../../Modal';
|
||||
|
||||
|
||||
/**
|
||||
* Prompt the user to set an email address.
|
||||
*
|
||||
* On success, `onFinished(true)` is called.
|
||||
*/
|
||||
export default React.createClass({
|
||||
displayName: 'SetEmailDialog',
|
||||
propTypes: {
|
||||
onFinished: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
emailAddress: null,
|
||||
emailBusy: false,
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
},
|
||||
|
||||
onEmailAddressChanged: function(value) {
|
||||
this.setState({
|
||||
emailAddress: value,
|
||||
});
|
||||
},
|
||||
|
||||
onSubmit: function() {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
|
||||
const emailAddress = this.state.emailAddress;
|
||||
if (!Email.looksValid(emailAddress)) {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Invalid Email Address"),
|
||||
description: _t("This doesn't appear to be a valid email address"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
this._addThreepid = new AddThreepid();
|
||||
// we always bind emails when registering, so let's do the
|
||||
// same here.
|
||||
this._addThreepid.addEmailAddress(emailAddress, true).done(() => {
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Verification Pending"),
|
||||
description: _t(
|
||||
"Please check your email and click on the link it contains. Once this " +
|
||||
"is done, click continue.",
|
||||
),
|
||||
button: _t('Continue'),
|
||||
onFinished: this.onEmailDialogFinished,
|
||||
});
|
||||
}, (err) => {
|
||||
this.setState({emailBusy: false});
|
||||
console.error("Unable to add email address " + emailAddress + " " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to add email address"),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
});
|
||||
this.setState({emailBusy: true});
|
||||
},
|
||||
|
||||
onCancelled: function() {
|
||||
this.props.onFinished(false);
|
||||
},
|
||||
|
||||
onEmailDialogFinished: function(ok) {
|
||||
if (ok) {
|
||||
this.verifyEmailAddress();
|
||||
} else {
|
||||
this.setState({emailBusy: false});
|
||||
}
|
||||
},
|
||||
|
||||
verifyEmailAddress: function() {
|
||||
this._addThreepid.checkEmailLinkClicked().done(() => {
|
||||
this.props.onFinished(true);
|
||||
}, (err) => {
|
||||
this.setState({emailBusy: false});
|
||||
if (err.errcode == 'M_THREEPID_AUTH_FAILED') {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const message = _t("Unable to verify email address.") + " " +
|
||||
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
|
||||
Modal.createDialog(QuestionDialog, {
|
||||
title: _t("Verification Pending"),
|
||||
description: message,
|
||||
button: _t('Continue'),
|
||||
onFinished: this.onEmailDialogFinished,
|
||||
});
|
||||
} else {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Unable to verify email address: " + err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Unable to verify email address."),
|
||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const Spinner = sdk.getComponent('elements.Spinner');
|
||||
const EditableText = sdk.getComponent('elements.EditableText');
|
||||
|
||||
const emailInput = this.state.emailBusy ? <Spinner /> : <EditableText
|
||||
className="mx_SetEmailDialog_email_input"
|
||||
placeholder={ _t("Email address") }
|
||||
placeholderClassName="mx_SetEmailDialog_email_input_placeholder"
|
||||
blurToCancel={ false }
|
||||
onValueChanged={ this.onEmailAddressChanged } />;
|
||||
|
||||
return (
|
||||
<BaseDialog className="mx_SetEmailDialog"
|
||||
onFinished={this.onCancelled}
|
||||
title={this.props.title}
|
||||
>
|
||||
<div className="mx_Dialog_content">
|
||||
<p>
|
||||
{ _t('This will allow you to reset your password and receive notifications.') }
|
||||
</p>
|
||||
{ emailInput }
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<input className="mx_Dialog_primary"
|
||||
type="submit"
|
||||
value={_t("Continue")}
|
||||
onClick={this.onSubmit}
|
||||
/>
|
||||
<input
|
||||
type="submit"
|
||||
value={_t("Cancel")}
|
||||
onClick={this.onCancelled}
|
||||
/>
|
||||
</div>
|
||||
</BaseDialog>
|
||||
);
|
||||
},
|
||||
});
|
|
@ -62,8 +62,8 @@ module.exports = React.createClass({
|
|||
var url = ContentRepo.getHttpUriForMxc(
|
||||
MatrixClientPeg.get().getHomeserverUrl(),
|
||||
ev.getContent().url,
|
||||
14 * window.devicePixelRatio,
|
||||
14 * window.devicePixelRatio,
|
||||
Math.ceil(14 * window.devicePixelRatio),
|
||||
Math.ceil(14 * window.devicePixelRatio),
|
||||
'crop'
|
||||
);
|
||||
|
||||
|
|
|
@ -89,12 +89,13 @@ module.exports = React.createClass({
|
|||
|
||||
var conferenceCallNotification = null;
|
||||
if (this.props.displayConfCallNotification) {
|
||||
var supportedText, joinText;
|
||||
let supportedText = '';
|
||||
let joinNode;
|
||||
if (!MatrixClientPeg.get().supportsVoip()) {
|
||||
supportedText = _t(" (unsupported)");
|
||||
}
|
||||
else {
|
||||
joinText = (<span>
|
||||
joinNode = (<span>
|
||||
{_tJsx(
|
||||
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.",
|
||||
[/<voiceText>(.*?)<\/voiceText>/, /<videoText>(.*?)<\/videoText>/],
|
||||
|
@ -106,9 +107,13 @@ module.exports = React.createClass({
|
|||
</span>);
|
||||
|
||||
}
|
||||
// XXX: the translation here isn't great: appending ' (unsupported)' is likely to not make sense in many languages,
|
||||
// but there are translations for this in the languages we do have so I'm leaving it for now.
|
||||
conferenceCallNotification = (
|
||||
<div className="mx_RoomView_ongoingConfCallNotification">
|
||||
{_t("Ongoing conference call%(supportedText)s. %(joinText)s", {supportedText: supportedText, joinText: joinText})}
|
||||
{_t("Ongoing conference call%(supportedText)s.", {supportedText: supportedText})}
|
||||
|
||||
{joinNode}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -594,7 +594,7 @@ module.exports = React.createClass({
|
|||
<div>
|
||||
<label>
|
||||
{ isEncrypted
|
||||
? <img className="mx_RoomSettings_e2eIcon mx_filterFlipColor" src="img/e2e-verified.svg" width="10" height="12" />
|
||||
? <img className="mx_RoomSettings_e2eIcon" src="img/e2e-verified.svg" width="10" height="12" />
|
||||
: <img className="mx_RoomSettings_e2eIcon mx_filterFlipColor" src="img/e2e-unencrypted.svg" width="12" height="12" />
|
||||
}
|
||||
{ isEncrypted ? _t("Encryption is enabled in this room") : _t("Encryption is not enabled in this room") }.
|
||||
|
|
|
@ -20,6 +20,8 @@ var React = require('react');
|
|||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var Modal = require("../../../Modal");
|
||||
var sdk = require("../../../index");
|
||||
|
||||
import q from 'q';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
|
@ -140,7 +142,15 @@ module.exports = React.createClass({
|
|||
});
|
||||
|
||||
cli.setPassword(authDict, newPassword).then(() => {
|
||||
this.props.onFinished();
|
||||
if (this.props.shouldAskForEmail) {
|
||||
return this._optionallySetEmail().then((confirmed) => {
|
||||
this.props.onFinished({
|
||||
didSetEmail: confirmed,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.props.onFinished();
|
||||
}
|
||||
}, (err) => {
|
||||
this.props.onError(err);
|
||||
}).finally(() => {
|
||||
|
@ -150,6 +160,20 @@ module.exports = React.createClass({
|
|||
}).done();
|
||||
},
|
||||
|
||||
_optionallySetEmail: function() {
|
||||
const deferred = q.defer();
|
||||
// Ask for an email otherwise the user has no way to reset their password
|
||||
const SetEmailDialog = sdk.getComponent("dialogs.SetEmailDialog");
|
||||
Modal.createDialog(SetEmailDialog, {
|
||||
title: _t('Do you want to set an email address?'),
|
||||
onFinished: (confirmed) => {
|
||||
// ignore confirmed, setting an email is optional
|
||||
deferred.resolve(confirmed);
|
||||
},
|
||||
});
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_onExportE2eKeysClicked: function() {
|
||||
Modal.createDialogAsync(
|
||||
(cb) => {
|
||||
|
@ -199,7 +223,7 @@ module.exports = React.createClass({
|
|||
const passwordLabel = this.state.cachedPassword ?
|
||||
_t('Password') : _t('New Password');
|
||||
return (
|
||||
<div className={this.props.className}>
|
||||
<form className={this.props.className} onSubmit={this.onClickChange}>
|
||||
{ currentPassword }
|
||||
<div className={rowClassName}>
|
||||
<div className={rowLabelClassName}>
|
||||
|
@ -222,7 +246,7 @@ module.exports = React.createClass({
|
|||
element="button">
|
||||
{ _t('Change Password') }
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
case this.Phases.Uploading:
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue