diff --git a/res/css/views/settings/tabs/_GeneralSettingsTab.scss b/res/css/views/settings/tabs/_GeneralSettingsTab.scss
index caacd0d3c7..097d81dab4 100644
--- a/res/css/views/settings/tabs/_GeneralSettingsTab.scss
+++ b/res/css/views/settings/tabs/_GeneralSettingsTab.scss
@@ -88,4 +88,22 @@
.mx_GeneralSettingsTab_profileAvatarUpload {
display: none;
+}
+
+.mx_GeneralSettingsTab_changePassword {
+ display: block;
+}
+
+.mx_GeneralSettingsTab_changePassword .mx_Field {
+ display: block;
+ margin-right: 100px; // Align with the other fields on the page
+}
+
+.mx_GeneralSettingsTab_changePassword .mx_Field input {
+ display: block;
+ width: calc(100% - 20px); // subtract 10px padding on left and right
+}
+
+.mx_GeneralSettingsTab_changePassword .mx_Field:first-child {
+ margin-top: 0;
}
\ No newline at end of file
diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js
index 65e1897137..f8d9e2dd84 100644
--- a/src/components/structures/UserSettings.js
+++ b/src/components/structures/UserSettings.js
@@ -1268,9 +1268,7 @@ module.exports = React.createClass({
);
diff --git a/src/components/views/dialogs/SetPasswordDialog.js b/src/components/views/dialogs/SetPasswordDialog.js
index 42c35ad187..fe3a2216f4 100644
--- a/src/components/views/dialogs/SetPasswordDialog.js
+++ b/src/components/views/dialogs/SetPasswordDialog.js
@@ -116,9 +116,8 @@ export default React.createClass({
element: PropTypes.string,
// All other props pass through to the .
+ };
+
+ get value() {
+ if (!this.refs.fieldInput) return null;
+ return this.refs.fieldInput.value;
}
render() {
diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js
index 77c7810436..50319850b5 100644
--- a/src/components/views/settings/ChangePassword.js
+++ b/src/components/views/settings/ChangePassword.js
@@ -15,6 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+import Field from "../elements/Field";
+
const React = require('react');
import PropTypes from 'prop-types';
const MatrixClientPeg = require("../../../MatrixClientPeg");
@@ -35,9 +37,8 @@ module.exports = React.createClass({
onError: PropTypes.func,
onCheckPassword: PropTypes.func,
rowClassName: PropTypes.string,
- rowLabelClassName: PropTypes.string,
- rowInputClassName: PropTypes.string,
buttonClassName: PropTypes.string,
+ buttonKind: PropTypes.string,
confirm: PropTypes.bool,
// Whether to autoFocus the new password input
autoFocusNewPasswordInput: PropTypes.bool,
@@ -203,21 +204,18 @@ module.exports = React.createClass({
},
render: function() {
+ // TODO: Live validation on `new pw == confirm pw`
+
const rowClassName = this.props.rowClassName;
- const rowLabelClassName = this.props.rowLabelClassName;
- const rowInputClassName = this.props.rowInputClassName;
const buttonClassName = this.props.buttonClassName;
let currentPassword = null;
if (!this.state.cachedPassword) {
- currentPassword =
-
-
+ currentPassword = (
+
+
-
-
-
-
;
+ );
}
switch (this.state.phase) {
@@ -228,24 +226,13 @@ module.exports = React.createClass({
diff --git a/src/components/views/settings/tabs/GeneralSettingsTab.js b/src/components/views/settings/tabs/GeneralSettingsTab.js
index f57609625f..aa99973130 100644
--- a/src/components/views/settings/tabs/GeneralSettingsTab.js
+++ b/src/components/views/settings/tabs/GeneralSettingsTab.js
@@ -24,6 +24,8 @@ import GroupUserSettings from "../../groups/GroupUserSettings";
import PropTypes from "prop-types";
import {MatrixClient} from "matrix-js-sdk";
import { DragDropContext } from 'react-beautiful-dnd';
+const sdk = require('../../../../index');
+const Modal = require("../../../../Modal");
export default class GeneralSettingsTab extends React.Component {
static childContextTypes = {
@@ -90,6 +92,13 @@ export default class GeneralSettingsTab extends React.Component {
this.setState(newState);
};
+ _changePassword = async (e) => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ console.log(this.refs.currentPassword);
+ };
+
_onDisplayNameChanged = (e) => {
this.setState({
displayName: e.target.value,
@@ -119,6 +128,34 @@ export default class GeneralSettingsTab extends React.Component {
reader.readAsDataURL(file);
};
+ _onPasswordChangeError = (err) => {
+ // TODO: Figure out a design that doesn't involve replacing the current dialog
+ let errMsg = err.error || "";
+ if (err.httpStatus === 403) {
+ errMsg = _t("Failed to change password. Is your password correct?");
+ } else if (err.httpStatus) {
+ errMsg += ` (HTTP status ${err.httpStatus})`;
+ }
+ const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ console.error("Failed to change password: " + errMsg);
+ Modal.createTrackedDialog('Failed to change password', '', ErrorDialog, {
+ title: _t("Error"),
+ description: errMsg,
+ });
+ };
+
+ _onPasswordChanged = () => {
+ // TODO: Figure out a design that doesn't involve replacing the current dialog
+ const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createTrackedDialog('Password changed', '', ErrorDialog, {
+ title: _t("Success"),
+ description: _t(
+ "Your password was successfully changed. You will not receive " +
+ "push notifications on other devices until you log back in to them",
+ ) + ".",
+ });
+ };
+
_renderProfileSection() {
// TODO: Why is rendering a box with an overlay so complicated? Can the DOM be reduced?
@@ -181,10 +218,23 @@ export default class GeneralSettingsTab extends React.Component {
}
_renderAccountSection() {
+ const ChangePassword = sdk.getComponent("views.settings.ChangePassword");
+ const passwordChangeForm = (
+
+ );
+
return (
{_t("Account")}
-
ACCOUNT SECTION
+
+ {_t("Set a new account password...")}
+
+ {passwordChangeForm}
);
}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 42046cba19..8e26c099da 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -402,6 +402,9 @@
"Off": "Off",
"On": "On",
"Noisy": "Noisy",
+ "Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
+ "Success": "Success",
+ "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them",
"Profile picture": "Profile picture",
"Upload profile picture": "Upload profile picture",
"Display Name": "Display Name",
@@ -409,6 +412,7 @@
"Profile": "Profile",
"Flair": "Flair",
"Account": "Account",
+ "Set a new account password...": "Set a new account password...",
"Language and region": "Language and region",
"Theme": "Theme",
"Account management": "Account management",
@@ -1000,7 +1004,6 @@
"You have successfully set a password and an email address!": "You have successfully set a password and an email address!",
"You can now return to your account after signing out, and sign in on other devices.": "You can now return to your account after signing out, and sign in on other devices.",
"Remember, you can always set an email address in user settings if you change your mind.": "Remember, you can always set an email address in user settings if you change your mind.",
- "Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
"(HTTP status %(httpStatus)s)": "(HTTP status %(httpStatus)s)",
"Please set a password!": "Please set a password!",
"This will allow you to return to your account after signing out, and sign in on other devices.": "This will allow you to return to your account after signing out, and sign in on other devices.",
@@ -1248,8 +1251,6 @@
"Status.im theme": "Status.im theme",
"Can't load user settings": "Can't load user settings",
"Server may be unavailable or overloaded": "Server may be unavailable or overloaded",
- "Success": "Success",
- "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them",
"Remove Contact Information?": "Remove Contact Information?",
"Remove %(threePid)s?": "Remove %(threePid)s?",
"Unable to remove contact information": "Unable to remove contact information",