From caa9a22d6970df331eebed032b9a9673d4217fc6 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 6 Dec 2021 15:27:20 -0300 Subject: check timeout when doing a query to /keys to add an exchange --- .../src/wallet/ExchangeSetUrl.tsx | 118 +++++++++++++-------- 1 file changed, 74 insertions(+), 44 deletions(-) (limited to 'packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx') diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx index e87a8894f..d529d162b 100644 --- a/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx @@ -17,52 +17,75 @@ import { export interface Props { initialValue?: string; expectedCurrency?: string; - knownExchanges: ExchangeListItem[]; onCancel: () => void; onVerify: (s: string) => Promise; onConfirm: (url: string) => Promise; withError?: string; } +function useEndpointStatus( + endpoint: string, + onVerify: (e: string) => Promise, +): { + loading: boolean; + error?: string; + endpoint: string; + result: T | undefined; + updateEndpoint: (s: string) => void; +} { + const [value, setValue] = useState(endpoint); + const [dirty, setDirty] = useState(false); + const [loading, setLoading] = useState(false); + const [result, setResult] = useState(undefined); + const [error, setError] = useState(undefined); + + const [handler, setHandler] = useState(undefined); + + useEffect(() => { + if (!value) return; + window.clearTimeout(handler); + const h = window.setTimeout(async () => { + setDirty(true); + setLoading(true); + try { + const url = canonicalizeBaseUrl(value); + const result = await onVerify(url); + setResult(result); + setError(undefined); + setLoading(false); + } catch (e) { + const errorMessage = + e instanceof Error ? e.message : `unknown error: ${e}`; + setError(errorMessage); + setLoading(false); + setResult(undefined); + } + }, 500); + setHandler(h); + }, [value]); + + return { + error: dirty ? error : undefined, + loading: loading, + result: result, + endpoint: value, + updateEndpoint: setValue, + }; +} + export function ExchangeSetUrlPage({ initialValue, - knownExchanges, expectedCurrency, onCancel, onVerify, onConfirm, - withError, }: Props) { - const [value, setValue] = useState(initialValue || ""); - const [dirty, setDirty] = useState(false); - const [result, setResult] = useState( - undefined, - ); - const [error, setError] = useState(withError); - - useEffect(() => { - try { - const url = canonicalizeBaseUrl(value); + const { loading, result, endpoint, updateEndpoint, error } = + useEndpointStatus(initialValue ?? "", onVerify); - const found = - knownExchanges.findIndex((e) => e.exchangeBaseUrl === url) !== -1; - - if (found) { - setError("This exchange is already known"); - return; - } - onVerify(url) - .then((r) => { - setResult(r); - }) - .catch(() => { - setResult(undefined); - }); - setDirty(true); - } catch { - setResult(undefined); - } - }, [value]); + const [confirmationError, setConfirmationError] = useState< + string | undefined + >(undefined); return ( @@ -72,21 +95,32 @@ export function ExchangeSetUrlPage({ ) : (

Add exchange for {expectedCurrency}

)} + {result && expectedCurrency && expectedCurrency !== result.currency && ( + + This exchange doesn't match the expected currency{" "} + {expectedCurrency} + + )} +

- + setValue(e.currentTarget.value)} + value={endpoint} + onInput={(e) => updateEndpoint(e.currentTarget.value)} /> - {result && ( + {loading &&

loading...
} + {result && !loading && ( @@ -100,12 +134,6 @@ export function ExchangeSetUrlPage({ )}

- {result && expectedCurrency && expectedCurrency !== result.currency && ( - - This exchange doesn't match the expected currency{" "} - {expectedCurrency} - - )}