diff --git a/lib/socket/socket.react.js b/lib/socket/socket.react.js --- a/lib/socket/socket.react.js +++ b/lib/socket/socket.react.js @@ -102,6 +102,8 @@ +dispatchActionPromise: DispatchActionPromise, // async functions that hit server APIs +logOut: (preRequestUserState: PreRequestUserState) => Promise, + +noDataAfterPolicyAcknowledgment?: boolean, + +refetchUserData?: () => Promise, }; type State = { +inflightRequests: ?InflightRequests, @@ -120,6 +122,7 @@ reopenConnectionAfterClosing: boolean = false; invalidationRecoveryInProgress: boolean = false; initializedWithUserState: ?PreRequestUserState; + failureCounter: number = 0; openSocket(newStatus: ConnectionStatus) { if ( @@ -403,6 +406,7 @@ if (!message) { return; } + this.failureCounter = 0; const { inflightRequests } = this.state; if (!inflightRequests) { @@ -630,6 +634,17 @@ try { await this.sendInitialMessage(); } catch (e) { + if (this.props.noDataAfterPolicyAcknowledgment) { + this.failureCounter++; + } else { + this.failureCounter = 0; + } + if (this.failureCounter >= 2) { + this.failureCounter = 0; + await this.props.refetchUserData?.(); + return; + } + console.log(e); const { status } = this.props.connection; if ( diff --git a/native/selectors/account-selectors.js b/native/selectors/account-selectors.js --- a/native/selectors/account-selectors.js +++ b/native/selectors/account-selectors.js @@ -4,8 +4,12 @@ import { logInExtraInfoSelector } from 'lib/selectors/account-selectors'; import type { LogInExtraInfo } from 'lib/types/account-types'; +import type { UserPolicies } from 'lib/types/policy-types'; +import { values } from 'lib/utils/objects'; import { calendarActiveSelector } from '../navigation/nav-selectors'; +import type { AppState } from '../redux/state-types'; +import type { ConnectivityInfo } from '../types/connectivity'; import type { NavPlusRedux } from '../types/selector-types'; const nativeLogInExtraInfoSelector: ( @@ -19,4 +23,26 @@ ) => () => logInExtraInfoFunc(calendarActive), ); -export { nativeLogInExtraInfoSelector }; +const noDataAfterPolicyAcknowledgmentSelector: ( + state: AppState, +) => boolean = createSelector( + (state: AppState) => state.connectivity, + (state: AppState) => state.messageStore.currentAsOf, + (state: AppState) => state.userPolicies, + ( + connectivity: ConnectivityInfo, + currentAsOf: number, + userPolicies: UserPolicies, + ) => { + return ( + connectivity.connected && + currentAsOf === 0 && + values(userPolicies).every(policy => policy.isAcknowledged) + ); + }, +); + +export { + nativeLogInExtraInfoSelector, + noDataAfterPolicyAcknowledgmentSelector, +}; diff --git a/native/socket.react.js b/native/socket.react.js --- a/native/socket.react.js +++ b/native/socket.react.js @@ -1,16 +1,20 @@ // @flow import * as React from 'react'; +import Alert from 'react-native/Libraries/Alert/Alert'; import { useDispatch } from 'react-redux'; -import { logOut } from 'lib/actions/user-actions'; +import { logOut, logOutActionTypes } from 'lib/actions/user-actions'; import { preRequestUserStateSelector } from 'lib/selectors/account-selectors'; import { isLoggedIn } from 'lib/selectors/user-selectors'; import Socket, { type BaseSocketProps } from 'lib/socket/socket.react'; +import { logInActionSources } from 'lib/types/account-types'; import { useServerCall, useDispatchActionPromise, + fetchNewCookieFromNativeCredentials, } from 'lib/utils/action-utils'; +import { isValidEthereumAddress } from 'lib/utils/siwe-utils'; import { InputStateContext } from './input/input-state'; import { @@ -19,6 +23,7 @@ } from './navigation/nav-selectors'; import { NavContext } from './navigation/navigation-context'; import { useSelector } from './redux/redux-utils'; +import { noDataAfterPolicyAcknowledgmentSelector } from './selectors/account-selectors'; import { openSocketSelector, sessionIdentificationSelector, @@ -38,6 +43,10 @@ const active = useSelector( state => isLoggedIn(state) && state.lifecycleState !== 'background', ); + const noDataAfterPolicyAcknowledgment = useSelector( + noDataAfterPolicyAcknowledgmentSelector, + ); + const currentUserInfo = useSelector(state => state.currentUserInfo); const openSocket = useSelector(openSocketSelector); const sessionIdentification = useSelector(sessionIdentificationSelector); @@ -80,6 +89,42 @@ const dispatchActionPromise = useDispatchActionPromise(); const callLogOut = useServerCall(logOut); + const refetchUserData = React.useCallback(async () => { + if ( + currentUserInfo?.username && + isValidEthereumAddress(currentUserInfo.username) + ) { + dispatchActionPromise( + logOutActionTypes, + callLogOut(preRequestUserState), + ); + Alert.alert( + 'Log in needed', + 'After acknowledging the policies, we need you to log in to your account again', + [{ text: 'OK' }], + { + cancelable: false, + }, + ); + return; + } + + await fetchNewCookieFromNativeCredentials( + dispatch, + cookie, + urlPrefix, + logInActionSources.socketAuthErrorResolutionAttempt, + ); + }, [ + callLogOut, + cookie, + currentUserInfo?.username, + dispatch, + dispatchActionPromise, + preRequestUserState, + urlPrefix, + ]); + return ( ); },