1
0
Fork 0

Use tsx syntax in TOTPView.

This commit is contained in:
Kitteh 2021-05-22 13:06:50 +01:00
parent e4d749cce0
commit 23cc9b60c9
2 changed files with 128 additions and 119 deletions

View file

@ -1,119 +0,0 @@
import { CopyableInputBox } from "../../../elements/CopyableInputBox";
import { DoesNotExistError } from "../../../types/internalErrors";
import { Page } from "../../../types/Page";
import { SecretTitleElement } from "../SecretTitleElement";
import { getTOTPCode } from "../../../api/totp/getTOTPCode";
import { getTOTPKeys } from "../../../api/totp/getTOTPKeys";
import { makeElement } from "z-makeelement";
import { objectToMap } from "../../../utils";
import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
export interface TOTPListElement extends HTMLElement {
setCode(code: string): void;
}
export class TOTPViewPage extends Page {
constructor() {
super();
this.refresher = undefined;
this.totpListElements = {};
}
refresher: number;
totpListElements: Record<string, TOTPListElement>;
async goBack(): Promise<void> {
await this.router.changePage("SECRETS_HOME");
}
async render(): Promise<void> {
const totpList = makeElement({ tag: "div" });
await this.router.setPageContent(
makeElement({
tag: "div",
children: [
makeElement({
tag: "button",
text: i18next.t("totp_view_new_btn"),
class: ["uk-button", "uk-button-primary", "uk-margin-bottom"],
onclick: async () => {
await this.router.changePage("NEW_TOTP");
},
}),
makeElement({
tag: "p",
id: "loadingText",
text: i18next.t("totp_view_loading"),
}),
makeElement({ tag: "br" }),
makeElement({ tag: "br" }),
totpList,
],
}),
);
try {
const res = await getTOTPKeys(this.state.baseMount);
for (const totpKeyName of res) {
const totpListElement = this.makeTOTPListElement(totpKeyName);
totpList.appendChild(totpListElement);
this.totpListElements[totpKeyName] = totpListElement;
await this.updateTOTPElement(totpKeyName, totpListElement);
}
document.getElementById("loadingText").remove();
} catch (e: unknown) {
const error = e as Error;
if (error == DoesNotExistError) {
const loadingText = document.getElementById("loadingText");
loadingText.innerText = i18next.t("totp_view_empty");
} else {
setErrorText(error.message);
}
}
const totpRefresher = async () => {
await Promise.all(
Array.from(objectToMap(this.totpListElements)).map((kv: [string, TOTPListElement]) => {
return this.updateTOTPElement(...kv);
}),
);
};
await totpRefresher();
this.refresher = setInterval(async () => {
await totpRefresher();
}, 3000) as unknown as number;
}
async cleanup(): Promise<void> {
clearInterval(this.refresher);
this.totpListElements = {};
}
async updateTOTPElement(totpKeyName: string, totpListElement: TOTPListElement): Promise<void> {
totpListElement.setCode(await getTOTPCode(this.state.baseMount, totpKeyName));
}
makeTOTPListElement(totpKeyName: string): TOTPListElement {
const totpKeyBox = CopyableInputBox(totpKeyName, false);
const totpValueBox = CopyableInputBox(i18next.t("totp_view_loading_box"));
const gridElement = makeElement({
tag: "div",
class: ["uk-grid", "uk-grid-small", "uk-text-expand"],
children: [totpKeyBox, totpValueBox],
}) as TOTPListElement;
gridElement.setCode = (code: string) => totpValueBox.setText(code);
return gridElement;
}
async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router);
}
get name(): string {
return i18next.t("totp_view_title");
}
}

View file

@ -0,0 +1,128 @@
import { CopyableInputBox } from "../../../elements/ReactCopyableInputBox";
import { DoesNotExistError } from "../../../types/internalErrors";
import { Page } from "../../../types/Page";
import { SecretTitleElement } from "../SecretTitleElement";
import { getTOTPCode } from "../../../api/totp/getTOTPCode";
import { getTOTPKeys } from "../../../api/totp/getTOTPKeys";
import { makeElement } from "z-makeelement";
import { objectToMap } from "../../../utils";
import { setErrorText } from "../../../pageUtils";
import i18next from "i18next";
import { render, JSX } from "preact";
export interface TOTPListElement extends HTMLElement {
setCode(code: string): void;
}
function quickHash(str: string): string {
var hash = 0;
if (str.length == 0) {
return String(hash).toString();
}
for (var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
return String(hash).toString();
}
export function TOTPGridItem(props: { item_key: string, item_value: string }): JSX.Element {
return (
<div class="uk-grid uk-grid-small uk-text-left" uk-grid>
<CopyableInputBox text={props.item_key} copyable />
<CopyableInputBox text={props.item_value} copyable />
</div>
);
}
export class TOTPViewPage extends Page {
constructor() {
super();
this.refresher = undefined;
}
refresher: number;
async goBack(): Promise<void> {
await this.router.changePage("SECRETS_HOME");
}
async render(): Promise<void> {
console.log(quickHash("abc"));
render((
<div>
<button
class="uk-button uk-button-primary uk-margin-bottom"
onClick={async () => {
await this.router.changePage("NEW_TOTP");
}}>
{i18next.t("totp_view_new_btn")}
</button>
<p id="loadingText">{i18next.t("totp_view_loading")}</p>
<br />
<br />
<div id="totpList"></div>
</div>
), this.router.pageContentElement)
try {
await this.updateTOTPElements();
document.getElementById("loadingText").remove();
} catch (e: unknown) {
const error = e as Error;
if (error == DoesNotExistError) {
const loadingText = document.getElementById("loadingText");
loadingText.innerText = i18next.t("totp_view_empty");
} else {
setErrorText(error.message);
}
}
const totpRefresher = async () => {
await this.updateTOTPElements();
};
this.refresher = setInterval(async () => {
await totpRefresher();
}, 3000) as unknown as number;
}
async cleanup(): Promise<void> {
clearInterval(this.refresher);
}
async updateTOTPElements(): Promise<void> {
render((
<>
{await Promise.all(Array.from(await getTOTPKeys(this.state.baseMount)).map(async (key) =>
<TOTPGridItem
item_key={String(key).toString()}
item_value={await getTOTPCode(this.state.baseMount, key)}
/>
))}
</>
), document.querySelector("#totpList"))
}
makeTOTPListElement(totpKeyName: string): TOTPListElement {
const gridElement = makeElement({
tag: "div",
class: ["uk-grid", "uk-grid-small", "uk-text-expand"],
}) as TOTPListElement;
return gridElement;
}
async getPageTitle(): Promise<Element | string> {
return await SecretTitleElement(this.router);
}
get name(): string {
return i18next.t("totp_view_title");
}
}