diff --git a/native/account/qr-auth/connect-secondary-device.react.js b/native/account/qr-auth/connect-secondary-device.react.js
new file mode 100644
--- /dev/null
+++ b/native/account/qr-auth/connect-secondary-device.react.js
@@ -0,0 +1,73 @@
+// @flow
+
+import invariant from 'invariant';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { QRAuthContext } from './qr-auth-context.js';
+import type { QRAuthNavigationProp } from './qr-auth-navigator.react.js';
+import RegistrationButtonContainer from '../../account/registration/registration-button-container.react.js';
+import RegistrationContainer from '../../account/registration/registration-container.react.js';
+import RegistrationContentContainer from '../../account/registration/registration-content-container.react.js';
+import PrimaryButton from '../../components/primary-button.react.js';
+import { type NavigationRoute } from '../../navigation/route-names.js';
+import { useStyles } from '../../themes/colors.js';
+
+export type ConnectSecondaryDeviceParams = {
+ +data: string,
+};
+
+type Props = {
+ +navigation: QRAuthNavigationProp<'ConnectSecondaryDevice'>,
+ +route: NavigationRoute<'ConnectSecondaryDevice'>,
+};
+
+function ConnectSecondaryDevice(props: Props): React.Node {
+ const { route } = props;
+ const data = route.params?.data;
+
+ const styles = useStyles(unboundStyles);
+
+ const qrAuthContext = React.useContext(QRAuthContext);
+ invariant(qrAuthContext, 'qrAuthContext should be set');
+ const { onConnect, connectingInProgress } = qrAuthContext;
+
+ const onPressConnect = React.useCallback(() => {
+ void onConnect(data);
+ }, [data, onConnect]);
+
+ return (
+
+
+ Connect with this device?
+
+ Are you sure you want to allow this device to log in to your account?
+
+
+
+
+
+
+ );
+}
+
+const unboundStyles = {
+ header: {
+ fontSize: 24,
+ color: 'panelForegroundLabel',
+ paddingBottom: 16,
+ },
+ body: {
+ fontFamily: 'Arial',
+ fontSize: 15,
+ lineHeight: 20,
+ color: 'panelForegroundSecondaryLabel',
+ paddingBottom: 16,
+ },
+};
+
+export default ConnectSecondaryDevice;
diff --git a/native/account/qr-auth/qr-auth-context-provider.js b/native/account/qr-auth/qr-auth-context-provider.js
--- a/native/account/qr-auth/qr-auth-context-provider.js
+++ b/native/account/qr-auth/qr-auth-context-provider.js
@@ -43,6 +43,7 @@
const aes256Key = React.useRef(null);
const secondaryDeviceID = React.useRef(null);
const secondaryDeviceType = React.useRef(null);
+ const [connectingInProgress, setConnectingInProgress] = React.useState(false);
const ownPeerDevices = useSelector(getOwnPeerDevices);
const keyserverDeviceID = getKeyserverDeviceID(ownPeerDevices);
@@ -90,6 +91,8 @@
return;
}
+ setConnectingInProgress(false);
+
Alert.alert('Device added', 'Device registered successfully', [
{ text: 'OK', onPress: goBack },
]);
@@ -189,6 +192,7 @@
],
);
} catch (err) {
+ setConnectingInProgress(false);
console.log('Primary device error:', err);
Alert.alert('Adding device failed', 'Failed to update the device list', [
{ text: 'OK' },
@@ -205,6 +209,8 @@
const onConnect = React.useCallback(
async (data: string) => {
+ setConnectingInProgress(true);
+
const parsedData = parseDataFromDeepLink(data);
const keysMatch = parsedData?.data?.keys;
@@ -214,6 +220,7 @@
'QR code does not contain a valid pair of keys.',
[{ text: 'OK' }],
);
+ setConnectingInProgress(false);
return;
}
@@ -224,6 +231,7 @@
secondaryDeviceID.current = ed25519;
secondaryDeviceType.current = parsedData.data.deviceType;
} catch (err) {
+ setConnectingInProgress(false);
console.log('Failed to decode URI component:', err);
return;
}
@@ -236,8 +244,9 @@
const contextValue = React.useMemo(
() => ({
onConnect,
+ connectingInProgress,
}),
- [onConnect],
+ [onConnect, connectingInProgress],
);
return (
diff --git a/native/account/qr-auth/qr-auth-context.js b/native/account/qr-auth/qr-auth-context.js
--- a/native/account/qr-auth/qr-auth-context.js
+++ b/native/account/qr-auth/qr-auth-context.js
@@ -4,6 +4,7 @@
export type QRAuthContextType = {
+onConnect: (data: string) => Promise,
+ +connectingInProgress: boolean,
};
const QRAuthContext: React.Context =
diff --git a/native/account/qr-auth/qr-auth-navigator.react.js b/native/account/qr-auth/qr-auth-navigator.react.js
--- a/native/account/qr-auth/qr-auth-navigator.react.js
+++ b/native/account/qr-auth/qr-auth-navigator.react.js
@@ -7,11 +7,13 @@
import { createStackNavigator } from '@react-navigation/stack';
import * as React from 'react';
+import ConnectSecondaryDevice from './connect-secondary-device.react.js';
import { QRAuthContextProvider } from './qr-auth-context-provider.js';
import QRAuthNotPrimaryDevice from './qr-auth-not-primary-device.react.js';
import SecondaryDeviceQRCodeScanner from './secondary-device-qr-code-scanner.react.js';
import type { RootNavigationProp } from '../../navigation/root-navigator.react.js';
import {
+ ConnectSecondaryDeviceRouteName,
type NavigationRoute,
type QRAuthNavigatorParamList,
QRAuthNotPrimaryDeviceRouteName,
@@ -64,6 +66,10 @@
name={QRAuthNotPrimaryDeviceRouteName}
component={QRAuthNotPrimaryDevice}
/>
+
);
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
@@ -4,6 +4,7 @@
import type { ActionResultModalParams } from './action-result-modal.react.js';
import type { InviteLinkModalParams } from './invite-link-modal.react';
+import type { ConnectSecondaryDeviceParams } from '../account/qr-auth/connect-secondary-device.react.js';
import type { AvatarSelectionParams } from '../account/registration/avatar-selection.react.js';
import type { ConnectEthereumParams } from '../account/registration/connect-ethereum.react.js';
import type { ConnectFarcasterParams } from '../account/registration/connect-farcaster.react.js';
@@ -181,6 +182,7 @@
export const NUXTipOverlayBackdropRouteName = 'NUXTipOverlayBackdrop';
export const QRAuthNavigatorRouteName = 'QRAuthNavigator';
export const QRAuthNotPrimaryDeviceRouteName = 'QRAuthNotPrimaryDevice';
+export const ConnectSecondaryDeviceRouteName = 'ConnectSecondaryDevice';
export type RootParamList = {
+LoggedOutModal: void,
@@ -356,6 +358,7 @@
export type QRAuthNavigatorParamList = {
+SecondaryDeviceQRCodeScanner: void,
+QRAuthNotPrimaryDevice: void,
+ +ConnectSecondaryDevice: ConnectSecondaryDeviceParams,
};
export type ScreenParamList = {