Skip to content

Commit

Permalink
feat: layout for onboarding
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseRFelix committed Dec 30, 2024
1 parent 5ef7a48 commit feacfd2
Show file tree
Hide file tree
Showing 18 changed files with 927 additions and 371 deletions.
6 changes: 6 additions & 0 deletions packages/mobile/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
4 changes: 4 additions & 0 deletions packages/mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ export default function RootLayout() {
}}
>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen
name="onboarding"
options={{ headerShown: false }}
/>
<Stack.Screen name="+not-found" />
</Stack>
</BottomSheetModalProvider>
Expand Down
195 changes: 195 additions & 0 deletions packages/mobile/app/onboarding/camera-scan.tsx
Original file line number Diff line number Diff line change
@@ -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<FocusMode>("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 (
<View style={{ flex: 1, backgroundColor: "rgba(0, 0, 0, 0.7)" }}>
<View
style={{
paddingHorizontal: 24,
paddingTop: 12,
backgroundColor: "rgba(0, 0, 0, 1)",
}}
>
<RouteHeader>
<Text
style={{
fontSize: 20,
fontWeight: "600",
}}
>
Scan to Connect
</Text>
</RouteHeader>
</View>
<MaskedView
style={{ flex: 1 }}
maskElement={
<View
style={{
backgroundColor: "rgba(0, 0, 0, 0.2)",
flex: 1,
justifyContent: "center",
alignItems: "center",
position: "relative",
}}
>
<View
style={{
backgroundColor: "#000",
borderRadius: 32,
width: scannerSize,
height: scannerSize,
position: "relative",
}}
/>
</View>
}
>
<CameraView
style={{ flex: 1 }}
onBarcodeScanned={({ data }) => {
console.log(data);
}}
/>
<View
style={{
position: "absolute",
width: scannerSize,
height: scannerSize,
top: "50%",
left: "50%",
transform: [
{ translateX: -scannerSize / 2 },
{ translateY: -scannerSize / 2 },
],
}}
>
<View style={{ position: "relative", flex: 1 }}>
<View style={styles.cornerTopLeft} />
<View style={styles.cornerTopRight} />
<View style={styles.cornerBottomLeft} />
<View style={styles.cornerBottomRight} />
</View>
</View>
<TouchableOpacity
style={StyleSheet.absoluteFill}
onPress={resetCameraAutoFocus}
/>
</MaskedView>
<Text style={styles.scanText}>Scan your QR Code</Text>
<Text style={styles.instructionText}>
With your wallet connected, navigate{"\n"}
to &apos;Profile&apos; &gt; &apos;Link mobile device&apos; on{"\n"}
Osmosis web app.
</Text>
</View>
);
}

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,
},
});
121 changes: 121 additions & 0 deletions packages/mobile/app/onboarding/enable-qr-code.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<SafeAreaView style={styles.container}>
<View style={{ paddingHorizontal: 24, paddingTop: 12 }}>
<RouteHeader>
<Text
style={{
fontSize: 20,
fontWeight: "600",
}}
>
Link via Desktop
</Text>
</RouteHeader>
</View>

<View style={styles.content}>
<Image
source={require("~/assets/images/qr-code-connection.png")}
style={styles.illustration}
resizeMode="contain"
/>

<Text style={styles.description}>
To Connect via QR Code, you need to allow access to the camera through
the iPhone settings and connect using QR code.
</Text>

<View style={styles.buttonContainer}>
<Button
buttonStyle={styles.button}
onPress={handleOpenSettings}
title="Open Settings"
textStyle={styles.buttonLabel}
/>
<Button
buttonStyle={styles.manualButton}
onPress={handleConnectManually}
title="Connect Manually"
textStyle={styles.manualButtonLabel}
variant="outline"
/>
</View>

<Text style={styles.alternateText}>
Or you can connect manually with your desktop account using your
pairing code.
</Text>
</View>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.osmoverse[1000],
},
content: {
flex: 1,
alignItems: "center",
paddingHorizontal: 24,
paddingTop: 40,
},
illustration: {
width: "100%",
height: 258,
marginBottom: 40,
},
description: {
fontSize: 16,
textAlign: "center",
marginBottom: 32,
lineHeight: 24,
},
buttonContainer: {
width: "100%",
gap: 12,
marginBottom: 24,
},
button: {
width: "100%",
},
buttonLabel: {
fontSize: 16,
fontWeight: "600",
},
manualButton: {
width: "100%",
},
manualButtonLabel: {
fontSize: 16,
color: Colors.osmoverse[100],
},
alternateText: {
fontSize: 14,
color: Colors.osmoverse[300],
textAlign: "center",
paddingHorizontal: 32,
},
});
24 changes: 0 additions & 24 deletions packages/mobile/app/onboarding/security.tsx

This file was deleted.

Loading

0 comments on commit feacfd2

Please sign in to comment.