diff --git a/native/account/siwe-panel.react.js b/native/account/siwe-panel.react.js index d9be75da9..06b28277b 100644 --- a/native/account/siwe-panel.react.js +++ b/native/account/siwe-panel.react.js @@ -1,249 +1,259 @@ // @flow import BottomSheet from '@gorhom/bottom-sheet'; import * as React from 'react'; -import { ActivityIndicator, Text, View, Alert } from 'react-native'; +import { ActivityIndicator, View, Alert } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import WebView from 'react-native-webview'; import { getSIWENonce, getSIWENonceActionTypes, siweAuth, siweAuthActionTypes, } from 'lib/actions/siwe-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import type { LogInStartingPayload } from 'lib/types/account-types'; import type { SIWEWebViewMessage } from 'lib/types/siwe-types'; import { useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils'; import { NavContext } from '../navigation/navigation-context'; import { useSelector } from '../redux/redux-utils'; import { nativeLogInExtraInfoSelector } from '../selectors/account-selectors'; import { defaultLandingURLPrefix } from '../utils/url-utils'; import type { LoggedOutMode } from './logged-out-modal.react'; const commSIWE = `${defaultLandingURLPrefix}/siwe`; const getSIWENonceLoadingStatusSelector = createLoadingStatusSelector( getSIWENonceActionTypes, ); const siweAuthLoadingStatusSelector = createLoadingStatusSelector( siweAuthActionTypes, ); type Props = { +onClose: () => mixed, +nextMode: LoggedOutMode, }; function SIWEPanel(props: Props): React.Node { const navContext = React.useContext(NavContext); const dispatchActionPromise = useDispatchActionPromise(); const getSIWENonceCall = useServerCall(getSIWENonce); const siweAuthCall = useServerCall(siweAuth); const logInExtraInfo = useSelector(state => nativeLogInExtraInfoSelector({ redux: state, navContext, }), ); const getSIWENonceCallFailed = useSelector( state => getSIWENonceLoadingStatusSelector(state) === 'error', ); + + const { onClose } = props; + React.useEffect(() => { + if (getSIWENonceCallFailed) { + Alert.alert( + 'Unknown error', + 'Uhh... try again?', + [{ text: 'OK', onPress: onClose }], + { cancelable: false }, + ); + } + }, [getSIWENonceCallFailed, onClose]); + const siweAuthCallLoading = useSelector( state => siweAuthLoadingStatusSelector(state) === 'loading', ); const [nonce, setNonce] = React.useState(null); React.useEffect(() => { (async () => { dispatchActionPromise( getSIWENonceActionTypes, (async () => { const response = await getSIWENonceCall(); setNonce(response); })(), ); })(); }, [dispatchActionPromise, getSIWENonceCall]); const [isLoading, setLoading] = React.useState(true); const [isWalletConnectModalOpen, setWalletConnectModalOpen] = React.useState( false, ); const insets = useSafeAreaInsets(); const bottomInset = insets.bottom; const snapPoints = React.useMemo(() => { if (isLoading) { return [1]; } else if (isWalletConnectModalOpen) { return [bottomInset + 600]; } else { return [bottomInset + 435, bottomInset + 600]; } }, [isLoading, isWalletConnectModalOpen, bottomInset]); const bottomSheetRef = React.useRef(); const snapToIndex = bottomSheetRef.current?.snapToIndex; React.useEffect(() => { // When the snapPoints change, always reset to the first one // Without this, when we close the WalletConnect modal we don't resize snapToIndex?.(0); }, [snapToIndex, snapPoints]); - const { onClose } = props; const callSIWE = React.useCallback( async (message, signature, extraInfo) => { try { return await siweAuthCall({ message, signature, ...extraInfo, }); } catch (e) { Alert.alert( 'Unknown error', 'Uhh... try again?', [{ text: 'OK', onPress: onClose }], { cancelable: false }, ); throw e; } }, [onClose, siweAuthCall], ); const handleSIWE = React.useCallback( ({ message, signature }) => { const extraInfo = logInExtraInfo(); dispatchActionPromise( siweAuthActionTypes, callSIWE(message, signature, extraInfo), undefined, ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), ); }, [logInExtraInfo, dispatchActionPromise, callSIWE], ); const closeBottomSheet = bottomSheetRef.current?.close; const { nextMode } = props; const disableOnClose = React.useRef(false); const handleMessage = React.useCallback( event => { const data: SIWEWebViewMessage = JSON.parse(event.nativeEvent.data); if (data.type === 'siwe_success') { const { address, message, signature } = data; if (address && signature) { disableOnClose.current = true; closeBottomSheet?.(); handleSIWE({ message, signature }); } } else if (data.type === 'siwe_closed') { onClose(); closeBottomSheet?.(); } else if (data.type === 'walletconnect_modal_update') { setWalletConnectModalOpen(data.state === 'open'); } }, [handleSIWE, onClose, closeBottomSheet], ); const prevNextModeRef = React.useRef(); React.useEffect(() => { if (nextMode === 'prompt' && prevNextModeRef.current === 'siwe') { closeBottomSheet?.(); } prevNextModeRef.current = nextMode; }, [nextMode, closeBottomSheet]); const source = React.useMemo( () => ({ uri: commSIWE, headers: { 'siwe-nonce': nonce, }, }), [nonce], ); const onWebViewLoaded = React.useCallback(() => { setLoading(false); }, []); const backgroundStyle = React.useMemo( () => ({ backgroundColor: '#242529', }), [], ); const bottomSheetHandleIndicatorStyle = React.useMemo( () => ({ backgroundColor: 'white', }), [], ); const onBottomSheetChange = React.useCallback( (index: number) => { if (disableOnClose.current) { disableOnClose.current = false; return; } if (index === -1) { onClose(); } }, [onClose], ); let bottomSheet; if (nonce) { bottomSheet = ( ); } let activity; - if (getSIWENonceCallFailed) { - activity = Oops, try again later!; - } else if (isLoading || siweAuthCallLoading) { + if (!getSIWENonceCallFailed && (isLoading || siweAuthCallLoading)) { activity = ; } const activityContainer = React.useMemo( () => ({ flex: 1, }), [], ); return ( <> {activity} {bottomSheet} ); } export default SIWEPanel;