Newer
Older
CrypticOreWallet / src / pages / backup / ImportBackupModal.tsx
@Drew Lemmy Drew Lemmy on 5 Mar 2021 3 KB refactor: import aliases
// Copyright (c) 2020-2021 Drew Lemmy
// This file is part of KristWeb 2 under GPL-3.0.
// Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt
import React, { useState, Dispatch, SetStateAction} from "react";
import { Modal, Form, Input, Button, Typography } from "antd";

import { useTranslation, Trans } from "react-i18next";
import { translateError } from "@utils/i18n";

import { FakeUsernameInput } from "@comp/auth/FakeUsernameInput";
import { getMasterPasswordInput } from "@comp/auth/MasterPasswordInput";

import { ImportDetectFormat } from "./ImportDetectFormat";
import { detectBackupFormat } from "../backup/backupParser";

import Debug from "debug";
const debug = Debug("kristweb:import-backup-modal");

const { Text, Paragraph } = Typography;
const { TextArea } = Input;

interface FormValues {
  masterPassword: string;
  code: string;
}

interface Props {
  visible: boolean;
  setVisible: Dispatch<SetStateAction<boolean>>;
}

export function ImportBackupModal({ visible, setVisible }: Props): JSX.Element {
  const { t } = useTranslation();

  const [form] = Form.useForm<FormValues>();
  const [code, setCode] = useState("");
  const [decodeError, setDecodeError] = useState<string | undefined>();

  function closeModal() {
    debug("closing modal and resetting fields");
    form.resetFields();
    setCode("");
    setVisible(false);
  }

  function onValuesChange(changed: Partial<FormValues>) {
    if (changed.code) setCode(changed.code);
  }

  // Detect the backup format for the final time, validate the password, and
  // if all is well, begin the import
  async function onFinish() {
    const values = await form.validateFields();
    if (!values.masterPassword || !values.code) return;

    try {
      // Decode first
      const format = detectBackupFormat(code);
      debug("detected format: %s", format.type);

      setDecodeError(undefined);
    } catch (err) {
      console.error(err);
      setDecodeError(translateError(t, err, "import.decodeErrors.unknown"));
    }
  }

  return <Modal
    title={t("import.modalTitle")}
    okText={t("import.modalButton")}
    cancelText={t("dialog.cancel")}

    visible={visible}
    destroyOnClose

    onCancel={closeModal}
    onOk={onFinish}
  >
    <Form
      form={form}
      layout="vertical"

      name={"importBackupForm"}

      initialValues={{
        masterPassword: "",
        code: ""
      }}

      onValuesChange={onValuesChange}
      onFinish={onFinish}
    >
      {/* Import lead */}
      <Paragraph>{t("import.description")}</Paragraph>

      {/* Detected format information */}
      <ImportDetectFormat
        code={code}
        setDecodeError={setDecodeError}
      />

      {/* Password input */}
      <Form.Item
        name="masterPassword"
        rules={[
          { required: true, message: t("import.masterPasswordRequired") },
          { min: 0, message: t("import.masterPasswordRequired") },
        ]}
        style={{ marginBottom: 8 }}
      >
        {getMasterPasswordInput({
          placeholder: t("import.masterPasswordPlaceholder"),
          autoFocus: true
        })}
      </Form.Item>


      {/* Code textarea */}
      <Form.Item
        name="code"
        rules={[
          { required: true, message: t("import.textareaRequired") },
          { min: 0, message: t("import.textareaRequired") },
        ]}

        // Show the decode error here, if present
        validateStatus={decodeError ? "error" : undefined}
        help={decodeError}
      >
        <TextArea
          rows={4}
          autoSize={{ minRows: 4, maxRows: 4 }}
          placeholder={t("import.textareaPlaceholder")}
        />
      </Form.Item>
    </Form>
  </Modal>;
}