From fdc1c221e6004274870e6e13f7798cfe2cc2875f Mon Sep 17 00:00:00 2001 From: thisconnect Date: Sat, 7 Oct 2023 11:34:19 +0200 Subject: [PATCH 1/2] frontend: type keystores --- frontends/web/src/api/keystores.ts | 33 +++++++++++++++++++ .../web/src/components/sidebar/sidebar.tsx | 32 ++++++++++-------- 2 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 frontends/web/src/api/keystores.ts diff --git a/frontends/web/src/api/keystores.ts b/frontends/web/src/api/keystores.ts new file mode 100644 index 0000000000..23104690f1 --- /dev/null +++ b/frontends/web/src/api/keystores.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2023 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { subscribeEndpoint, TUnsubscribe } from './subscribe'; +import { apiGet } from '../utils/request'; + +export type { TUnsubscribe }; + +type TKeystore = { type: 'hardware' | 'software' }; +export type TKeystores = TKeystore[]; + +export const subscribeKeystores = ( + cb: (keystores: TKeystores) => void +) => { + return subscribeEndpoint('keystores', cb); +}; + +export const getKeystores = (): Promise => { + return apiGet('keystores'); +}; diff --git a/frontends/web/src/components/sidebar/sidebar.tsx b/frontends/web/src/components/sidebar/sidebar.tsx index c2f6ba0283..79ff1e2329 100644 --- a/frontends/web/src/components/sidebar/sidebar.tsx +++ b/frontends/web/src/components/sidebar/sidebar.tsx @@ -17,6 +17,7 @@ import React, { Component } from 'react'; import { Link, NavLink } from 'react-router-dom'; +import { TKeystores, subscribeKeystores, TUnsubscribe, getKeystores } from '../../api/keystores'; import { IAccount } from '../../api/account'; import coins from '../../assets/icons/coins.svg'; import ejectIcon from '../../assets/icons/eject.svg'; @@ -24,7 +25,6 @@ import info from '../../assets/icons/info.svg'; import settings from '../../assets/icons/settings-alt.svg'; import settingsGrey from '../../assets/icons/settings-alt_disabled.svg'; import { share } from '../../decorators/share'; -import { subscribe } from '../../decorators/subscribe'; import { translate, TranslateProps } from '../../decorators/translate'; import { debug } from '../../utils/env'; import { apiPost } from '../../utils/request'; @@ -40,10 +40,6 @@ interface SidebarProps { accounts: IAccount[]; } -interface SubscribedProps { - keystores?: Array<{ type: 'hardware' | 'software' }>; -} - export type SharedPanelProps = { // eslint-disable-next-line react/no-unused-prop-types activeSidebar: boolean; @@ -51,7 +47,7 @@ export type SharedPanelProps = { sidebarStatus: string; } -type Props = SubscribedProps & SharedPanelProps & SidebarProps & TranslateProps; +type Props = SharedPanelProps & SidebarProps & TranslateProps; type TGetAccountLinkProps = IAccount & { handleSidebarItemClick: ((e: React.SyntheticEvent) => void) }; @@ -92,16 +88,30 @@ const GetAccountLink = ({ coinCode, code, name, handleSidebarItemClick }: TGetAc ); }; +type State = { + keystores: TKeystores; +} class Sidebar extends Component { private swipe!: SwipeAttributes; + private unsubscribeFn?: TUnsubscribe; + + public readonly state: State = { + keystores: [], + }; public componentDidMount() { this.registerTouchEvents(); + getKeystores().then(keystores => this.setState({ keystores }, () => { + this.unsubscribeFn = subscribeKeystores(keystores => this.setState({ keystores })); + })); } public componentWillUnmount() { this.removeTouchEvents(); + if (this.unsubscribeFn) { + this.unsubscribeFn(); + } } private registerTouchEvents = () => { @@ -158,11 +168,11 @@ class Sidebar extends Component { }; public render() { + const { keystores } = this.state; const { t, deviceIDs, accounts, - keystores, activeSidebar, sidebarStatus, } = this.props; @@ -255,12 +265,6 @@ function eject(e: React.SyntheticEvent): void { e.preventDefault(); } -const subscribeHOC = subscribe( - { keystores: 'keystores' }, - false, - false, -)(Sidebar); - -const guideShareHOC = share(panelStore)(subscribeHOC); +const guideShareHOC = share(panelStore)(Sidebar); const translateHOC = translate()(guideShareHOC); export { translateHOC as Sidebar }; From cf93f4654e3da9a52fe0766087b6ff2a7d951ef0 Mon Sep 17 00:00:00 2001 From: thisconnect Date: Tue, 24 Oct 2023 09:21:41 +0200 Subject: [PATCH 2/2] frontend: only update addbuyreceiveonemptybalance state if mounted Used mounted hook to only update AddBuyReceiveOnEmptyBalances state if the component is actually mounted. --- .../web/src/routes/account/info/buyReceiveCTA.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/frontends/web/src/routes/account/info/buyReceiveCTA.tsx b/frontends/web/src/routes/account/info/buyReceiveCTA.tsx index ed1f3580c5..c70b64bf0a 100644 --- a/frontends/web/src/routes/account/info/buyReceiveCTA.tsx +++ b/frontends/web/src/routes/account/info/buyReceiveCTA.tsx @@ -22,6 +22,7 @@ import { Balances } from '../summary/accountssummary'; import { isBitcoinCoin } from '../utils'; import { getExchangeSupportedAccounts } from '../../buy/utils'; import styles from './buyReceiveCTA.module.css'; +import { useMountedRef } from '../../../hooks/mount'; type TBuyReceiveCTAProps = { balanceList?: [string, IBalance][]; @@ -62,12 +63,20 @@ export const BuyReceiveCTA = ({ code, unit, balanceList, exchangeBuySupported = export const AddBuyReceiveOnEmptyBalances = ({ balances, accounts }: TAddBuyReceiveOnEmpyBalancesProps) => { - + const mounted = useMountedRef(); const [supportedAccounts, setSupportedAccounts] = useState(); useEffect(() => { - getExchangeSupportedAccounts(accounts).then(setSupportedAccounts); - }, [accounts]); + if (mounted.current) { + getExchangeSupportedAccounts(accounts) + .then(supportedAccounts => { + if (mounted.current) { + setSupportedAccounts(supportedAccounts); + } + }) + .catch(console.error); + } + }, [accounts, mounted]); if (balances === undefined || supportedAccounts === undefined) { return null;