diff --git a/scenes/SceneEditAccount.js b/scenes/SceneEditAccount.js
index 8bc88c2c..206be235 100644
--- a/scenes/SceneEditAccount.js
+++ b/scenes/SceneEditAccount.js
@@ -5,7 +5,7 @@ import * as Strings from "~/common/strings";
import * as Validations from "~/common/validations";
import * as Window from "~/common/window";
import * as Constants from "~/common/constants";
-import * as FileUtilities from "~/common/file-utilities";
+import * as Utilities from "~/common/utilities";
import * as UserBehaviors from "~/common/user-behaviors";
import * as Events from "~/common/custom-events";
import * as SVG from "~/common/svg";
@@ -13,11 +13,13 @@ import * as SVG from "~/common/svg";
import { css } from "@emotion/react";
import { SecondaryTabGroup } from "~/components/core/TabGroup";
import { ConfirmationModal } from "~/components/core/ConfirmationModal";
+import { useForm, useToggle } from "~/common/hooks";
import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
import Avatar from "~/components/core/Avatar";
+import Field from "~/components/core/Field";
const STYLES_FILE_HIDDEN = css`
height: 1px;
@@ -41,25 +43,89 @@ const STYLES_HEADER = css`
margin-bottom: 16px;
`;
+const SecuritySection = ({ onUpdateViewer, username }) => {
+ const [passwordValidations, setPasswordValidations] = React.useState(
+ Validations.passwordForm("")
+ );
+
+ const { getFieldProps, getFormProps, isSubmitting } = useForm({
+ initialValues: { password: "" },
+ validate: ({ password }, errors) => {
+ if (!Validations.password(password)) errors.password = "Incorrect password";
+ return errors;
+ },
+ onSubmit: async ({ password }) => {
+ const userVersionResponse = await Actions.getUserVersion({ username });
+ if (Events.hasError(userVersionResponse)) return;
+
+ let hashedPassword;
+ if (userVersionResponse?.data?.version === 2) {
+ hashedPassword = await Utilities.encryptPasswordClient(password);
+ } else {
+ hashedPassword = password;
+ }
+
+ let response = await onUpdateViewer({
+ type: "CHANGE_PASSWORD",
+ password: hashedPassword,
+ });
+
+ if (Events.hasError(response)) {
+ return;
+ }
+
+ Events.dispatchMessage({ message: "Password successfully updated!", status: "INFO" });
+ },
+ });
+
+ const [showPassword, togglePasswordVisibility] = useToggle(false);
+
+ return (
+
+
Change password
+
Passwords must be a minimum of eight characters.
+
+
+ );
+};
+
export default class SceneEditAccount extends React.Component {
state = {
username: this.props.viewer.username,
- password: "",
confirm: "",
body: this.props.viewer.data.body,
photo: this.props.viewer.data.photo,
name: this.props.viewer.data.name,
deleting: false,
- allow_filecoin_directory_listing: this.props.viewer.data.settings
- ?.allow_filecoin_directory_listing,
+ allow_filecoin_directory_listing:
+ this.props.viewer.data.settings?.allow_filecoin_directory_listing,
allow_automatic_data_storage: this.props.viewer.data.settings?.allow_automatic_data_storage,
allow_encrypted_data_storage: this.props.viewer.data.settings?.allow_encrypted_data_storage,
- changingPassword: false,
changingAvatar: false,
savingNameBio: false,
changingFilecoin: false,
modalShow: false,
- showPassword: false,
};
_handleUpload = async (e) => {
@@ -70,7 +136,7 @@ export default class SceneEditAccount extends React.Component {
return;
}
- const cid = file.cid;
+ const { cid } = file;
const url = Strings.getURLfromCID(cid);
let updateResponse = await Actions.updateViewer({
data: {
@@ -82,7 +148,7 @@ export default class SceneEditAccount extends React.Component {
this.setState({ changingAvatar: false, photo: url });
};
- _handleSaveFilecoin = async (e) => {
+ _handleSaveFilecoin = async () => {
this.setState({ changingFilecoin: true });
let response = await Actions.updateViewer({
@@ -100,7 +166,7 @@ export default class SceneEditAccount extends React.Component {
this.setState({ changingFilecoin: false });
};
- _handleSave = async (e) => {
+ _handleSave = async () => {
if (!Validations.username(this.state.username)) {
Events.dispatchMessage({
message: "Please include only letters and numbers in your username",
@@ -129,32 +195,6 @@ export default class SceneEditAccount extends React.Component {
this.setState({ [e.target.name]: e.target.value.toLowerCase() });
};
- _handleChangePassword = async (e) => {
- if (this.state.password !== this.state.confirm) {
- Events.dispatchMessage({ message: "Passwords did not match" });
- return;
- }
-
- if (!Validations.password(this.state.password)) {
- Events.dispatchMessage({ message: "Password length must be more than 8 characters" });
- return;
- }
-
- this.setState({ changingPassword: true });
-
- let response = await Actions.updateViewer({
- type: "CHANGE_PASSWORD",
- password: this.state.password,
- });
-
- if (Events.hasError(response)) {
- this.setState({ changingPassword: false });
- return;
- }
-
- this.setState({ changingPassword: false, password: "", confirm: "" });
- };
-
_handleDelete = async (res) => {
if (!res) {
this.setState({ modalShow: false });
@@ -296,31 +336,10 @@ export default class SceneEditAccount extends React.Component {
) : null}
{tab === "security" ? (
-
-
Change password
-
Passwords must be a minimum of eight characters.
-
-
this.setState({ showPassword: !this.state.showPassword })}
- icon={this.state.showPassword ? SVG.EyeOff : SVG.Eye}
- />
-
-
-
- Change password
-
-
-
+
) : null}
{tab === "account" ? (