diff --git a/src/pages/Secrets/TOTP/TOTPView.ts b/src/pages/Secrets/TOTP/TOTPView.ts deleted file mode 100644 index 4bf7c6f..0000000 --- a/src/pages/Secrets/TOTP/TOTPView.ts +++ /dev/null @@ -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; - - async goBack(): Promise { - await this.router.changePage("SECRETS_HOME"); - } - - async render(): Promise { - 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 { - clearInterval(this.refresher); - this.totpListElements = {}; - } - - async updateTOTPElement(totpKeyName: string, totpListElement: TOTPListElement): Promise { - 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 { - return await SecretTitleElement(this.router); - } - - get name(): string { - return i18next.t("totp_view_title"); - } -} diff --git a/src/pages/Secrets/TOTP/TOTPView.tsx b/src/pages/Secrets/TOTP/TOTPView.tsx new file mode 100644 index 0000000..87e932d --- /dev/null +++ b/src/pages/Secrets/TOTP/TOTPView.tsx @@ -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 ( +
+ + +
+ ); +} + +export class TOTPViewPage extends Page { + constructor() { + super(); + this.refresher = undefined; + } + + refresher: number; + + async goBack(): Promise { + await this.router.changePage("SECRETS_HOME"); + } + + async render(): Promise { + console.log(quickHash("abc")); + + render(( +
+ +

{i18next.t("totp_view_loading")}

+
+
+
+
+ ), 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 { + clearInterval(this.refresher); + } + + async updateTOTPElements(): Promise { + render(( + <> + {await Promise.all(Array.from(await getTOTPKeys(this.state.baseMount)).map(async (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 { + return await SecretTitleElement(this.router); + } + + get name(): string { + return i18next.t("totp_view_title"); + } +}