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 { AppOutOfDateAlertDetails } 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,9 @@ { cancelable: false }, ); } 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!`, + AppOutOfDateAlertDetails.title, + AppOutOfDateAlertDetails.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 { AppOutOfDateAlertDetails } 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,9 @@ { cancelable: false }, ); } 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!`, + AppOutOfDateAlertDetails.title, + AppOutOfDateAlertDetails.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 { AppOutOfDateAlertDetails } from '../../utils/alert-messages.js'; import Alert from '../../utils/alert.js'; import { setNativeCredentials } from '../native-credentials.js'; import { useSIWEServerCall } from '../siwe-hooks.js'; @@ -103,14 +103,9 @@ '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!`, + AppOutOfDateAlertDetails.title, + AppOutOfDateAlertDetails.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,65 @@ +// @flow + +import * as React from 'react'; + +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 { useSelector } from '../redux/redux-utils.js'; +import { AppOutOfDateAlertDetails } 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; + } + Alert.alert( + AppOutOfDateAlertDetails.title, + AppOutOfDateAlertDetails.message, + [ + { + text: 'OK', + onPress: onUsernameAlertAcknowledged, + }, + ], + { cancelable: false }, + ); + } catch (error) { + console.log('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 { AppOutOfDateAlertDetails } from '../utils/alert-messages.js'; import { isStaffRelease } from '../utils/staff-utils.js'; import { setCustomServer, getDevServerHostname } from '../utils/url-utils.js'; @@ -266,16 +267,13 @@ return; } if (payload.error === '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!`, + AppOutOfDateAlertDetails.title, + AppOutOfDateAlertDetails.message, [{ text: 'OK' }], - { cancelable: true }, + { + cancelable: true, + }, ); } else { Alert.alert( 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,20 @@ +// @flow + +import { Platform } from 'react-native'; + +type AlertDetails = { + +title: string, + +message: string, +}; + +const platformStore = Platform.select({ + ios: 'App Store', + android: 'Play Store', +}); + +export const AppOutOfDateAlertDetails: AlertDetails = { + 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 ${platformStore} to update!`, +};