// 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, useEffect } from "react"; import classNames from "classnames"; import { Typography } from "antd"; import { CopyConfig } from "@comp/types"; import { useTranslation } from "react-i18next"; import { useSelector, shallowEqual } from "react-redux"; import { RootState } from "@store"; import { aesGcmDecrypt } from "@utils/crypto"; import { AuthorisedAction } from "@comp/auth/AuthorisedAction"; const { Text, Link } = Typography; interface Props { value?: string; encrypted?: boolean; copyable?: boolean | CopyConfig; className?: string; } /** Hides a piece of data until a 'Reveal' link is clicked. If necessary, the * user will be prompted for their master password to decrypt the data. */ export function DecryptReveal({ value, encrypted, copyable, className }: Props): JSX.Element { const { t } = useTranslation(); const { isAuthed, masterPassword } = useSelector((s: RootState) => s.masterPassword, shallowEqual); const [revealed, setRevealed] = useState(false); const [decrypted, setDecrypted] = useState<string>(); const reveal = () => setRevealed(true); useEffect(() => { if (!isAuthed || !masterPassword || !value || !revealed || decrypted) return; (async () => { const dec = await aesGcmDecrypt(value, masterPassword); setDecrypted(dec); })().catch(console.error); }, [isAuthed, masterPassword, value, revealed, decrypted]); function RevealedContents(): JSX.Element { return <> <Text className={classes} copyable={copyable}> {encrypted ? decrypted : value} </Text> {/* Hide link */} <Link onClick={() => setRevealed(false)} style={{ display: "inline-block", marginLeft: 8 }} > {t("myWallets.info.hideLink")} </Link> </>; } const canReveal = !encrypted || isAuthed; const revealLink = ( <Link onClick={canReveal ? reveal : undefined}> {t("myWallets.info.revealLink")} </Link> ); const classes = classNames("decrypt-reveal", className, { "decrypt-reveal-revealed": revealed, "decrypt-reveal-encrypted": encrypted, "decrypt-reveal-decrypted": !!decrypted, }); return revealed ? <RevealedContents /> : (encrypted ? <AuthorisedAction onAuthed={reveal}>{revealLink}</AuthorisedAction> : revealLink ); }