From 907c54bf296b34ce72dd852e9e0f3b3ce5261287 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Thu, 12 Sep 2024 11:26:41 +0200 Subject: [PATCH 1/4] dev: react strict mode in dev mode --- src/index.tsx | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 119ee5147..d8779c713 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -7,25 +7,32 @@ import { WebsocketProvider } from './context/WebsocketContext' import { ServiceInfoProvider } from './context/ServiceInfoContext' import { WalletProvider } from './context/WalletContext' import { ServiceConfigProvider } from './context/ServiceConfigContext' +import { isDevMode } from './constants/debugFeatures' import 'bootstrap/dist/css/bootstrap.min.css' import './index.css' import './i18n/config' +const ENBALE_STRICT_MODE = isDevMode() + const container = document.getElementById('root') const root = createRoot(container!) root.render( - - - - - - - - - - - - - , + (() => { + const children = ( + + + + + + + + + + + + ) + + return ENBALE_STRICT_MODE ? {children} : children + })(), ) From 342d030aab9c00f1d2623b0ad53eb557e6d5a414 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Thu, 12 Sep 2024 14:54:01 +0200 Subject: [PATCH 2/4] perf: load display data only if necessary --- src/context/WalletContext.tsx | 41 +++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/context/WalletContext.tsx b/src/context/WalletContext.tsx index 4a6f59ad0..b1aa8f0d7 100644 --- a/src/context/WalletContext.tsx +++ b/src/context/WalletContext.tsx @@ -1,4 +1,4 @@ -import { createContext, useEffect, useCallback, useState, useContext, PropsWithChildren, useMemo } from 'react' +import { createContext, useEffect, useCallback, useState, useContext, PropsWithChildren, useMemo, useRef } from 'react' import { getSession, setSession } from '../session' import * as fb from '../components/fb/utils' import * as Api from '../libs/JmWalletApi' @@ -143,6 +143,7 @@ interface WalletContextEntry { currentWalletInfo: WalletInfo | undefined reloadCurrentWalletInfo: { reloadAll: ({ signal }: { signal: AbortSignal }) => Promise + reloadAllForce: ({ signal }: { signal: AbortSignal }) => Promise reloadUtxos: ({ signal }: { signal: AbortSignal }) => Promise } } @@ -280,7 +281,7 @@ const WalletProvider = ({ children }: PropsWithChildren) => { [fetchDisplay], ) - const reloadAll = useCallback( + const reloadAllForce = useCallback( ({ signal }: { signal: AbortSignal }): Promise => Promise.all([reloadUtxos({ signal }), reloadDisplay({ signal })]) .then((data) => toCombinedRawData(data[0], data[1])) @@ -298,12 +299,44 @@ const WalletProvider = ({ children }: PropsWithChildren) => { return toWalletInfo(combinedRawData) }, [combinedRawData]) + const currentWalletInfoRef = useRef(currentWalletInfo) + + useEffect(() => { + currentWalletInfoRef.current = currentWalletInfo + }, [currentWalletInfoRef, currentWalletInfo]) + + const reloadAllIfNecessary = useCallback( + ({ signal }: { signal: AbortSignal }): Promise => + reloadUtxos({ signal }).then((utxoResponse) => { + const needsDisplayReload = + currentWalletInfoRef.current === undefined || + !!utxoResponse.utxos.find( + (utxo) => + // reload display data if: + // no address summary could be found for a returned UTXO... + currentWalletInfoRef.current!.addressSummary[utxo.address] === undefined || + // ...or if the address is still considered new + currentWalletInfoRef.current!.addressSummary[utxo.address].status === 'new', + ) + + if (!needsDisplayReload) { + return currentWalletInfoRef.current! + } + + return reloadDisplay({ signal }) + .then((displayResponse) => toCombinedRawData(utxoResponse, displayResponse)) + .then((raw) => toWalletInfo(raw)) + }), + [currentWalletInfoRef, reloadUtxos, reloadDisplay], + ) + const reloadCurrentWalletInfo = useMemo( () => ({ - reloadAll, + reloadAll: reloadAllIfNecessary, + reloadAllForce, reloadUtxos, }), - [reloadAll, reloadUtxos], + [reloadAllIfNecessary, reloadUtxos, reloadAllForce], ) useEffect(() => { From d88072a1792eb65ba91d14eb7d83edc2382bedd2 Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Thu, 12 Sep 2024 16:00:33 +0200 Subject: [PATCH 3/4] chore: 'force' reload on wallet unlock --- src/components/App.tsx | 14 +++++++------- src/context/WalletContext.tsx | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index 915a75f25..d8328d088 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -67,14 +67,14 @@ export default function App() { }, [clearCurrentWallet]) const reloadWalletInfo = useCallback( - (delay: Milliseconds) => { + ({ delay, force }: { delay: Milliseconds; force: boolean }) => { setReloadingWalletInfoCounter((current) => current + 1) console.info('Reloading wallet info...') return new Promise((resolve, reject) => setTimeout(() => { + const reload = force ? reloadCurrentWalletInfo.reloadAllForce : reloadCurrentWalletInfo.reloadAll const abortCtrl = new AbortController() - reloadCurrentWalletInfo - .reloadAll({ signal: abortCtrl.signal }) + reload({ signal: abortCtrl.signal }) .then((result) => resolve(result)) .catch((error) => reject(error)) .finally(() => { @@ -286,7 +286,7 @@ const MAX_RECURSIVE_WALLET_INFO_RELOADS = 10 interface WalletInfoAutoReloadProps { currentWallet: CurrentWallet | null - reloadWalletInfo: (delay: Milliseconds) => Promise + reloadWalletInfo: ({ delay, force }: { delay: Milliseconds; force: boolean }) => Promise } /** @@ -316,7 +316,7 @@ const WalletInfoAutoReload = ({ currentWallet, reloadWalletInfo }: WalletInfoAut function reloadAfterUnlock() { if (!currentWallet) return - reloadWalletInfo(RELOAD_WALLET_INFO_DELAY.AFTER_UNLOCK).catch((err) => console.error(err)) + reloadWalletInfo({ delay: RELOAD_WALLET_INFO_DELAY.AFTER_UNLOCK, force: true }).catch((err) => console.error(err)) }, [currentWallet, reloadWalletInfo], ) @@ -335,14 +335,14 @@ const WalletInfoAutoReload = ({ currentWallet, reloadWalletInfo }: WalletInfoAut callCounter: number = 0, ) => { if (callCounter >= maxCalls) return - const info = await reloadWalletInfo(delay) + const info = await reloadWalletInfo({ delay, force: false }) const newBalance = info.balanceSummary.calculatedTotalBalanceInSats if (newBalance > currentBalance) { await reloadWhileBalanceChangesRecursively(newBalance, delay, maxCalls, callCounter++) } } - reloadWalletInfo(RELOAD_WALLET_INFO_DELAY.AFTER_RESCAN) + reloadWalletInfo({ delay: RELOAD_WALLET_INFO_DELAY.AFTER_RESCAN, force: false }) .then((info) => reloadWhileBalanceChangesRecursively( info.balanceSummary.calculatedTotalBalanceInSats, diff --git a/src/context/WalletContext.tsx b/src/context/WalletContext.tsx index b1aa8f0d7..ed322f830 100644 --- a/src/context/WalletContext.tsx +++ b/src/context/WalletContext.tsx @@ -312,10 +312,10 @@ const WalletProvider = ({ children }: PropsWithChildren) => { currentWalletInfoRef.current === undefined || !!utxoResponse.utxos.find( (utxo) => - // reload display data if: + // reload "display" data if: // no address summary could be found for a returned UTXO... currentWalletInfoRef.current!.addressSummary[utxo.address] === undefined || - // ...or if the address is still considered new + // ...or if the address is still considered "new" currentWalletInfoRef.current!.addressSummary[utxo.address].status === 'new', ) From 09cf5a5cb91f0868fddcf59acede9953b207fbcd Mon Sep 17 00:00:00 2001 From: theborakompanioni Date: Thu, 12 Sep 2024 16:12:03 +0200 Subject: [PATCH 4/4] ui(earn): validate minsize on mount of form --- src/components/Earn.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/Earn.tsx b/src/components/Earn.tsx index 17c2683ad..9c9b3dcce 100644 --- a/src/components/Earn.tsx +++ b/src/components/Earn.tsx @@ -276,7 +276,15 @@ const EarnForm = ({ } return ( - + {(props) => { const { handleSubmit, setFieldValue, handleBlur, values, touched, errors, isSubmitting } = props const minsizeField = props.getFieldProps('minsize')