diff --git a/native/account/log-in-panel.react.js b/native/account/log-in-panel.react.js --- a/native/account/log-in-panel.react.js +++ b/native/account/log-in-panel.react.js @@ -43,6 +43,7 @@ import { useSelector } from '../redux/redux-utils.js'; import { nativeLogInExtraInfoSelector } from '../selectors/account-selectors.js'; import type { KeyPressEvent } from '../types/react-native.js'; +import { appOutOfDateAlert } from '../utils/alert-messages.js'; import Alert from '../utils/alert.js'; import { useInitialNotificationsEncryptedMessage } from '../utils/crypto-utils.js'; import type { StateContainer } from '../utils/state-container.js'; @@ -270,14 +271,10 @@ { cancelable: false }, ); } else if (e.message === 'client_version_unsupported') { - const app = Platform.select({ - ios: 'App Store', - android: 'Play Store', - }); + const alertDetails = appOutOfDateAlert(); Alert.alert( - 'App out of date', - 'Your app version is pretty old, and the server doesn’t know how ' + - `to speak to it anymore. Please use the ${app} app to update!`, + alertDetails.title, + alertDetails.message, [{ text: 'OK', onPress: this.onAppOutOfDateAlertAcknowledged }], { cancelable: false }, ); diff --git a/native/account/register-panel.react.js b/native/account/register-panel.react.js --- a/native/account/register-panel.react.js +++ b/native/account/register-panel.react.js @@ -46,6 +46,7 @@ import { useSelector } from '../redux/redux-utils.js'; import { nativeLogInExtraInfoSelector } from '../selectors/account-selectors.js'; import type { KeyPressEvent } from '../types/react-native.js'; +import { appOutOfDateAlert } from '../utils/alert-messages.js'; import Alert from '../utils/alert.js'; import { useInitialNotificationsEncryptedMessage } from '../utils/crypto-utils.js'; import { type StateContainer } from '../utils/state-container.js'; @@ -379,14 +380,10 @@ { cancelable: false }, ); } else if (e.message === 'client_version_unsupported') { - const app = Platform.select({ - ios: 'App Store', - android: 'Play Store', - }); + const alertDetails = appOutOfDateAlert(); Alert.alert( - 'App out of date', - 'Your app version is pretty old, and the server doesn’t know how ' + - `to speak to it anymore. Please use the ${app} app to update!`, + alertDetails.title, + alertDetails.message, [{ text: 'OK', onPress: this.onAppOutOfDateAlertAcknowledged }], { cancelable: false }, ); diff --git a/native/account/registration/registration-server-call.js b/native/account/registration/registration-server-call.js --- a/native/account/registration/registration-server-call.js +++ b/native/account/registration/registration-server-call.js @@ -1,7 +1,6 @@ // @flow import * as React from 'react'; -import { Platform } from 'react-native'; import { useDispatch } from 'react-redux'; import { setDataLoadedActionType } from 'lib/actions/client-db-store-actions.js'; @@ -25,6 +24,7 @@ import { NavContext } from '../../navigation/navigation-context.js'; import { useSelector } from '../../redux/redux-utils.js'; import { nativeLogInExtraInfoSelector } from '../../selectors/account-selectors.js'; +import { appOutOfDateAlert } from '../../utils/alert-messages.js'; import Alert from '../../utils/alert.js'; import { setNativeCredentials } from '../native-credentials.js'; import { useSIWEServerCall } from '../siwe-hooks.js'; @@ -103,15 +103,8 @@ 'An account with that username already exists', ); } else if (e.message === 'client_version_unsupported') { - const app = Platform.select({ - ios: 'App Store', - android: 'Play Store', - }); - Alert.alert( - 'App out of date', - 'Your app version is pretty old, and the server doesn’t know how ' + - `to speak to it anymore. Please use the ${app} app to update!`, - ); + const alertDetails = appOutOfDateAlert(); + Alert.alert(alertDetails.title, alertDetails.message); } else { Alert.alert('Unknown error', 'Uhh... try again?'); } diff --git a/native/components/version-supported.react.js b/native/components/version-supported.react.js new file mode 100644 --- /dev/null +++ b/native/components/version-supported.react.js @@ -0,0 +1,66 @@ +// @flow + +import * as React from 'react'; +import { useSelector } from 'react-redux'; + +import { useLogOut, logOutActionTypes } from 'lib/actions/user-actions.js'; +import { preRequestUserStateForSingleKeyserverSelector } from 'lib/selectors/account-selectors.js'; +import { isLoggedIn } from 'lib/selectors/user-selectors.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; +import { ashoatKeyserverID } from 'lib/utils/validation-utils.js'; + +import { commRustModule } from '../native-modules.js'; +import { appOutOfDateAlert } from '../utils/alert-messages.js'; +import Alert from '../utils/alert.js'; + +function VersionSupportedChecker(): React.Node { + const hasRun = React.useRef(false); + + const loggedIn = useSelector(isLoggedIn); + const preRequestUserState = useSelector( + preRequestUserStateForSingleKeyserverSelector(ashoatKeyserverID), + ); + const dispatchActionPromise = useDispatchActionPromise(); + const callLogOut = useLogOut(); + + const onUsernameAlertAcknowledged = React.useCallback(() => { + if (loggedIn) { + dispatchActionPromise(logOutActionTypes, callLogOut(preRequestUserState)); + } + }, [callLogOut, dispatchActionPromise, loggedIn, preRequestUserState]); + + const checkVersionSupport = React.useCallback(async () => { + try { + const isVersionSupported = await commRustModule.versionSupported(); + if (isVersionSupported) { + return; + } + const alertDetails = appOutOfDateAlert(); + Alert.alert( + alertDetails.title, + alertDetails.message, + [ + { + text: 'OK', + onPress: onUsernameAlertAcknowledged, + }, + ], + { cancelable: false }, + ); + } catch (error) { + console.error('Error checking version:', error); + } + }, [onUsernameAlertAcknowledged]); + + React.useEffect(() => { + if (hasRun.current) { + return; + } + hasRun.current = true; + checkVersionSupport(); + }, [checkVersionSupport]); + + return null; +} + +export default VersionSupportedChecker; diff --git a/native/redux/redux-setup.js b/native/redux/redux-setup.js --- a/native/redux/redux-setup.js +++ b/native/redux/redux-setup.js @@ -1,6 +1,6 @@ // @flow -import { AppState as NativeAppState, Platform, Alert } from 'react-native'; +import { AppState as NativeAppState, Alert } from 'react-native'; import { createStore, applyMiddleware, type Store, compose } from 'redux'; import { persistStore, persistReducer } from 'redux-persist'; import thunk from 'redux-thunk'; @@ -46,6 +46,7 @@ import { getGlobalNavContext } from '../navigation/icky-global.js'; import { activeMessageListSelector } from '../navigation/nav-selectors.js'; import reactotron from '../reactotron.js'; +import { appOutOfDateAlert } from '../utils/alert-messages.js'; import { isStaffRelease } from '../utils/staff-utils.js'; import { setCustomServer, getDevServerHostname } from '../utils/url-utils.js'; @@ -264,17 +265,10 @@ return; } if (payload.error === 'client_version_unsupported') { - const app = Platform.select({ - ios: 'App Store', - android: 'Play Store', + const alertDetails = appOutOfDateAlert(); + Alert.alert(alertDetails.title, alertDetails.message, [{ text: 'OK' }], { + cancelable: true, }); - Alert.alert( - 'App out of date', - 'Your app version is pretty old, and the server doesn’t know how to ' + - `speak to it anymore. Please use the ${app} app to update!`, - [{ text: 'OK' }], - { cancelable: true }, - ); } else { Alert.alert( 'Session invalidated', diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -35,6 +35,7 @@ import MessageEditingContextProvider from './chat/message-editing-context-provider.react.js'; import { FeatureFlagsProvider } from './components/feature-flags-provider.react.js'; import PersistedStateGate from './components/persisted-state-gate.js'; +import VersionSupportedChecker from './components/version-supported.react.js'; import ConnectedStatusBar from './connected-status-bar.react.js'; import { SQLiteDataHandler } from './data/sqlite-data-handler.js'; import ErrorBoundary from './error-boundary.react.js'; @@ -308,6 +309,7 @@ detectUnsupervisedBackgroundRef } /> + {navigation} diff --git a/native/utils/alert-messages.js b/native/utils/alert-messages.js new file mode 100644 --- /dev/null +++ b/native/utils/alert-messages.js @@ -0,0 +1,21 @@ +// @flow + +import { Platform } from 'react-native'; + +type AlertDetails = { + title: string, + message: string, +}; + +export function appOutOfDateAlert(): AlertDetails { + const app = Platform.select({ + ios: 'App Store', + android: 'Play Store', + }); + return { + title: 'App out of date', + message: + 'Your app version is pretty old, and the server doesn’t know how ' + + `to speak to it anymore. Please use the ${app} app to update!`, + }; +}