diff --git a/native/account/registration/missing-registration-data/missing-registration-data-handler.react.js b/native/account/registration/missing-registration-data/missing-registration-data-handler.react.js new file mode 100644 --- /dev/null +++ b/native/account/registration/missing-registration-data/missing-registration-data-handler.react.js @@ -0,0 +1,57 @@ +// @flow + +import { useNavigation } from '@react-navigation/native'; +import invariant from 'invariant'; +import * as React from 'react'; + +import { isLoggedIn } from 'lib/selectors/user-selectors.js'; +import { accountHasPassword } from 'lib/shared/account-utils.js'; + +import { commCoreModule } from '../../../native-modules.js'; +import { CreateMissingSIWEBackupMessageRouteName } from '../../../navigation/route-names.js'; +import { useSelector } from '../../../redux/redux-utils.js'; +import { RegistrationContext } from '../registration-context.js'; +import { enableSIWEBackupCreation } from '../registration-types.js'; + +function MissingRegistrationDataHandler(): React.Node { + const loggedIn = useSelector(isLoggedIn); + const navigation = useNavigation(); + const currentUserInfo = useSelector(state => state.currentUserInfo); + + const registrationContext = React.useContext(RegistrationContext); + invariant(registrationContext, 'registrationContext should be set'); + const { cachedSelections } = registrationContext; + + React.useEffect(() => { + if ( + !enableSIWEBackupCreation || + !loggedIn || + accountHasPassword(currentUserInfo) || + cachedSelections.siweBackupSecrets + ) { + return; + } + + void (async () => { + const nativeSIWEBackupSecrets = + await commCoreModule.getSIWEBackupSecrets(); + + if (nativeSIWEBackupSecrets) { + return; + } + + navigation.navigate<'CreateMissingSIWEBackupMessage'>({ + name: CreateMissingSIWEBackupMessageRouteName, + }); + })(); + }, [ + currentUserInfo, + loggedIn, + cachedSelections.siweBackupSecrets, + navigation, + ]); + + return null; +} + +export { MissingRegistrationDataHandler }; diff --git a/native/account/registration/missing-registration-data/missing-siwe-backup-message.react.js b/native/account/registration/missing-registration-data/missing-siwe-backup-message.react.js new file mode 100644 --- /dev/null +++ b/native/account/registration/missing-registration-data/missing-siwe-backup-message.react.js @@ -0,0 +1,59 @@ +// @flow + +import * as React from 'react'; +import { SafeAreaView } from 'react-native-safe-area-context'; + +import { type SIWEResult } from 'lib/types/siwe-types.js'; + +import { commCoreModule } from '../../../native-modules.js'; +import { type RootNavigationProp } from '../../../navigation/root-navigator.react.js'; +import { type NavigationRoute } from '../../../navigation/route-names.js'; +import { useStyles } from '../../../themes/colors.js'; +import { CreateSIWEBackupMessageBase } from '../siwe-backup-message-creation.react.js'; + +type Props = { + +navigation: RootNavigationProp<'CreateMissingSIWEBackupMessage'>, + +route: NavigationRoute<'CreateMissingSIWEBackupMessage'>, +}; + +function CreateMissingSIWEBackupMessage(props: Props): React.Node { + const styles = useStyles(unboundStyles); + const [siweBackupSecretsPersisted, setSIWEBackupSecretsPersisted] = + React.useState(false); + + const onSuccessfulWalletSignature = React.useCallback( + (result: SIWEResult) => { + void (async () => { + const { message, signature } = result; + await commCoreModule.setSIWEBackupSecrets({ message, signature }); + setSIWEBackupSecretsPersisted(true); + })(); + }, + [setSIWEBackupSecretsPersisted], + ); + + React.useEffect(() => { + if (siweBackupSecretsPersisted) { + props.navigation.goBack(); + } + }, [siweBackupSecretsPersisted, props]); + + return ( + + + + ); +} + +const safeAreaEdges = ['top']; +const unboundStyles = { + container: { + flex: 1, + backgroundColor: 'panelBackground', + justifyContent: 'space-between', + }, +}; + +export default CreateMissingSIWEBackupMessage; diff --git a/native/navigation/root-navigator.react.js b/native/navigation/root-navigator.react.js --- a/native/navigation/root-navigator.react.js +++ b/native/navigation/root-navigator.react.js @@ -54,8 +54,10 @@ KeyserverSelectionBottomSheetRouteName, ConnectFarcasterBottomSheetRouteName, TagFarcasterChannelNavigatorRouteName, + CreateMissingSIWEBackupMessageRouteName, } from './route-names.js'; import LoggedOutModal from '../account/logged-out-modal.react.js'; +import CreateMissingSIWEBackupMessage from '../account/registration/missing-registration-data/missing-siwe-backup-message.react.js'; import RegistrationNavigator from '../account/registration/registration-navigator.react.js'; import TermsAndPrivacyModal from '../account/terms-and-privacy-modal.react.js'; import ThreadPickerModal from '../calendar/thread-picker-modal.react.js'; @@ -297,6 +299,10 @@ name={TagFarcasterChannelNavigatorRouteName} component={TagFarcasterChannelNavigator} /> + ); } diff --git a/native/navigation/route-names.js b/native/navigation/route-names.js --- a/native/navigation/route-names.js +++ b/native/navigation/route-names.js @@ -123,6 +123,8 @@ export const CoolOrNerdModeSelectionRouteName = 'CoolOrNerdModeSelection'; export const ConnectEthereumRouteName = 'ConnectEthereum'; export const CreateSIWEBackupMessageRouteName = 'CreateSIWEBackupMessage'; +export const CreateMissingSIWEBackupMessageRouteName = + 'CreateMissingSIWEBackupMessage'; export const ExistingEthereumAccountRouteName = 'ExistingEthereumAccount'; export const ConnectFarcasterRouteName = 'ConnectFarcaster'; export const UsernameSelectionRouteName = 'UsernameSelection'; @@ -181,6 +183,7 @@ +KeyserverSelectionBottomSheet: KeyserverSelectionBottomSheetParams, +ConnectFarcasterBottomSheet: void, +TagFarcasterChannelNavigator: void, + +CreateMissingSIWEBackupMessage: void, }; export type MessageTooltipRouteNames = diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -39,6 +39,7 @@ import { TunnelbrokerProvider } from 'lib/tunnelbroker/tunnelbroker-context.js'; import { actionLogger } from 'lib/utils/action-logger.js'; +import { MissingRegistrationDataHandler } from './account/registration/missing-registration-data/missing-registration-data-handler.react.js'; import { RegistrationContextProvider } from './account/registration/registration-context-provider.react.js'; import NativeEditThreadAvatarProvider from './avatars/native-edit-thread-avatar-provider.react.js'; import BackupHandler from './backup/backup-handler.js'; @@ -299,6 +300,7 @@ + );