1 import { useRef, useState } from 'react';
3 import { getApiSubdomainUrl } from '@proton/shared/lib/helpers/url';
4 import randomIntFromInterval from '@proton/utils/randomIntFromInterval';
6 import ChallengeError from './ChallengeError';
7 import type { Props as ChallengeProps } from './ChallengeFrame';
8 import ChallengeFrame from './ChallengeFrame';
9 import type { ChallengeLog } from './interface';
11 interface Props extends Omit<ChallengeProps, 'src' | 'onError' | 'onSuccess'> {
14 iframeClassName?: string;
15 onSuccess: (challengeLog: ChallengeLog[]) => void;
16 onError: (challengeLog: ChallengeLog[]) => void;
30 const [error, setError] = useState(false);
31 const [errorRetry, setErrorRetry] = useState(0);
32 const challengeLogRef = useRef<ChallengeLog[]>([]);
34 const challengeSrc = (() => {
35 const url = getApiSubdomainUrl('/challenge/v4/html', window.location.origin);
36 url.searchParams.set('Type', `${type}`);
37 url.searchParams.set('Name', name);
39 url.searchParams.set('Retry', `${errorRetry}`);
41 return url.toString();
44 // Loading error timeouts in intervals of [12, 15], [17, 20], [22, 25]
45 const jitter = randomIntFromInterval(0, 3);
46 const errorTimeout = (15 + errorRetry * 5 - jitter) * 1000;
52 return <ChallengeError />;
59 errorTimeout={errorTimeout}
60 className={iframeClassName ? iframeClassName : 'w-full'}
61 bodyClassName={bodyClassName}
64 onSuccess?.(challengeLogRef.current);
66 onError={(challengeLog) => {
67 challengeLogRef.current = challengeLogRef.current.concat(challengeLog);
69 setErrorRetry(errorRetry + 1);
73 onError?.(challengeLogRef.current);
82 export default Challenge;