From fce8938a1da5766b64175835449e83faff860530 Mon Sep 17 00:00:00 2001 From: sl Date: Thu, 10 Oct 2024 09:42:15 +0200 Subject: [PATCH] frontend: revert f564cfa94f0979fd3efff2b638ce1e933f4e63f0 f564cfa94f0979fd3efff2b638ce1e933f4e63f0 causes infinite loop to AOPP endpoint, thus we revert it for now. --- .../web/src/components/aopp/aopp.module.css | 5 + frontends/web/src/components/aopp/aopp.tsx | 395 ++++++++++-------- 2 files changed, 218 insertions(+), 182 deletions(-) diff --git a/frontends/web/src/components/aopp/aopp.module.css b/frontends/web/src/components/aopp/aopp.module.css index e9e8a89472..8d2dadbf60 100644 --- a/frontends/web/src/components/aopp/aopp.module.css +++ b/frontends/web/src/components/aopp/aopp.module.css @@ -7,6 +7,11 @@ text-align: center; } +.smallIcon { + margin: auto 0; + width: 30px; +} + .successText { color: var(--color-secondary); font-weight: 400; diff --git a/frontends/web/src/components/aopp/aopp.tsx b/frontends/web/src/components/aopp/aopp.tsx index 562fac387a..e75a57c50f 100644 --- a/frontends/web/src/components/aopp/aopp.tsx +++ b/frontends/web/src/components/aopp/aopp.tsx @@ -1,5 +1,5 @@ /** - * Copyright 2021-2024 Shift Crypto AG + * Copyright 2021 Shift Crypto AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +14,21 @@ * limitations under the License. */ -import React, { ReactNode, useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; +import React, { Component, ReactNode } from 'react'; import * as accountAPI from '@/api/account'; import * as aoppAPI from '@/api/aopp'; +import { translate, TranslateProps } from '@/decorators/translate'; import { equal } from '@/utils/equal'; import { SimpleMarkup } from '@/utils/markup'; import { View, ViewHeader, ViewContent, ViewButtons } from '@/components/view/view'; import { Message } from '@/components/message/message'; import { Button, Field, Label, Select } from '@/components/forms'; import { CopyableInput } from '@/components/copy/Copy'; -import { PointToBitBox02 } from '@/components/icon'; +import { Cancel, PointToBitBox02 } from '@/components/icon'; import { VerifyAddress } from './verifyaddress'; import { Vasp } from './vasp'; import styles from './aopp.module.css'; +import { TUnsubscribe } from '@/utils/transport-common'; type TProps = { children: ReactNode; @@ -37,111 +38,164 @@ const Banner = ({ children }: TProps) => (
{children}
); +type State = { + accountCode: accountAPI.AccountCode; + aopp?: aoppAPI.Aopp; +} + +type Props = TranslateProps; + const domain = (callback: string): string => new URL(callback).host; -export const Aopp = () => { - const { t } = useTranslation(); +class Aopp extends Component { + public readonly state: State = { + accountCode: '', + aopp: undefined, + }; + private unsubscribe?: TUnsubscribe; - const [accountCode, setAccountCode] = useState(''); - const [aopp, setAopp] = useState(); + public componentDidMount() { + this.setAccountCodeDefault(); + this.unsubscribe = aoppAPI.subscribeAOPP(aopp => this.updateAOPP(aopp)); + aoppAPI.getAOPP().then(aopp => this.setState({ aopp })); + } + public componentWillUnmount() { + if (this.unsubscribe) { + this.unsubscribe(); + } + } - const setAccountCodeDefault = (aopp: aoppAPI.Aopp | undefined) => { + private updateAOPP(aopp: aoppAPI.Aopp) { + let shouldUpdateAccountCodeDefault = false; + this.setState(currentState => { + if (aopp?.state === 'choosing-account' + && ( + currentState.aopp?.state !== 'choosing-account' + || !equal(aopp.accounts, currentState.aopp?.accounts) + ) + ) { + shouldUpdateAccountCodeDefault = true; + } + return { aopp }; + }, () => { // callback when state did update + if (shouldUpdateAccountCodeDefault) { + this.setAccountCodeDefault(); + } + }); + } + + private setAccountCodeDefault() { + const { aopp } = this.state; if (aopp === undefined || aopp.state !== 'choosing-account') { return; } if (aopp.accounts.length) { - setAccountCode(aopp.accounts[0].code); + this.setState({ accountCode: aopp.accounts[0].code }); } - }; - - useEffect(() => { - setAccountCodeDefault(aopp); - const unsubscribe = aoppAPI.subscribeAOPP((new_aopp: aoppAPI.Aopp) => { - if (new_aopp?.state === 'choosing-account' - && ( - aopp?.state !== 'choosing-account' - || !equal(new_aopp.accounts, aopp?.accounts) - )) { - setAccountCodeDefault(new_aopp); - } - setAopp(new_aopp); - }); - aoppAPI.getAOPP().then(aopp => setAopp(aopp)); - return unsubscribe; - }, [aopp]); + } - const chooseAccount = (e: React.SyntheticEvent) => { - if (accountCode) { - aoppAPI.chooseAccount(accountCode); + private chooseAccount = (e: React.SyntheticEvent) => { + if (this.state.accountCode) { + aoppAPI.chooseAccount(this.state.accountCode); } e.preventDefault(); }; - if (!aopp) { - return null; - } - switch (aopp.state) { - case 'error': - return ( - - -

{domain(aopp.callback)}

-
- - - {t(`error.${aopp.errorCode}`, { host: domain(aopp.callback) })} - - - - - -
- ); - case 'inactive': - // Inactive, waiting for action. - return null; - case 'user-approval': - return ( - - - - ${domain(aopp.callback)}` - })} /> - )} - withLogoText={t('aopp.addressRequestWithLogo')} /> - - - - - - - ); - case 'awaiting-keystore': - return ( - {t('aopp.banner')} - ); - case 'choosing-account': { - const options = aopp.accounts.map(account => { - return { - text: account.name, - value: account.code, - }; - }); - return ( -
+ public render() { + const { t } = this.props; + const { accountCode, aopp } = this.state; + if (!aopp) { + return null; + } + switch (aopp.state) { + case 'error': + return ( + + +

{domain(aopp.callback)}

+
+ + + + {t(`error.${aopp.errorCode}`, { host: domain(aopp.callback) })} + + + + + +
+ ); + case 'inactive': + // Inactive, waiting for action. + return null; + case 'user-approval': + return ( + + + + ${domain(aopp.callback)}` + })}/> + )} + withLogoText={t('aopp.addressRequestWithLogo')} /> + + + + + + + ); + case 'awaiting-keystore': + return ( + {t('aopp.banner')} + ); + case 'choosing-account': { + const options = aopp.accounts.map(account => { + return { + text: account.name, + value: account.code, + }; + }); + return ( + + + + + + + setAccountCode((e.target as HTMLSelectElement)?.value)} - id="account" /> +

{t('aopp.syncing')}

-
-
- ); - } - case 'syncing': - return ( - - - - - -

{t('aopp.syncing')}

-
- - - -
- ); - case 'signing': - return ( - - - - - -

{t('aopp.signing')}

- - - - - - -
- {aopp.message} -
-
- -
-
- ); - case 'success': - return ( - - -

{t('aopp.success.title')}

-

- {t('aopp.success.message', { host: domain(aopp.callback) })} -

- - - - - - -
- {aopp.message} -
-
-
- - - - -
- ); + ); + case 'signing': + return ( + + + + + +

{t('aopp.signing')}

+ + + + + + +
+ {aopp.message} +
+
+ +
+
+ ); + case 'success': + return ( + + +

{t('aopp.success.title')}

+

+ {t('aopp.success.message', { host: domain(aopp.callback) })} +

+ + + + + + +
+ {aopp.message} +
+
+
+ + + + +
+ ); + } } -}; +} +const translateHOC = translate()(Aopp); +export { translateHOC as Aopp }; \ No newline at end of file