From 64e3e9911b3db8525bd3792a5b169e5cec12e737 Mon Sep 17 00:00:00 2001 From: Kitteh Date: Tue, 25 May 2021 12:36:10 +0100 Subject: [PATCH] Add ability to add totp codes by scanning a QR code. Closes #30. --- src/pages/Secrets/TOTP/TOTPNew.tsx | 112 ++++++++++++++++++++--------- src/translations/en.js | 2 + 2 files changed, 82 insertions(+), 32 deletions(-) diff --git a/src/pages/Secrets/TOTP/TOTPNew.tsx b/src/pages/Secrets/TOTP/TOTPNew.tsx index 4c567d6..ba4e407 100644 --- a/src/pages/Secrets/TOTP/TOTPNew.tsx +++ b/src/pages/Secrets/TOTP/TOTPNew.tsx @@ -1,31 +1,54 @@ +import { Component, JSX, createRef, render } from "preact"; import { Form } from "../../../elements/Form"; import { Margin } from "../../../elements/Margin"; import { MarginInline } from "../../../elements/MarginInline"; import { Page } from "../../../types/Page"; +import { QRScanner } from "../../../elements/QRScanner"; import { SecretTitleElement } from "../SecretTitleElement"; import { addNewTOTP } from "../../../api/totp/addNewTOTP"; -import { render } from "preact"; import { setErrorText } from "../../../pageUtils"; import i18next from "i18next"; function replaceAll(str: string, replace: string, replaceWith: string): string { return str.replace(new RegExp(replace, "g"), replaceWith); } + function removeDashSpaces(str: string): string { str = replaceAll(str, "-", ""); str = replaceAll(str, " ", ""); return str; } -export class TOTPNewPage extends Page { +export class TOTPNewForm extends Component<{ page: Page }, { qrMode: boolean }> { constructor() { super(); + this.state = { + qrMode: false, + }; } - async goBack(): Promise { - await this.router.changePage("TOTP_VIEW"); + + uriInputRef = createRef(); + + async onSubmit(data: FormData): Promise { + const page = this.props.page; + const parms = { + url: data.get("uri") as string, + key: removeDashSpaces(data.get("key") as string).toUpperCase(), + name: data.get("name") as string, + generate: false, + }; + + try { + await addNewTOTP(page.state.baseMount, parms); + await page.router.changePage("TOTP_VIEW"); + } catch (e: unknown) { + const error = e as Error; + setErrorText(`API Error: ${error.message}`); + } } - async render(): Promise { - render( + + render(): JSX.Element { + return (
this.onSubmit(data)}> -

{i18next.t("totp_new_info")}

- - - + + + + + + + + + {this.state.qrMode && ( + { + this.uriInputRef.current.value = uri; + this.setState({ qrMode: !this.state.qrMode }); + }} + /> + )} + + + + +

+ -

, - this.router.pageContentElement, + ); } +} - async onSubmit(data: FormData): Promise { - const parms = { - url: data.get("uri") as string, - key: removeDashSpaces(data.get("key") as string).toUpperCase(), - name: data.get("name") as string, - generate: false, - }; - - try { - await addNewTOTP(this.state.baseMount, parms); - await this.router.changePage("TOTP_VIEW"); - } catch (e: unknown) { - const error = e as Error; - setErrorText(`API Error: ${error.message}`); - } +export class TOTPNewPage extends Page { + constructor() { + super(); + } + async goBack(): Promise { + await this.router.changePage("TOTP_VIEW"); + } + async render(): Promise { + render(, this.router.pageContentElement); } async renderPageTitle(): Promise { diff --git a/src/translations/en.js b/src/translations/en.js index f42c34b..deee621 100644 --- a/src/translations/en.js +++ b/src/translations/en.js @@ -163,6 +163,8 @@ module.exports = { totp_new_uri_input: "URI", totp_new_key_input: "Key", totp_new_add_btn: "Add TOTP Key", + totp_new_switch_to_qr_btn: "Switch to QR Input", + totp_new_switch_back_to_manual_input_btn: "Switch back to manual input", // TOTP Delete Page totp_delete_title: "Delete TOTP Key",