diff --git a/packages/mobile/app.json b/packages/mobile/app.json index fc7d73f3d2..7b7cd51c09 100644 --- a/packages/mobile/app.json +++ b/packages/mobile/app.json @@ -57,6 +57,12 @@ "configureAndroidBackup": true, "faceIDPermission": "Allow $(PRODUCT_NAME) to access your Face ID biometric data." } + ], + [ + "expo-camera", + { + "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera" + } ] ], "experiments": { diff --git a/packages/mobile/app/_layout.tsx b/packages/mobile/app/_layout.tsx index 3097fad341..cb6a3907ca 100644 --- a/packages/mobile/app/_layout.tsx +++ b/packages/mobile/app/_layout.tsx @@ -155,6 +155,10 @@ export default function RootLayout() { }} > + diff --git a/packages/mobile/app/onboarding/camera-scan.tsx b/packages/mobile/app/onboarding/camera-scan.tsx new file mode 100644 index 0000000000..e8d728a117 --- /dev/null +++ b/packages/mobile/app/onboarding/camera-scan.tsx @@ -0,0 +1,195 @@ +import MaskedView from "@react-native-masked-view/masked-view"; +import { CameraView, FocusMode } from "expo-camera"; +import { useState } from "react"; +import { Dimensions, StyleSheet, TouchableOpacity, View } from "react-native"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; + +import { RouteHeader } from "~/components/route-header"; +import { Text } from "~/components/ui/text"; +import { Colors } from "~/constants/theme-colors"; + +const SCAN_ICON_RADIUS_RATIO = 0.05; +const SCAN_ICON_MASK_OFFSET_RATIO = 0.02; // used for mask to match spacing in CameraScan SVG +const CAMERA_ASPECT_RATIO = 4 / 3; +const SCAN_ICON_WIDTH_RATIO = 0.7; + +export default function Welcome() { + const { top } = useSafeAreaInsets(); + const [autoFocus, setAutoFocus] = useState("off"); + + const resetCameraAutoFocus = () => { + const abortController = new AbortController(); + setAutoFocus("off"); + setTimeout(() => { + if (!abortController.signal.aborted) { + setAutoFocus("on"); + } + }, 100); + return () => abortController.abort(); + }; + + const overlayWidth = Dimensions.get("window").height / CAMERA_ASPECT_RATIO; + const cameraWidth = Dimensions.get("window").width; + const cameraHeight = CAMERA_ASPECT_RATIO * cameraWidth; + const scannerSize = + Math.min(overlayWidth, cameraWidth) * SCAN_ICON_WIDTH_RATIO; + + return ( + + + + + Scan to Connect + + + + + + + } + > + { + console.log(data); + }} + /> + + + + + + + + + + + Scan your QR Code + + With your wallet connected, navigate{"\n"} + to 'Profile' > 'Link mobile device' on{"\n"} + Osmosis web app. + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + camera: { + flex: 1, + }, + overlay: { + flex: 1, + alignItems: "center", + justifyContent: "center", + }, + scanArea: { + backgroundColor: "transparent", + borderRadius: 24, + position: "relative", + }, + cornerTopLeft: { + position: "absolute", + top: 0, + left: 0, + width: 60, + height: 60, + borderTopWidth: 2, + borderLeftWidth: 2, + borderColor: "white", + borderTopLeftRadius: 32, + }, + cornerTopRight: { + position: "absolute", + top: 0, + right: 0, + width: 60, + height: 60, + borderTopWidth: 2, + borderRightWidth: 2, + borderColor: "white", + borderTopRightRadius: 32, + }, + cornerBottomLeft: { + position: "absolute", + bottom: 0, + left: 0, + width: 60, + height: 60, + borderBottomWidth: 2, + borderLeftWidth: 2, + borderColor: "white", + borderBottomLeftRadius: 32, + }, + cornerBottomRight: { + position: "absolute", + bottom: 0, + right: 0, + width: 60, + height: 60, + borderBottomWidth: 2, + borderRightWidth: 2, + borderColor: "white", + borderBottomRightRadius: 32, + }, + scanText: { + color: "white", + fontSize: 24, + fontWeight: "600", + marginBottom: 16, + }, + instructionText: { + color: Colors.osmoverse[300], + fontSize: 16, + textAlign: "center", + lineHeight: 24, + }, +}); diff --git a/packages/mobile/app/onboarding/enable-qr-code.tsx b/packages/mobile/app/onboarding/enable-qr-code.tsx new file mode 100644 index 0000000000..a0f92ffe76 --- /dev/null +++ b/packages/mobile/app/onboarding/enable-qr-code.tsx @@ -0,0 +1,121 @@ +import * as Linking from "expo-linking"; +import React from "react"; +import { Image, StyleSheet, View } from "react-native"; +import { SafeAreaView } from "react-native-safe-area-context"; + +import { RouteHeader } from "~/components/route-header"; +import { Text } from "~/components/ui/text"; + +import { Button } from "../../components/ui/button"; +import { Colors } from "../../constants/theme-colors"; + +export default function LinkViaDesktop() { + const handleOpenSettings = () => { + Linking.openSettings(); + }; + + const handleConnectManually = () => { + // TODO: Implement manual connection flow + console.log("Connect manually pressed"); + }; + + return ( + + + + + Link via Desktop + + + + + + + + + To Connect via QR Code, you need to allow access to the camera through + the iPhone settings and connect using QR code. + + + +