Add ability to add totp codes by scanning a QR code. Closes #30.
This commit is contained in:
parent
4927707450
commit
64e3e9911b
|
@ -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<void> {
|
||||
await this.router.changePage("TOTP_VIEW");
|
||||
|
||||
uriInputRef = createRef<HTMLInputElement>();
|
||||
|
||||
async onSubmit(data: FormData): Promise<void> {
|
||||
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<void> {
|
||||
render(
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Form onSubmit={(data) => this.onSubmit(data)}>
|
||||
<Margin>
|
||||
<input
|
||||
|
@ -36,49 +59,74 @@ export class TOTPNewPage extends Page {
|
|||
required
|
||||
/>
|
||||
</Margin>
|
||||
<p>{i18next.t("totp_new_info")}</p>
|
||||
<Margin>
|
||||
<input
|
||||
class="uk-input uk-form-width-medium"
|
||||
name="uri"
|
||||
type="text"
|
||||
placeholder={i18next.t("totp_new_uri_input")}
|
||||
/>
|
||||
</Margin>
|
||||
|
||||
<p hidden={this.state.qrMode}>{i18next.t("totp_new_info")}</p>
|
||||
|
||||
<Margin>
|
||||
<input
|
||||
class="uk-input uk-form-width-medium"
|
||||
name="key"
|
||||
type="text"
|
||||
hidden={this.state.qrMode}
|
||||
placeholder={i18next.t("totp_new_key_input")}
|
||||
/>
|
||||
</Margin>
|
||||
|
||||
<Margin>
|
||||
<input
|
||||
class="uk-input uk-form-width-medium"
|
||||
ref={this.uriInputRef}
|
||||
name="uri"
|
||||
type="text"
|
||||
hidden={this.state.qrMode}
|
||||
placeholder={i18next.t("totp_new_uri_input")}
|
||||
/>
|
||||
</Margin>
|
||||
|
||||
{this.state.qrMode && (
|
||||
<QRScanner
|
||||
onScan={(uri) => {
|
||||
this.uriInputRef.current.value = uri;
|
||||
this.setState({ qrMode: !this.state.qrMode });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<MarginInline>
|
||||
<button
|
||||
class="uk-button uk-button-primary"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
this.setState({ qrMode: !this.state.qrMode });
|
||||
}}
|
||||
>
|
||||
{!this.state.qrMode
|
||||
? i18next.t("totp_new_switch_to_qr_btn")
|
||||
: i18next.t("totp_new_switch_back_to_manual_input_btn")}
|
||||
</button>
|
||||
</MarginInline>
|
||||
|
||||
<p id="errorText" class="uk-text-danger" />
|
||||
|
||||
<MarginInline>
|
||||
<button class="uk-button uk-button-primary" type="submit">
|
||||
{i18next.t("totp_new_add_btn")}
|
||||
</button>
|
||||
</MarginInline>
|
||||
</Form>,
|
||||
this.router.pageContentElement,
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async onSubmit(data: FormData): Promise<void> {
|
||||
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<void> {
|
||||
await this.router.changePage("TOTP_VIEW");
|
||||
}
|
||||
async render(): Promise<void> {
|
||||
render(<TOTPNewForm page={this} />, this.router.pageContentElement);
|
||||
}
|
||||
|
||||
async renderPageTitle(): Promise<void> {
|
||||
|
|
2
src/translations/en.js
vendored
2
src/translations/en.js
vendored
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue