mirror of
https://github.com/selfxyz/self.git
synced 2026-02-08 13:25:59 -05:00
fix bugs, improve layouts, improve UX on tab selection
This commit is contained in:
77
app/App.tsx
77
app/App.tsx
@@ -1,22 +1,13 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
StyleSheet,
|
||||
useColorScheme,
|
||||
NativeModules,
|
||||
DeviceEventEmitter,
|
||||
TextInput,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
|
||||
import {
|
||||
Colors,
|
||||
DebugInstructions,
|
||||
Header,
|
||||
LearnMoreLinks,
|
||||
ReloadInstructions,
|
||||
} from 'react-native/Libraries/NewAppScreen';
|
||||
import Toast, { BaseToast, ErrorToast, SuccessToast, ToastProps } from 'react-native-toast-message';
|
||||
// @ts-ignore
|
||||
@@ -449,7 +440,7 @@ function App(): JSX.Element {
|
||||
|
||||
// setProofTime(response.duration);
|
||||
setGeneratingProof(false)
|
||||
setStep('proofGenerated');
|
||||
setStep(Steps.PROOF_GENERATED);
|
||||
} catch (err: any) {
|
||||
console.log('err', err);
|
||||
setError(
|
||||
@@ -540,47 +531,33 @@ function App(): JSX.Element {
|
||||
};
|
||||
|
||||
return (
|
||||
<YStack f={1}>
|
||||
<SafeAreaView style={backgroundStyle}>
|
||||
<StatusBar
|
||||
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
|
||||
backgroundColor={Colors.red}
|
||||
<YStack h="100%" w="100%">
|
||||
<YStack h="100%" w="100%">
|
||||
<MainScreen
|
||||
onStartCameraScan={startCameraScan}
|
||||
nfcScan={scan}
|
||||
passportData={passportData}
|
||||
disclosure={disclosure}
|
||||
handleDisclosureChange={handleDisclosureChange}
|
||||
address={address}
|
||||
setAddress={setAddress}
|
||||
generatingProof={generatingProof}
|
||||
handleProve={handleProve}
|
||||
step={step}
|
||||
mintText={mintText}
|
||||
proof={proof}
|
||||
proofTime={proofTime}
|
||||
handleMint={handleMint}
|
||||
totalTime={totalTime}
|
||||
setStep={setStep}
|
||||
passportNumber={passportNumber}
|
||||
setPassportNumber={setPassportNumber}
|
||||
dateOfBirth={dateOfBirth}
|
||||
setDateOfBirth={setDateOfBirth}
|
||||
dateOfExpiry={dateOfExpiry}
|
||||
setDateOfExpiry={setDateOfExpiry}
|
||||
/>
|
||||
<ScrollView
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
style={{
|
||||
backgroundColor: isDarkMode ? Colors.black : Colors.black,
|
||||
}}
|
||||
contentContainerStyle={{ flexGrow: 1 }}
|
||||
>
|
||||
<YStack style={styles.view}>
|
||||
<MainScreen
|
||||
onStartCameraScan={startCameraScan}
|
||||
nfcScan={scan}
|
||||
passportData={passportData}
|
||||
disclosure={disclosure}
|
||||
handleDisclosureChange={handleDisclosureChange}
|
||||
address={address}
|
||||
setAddress={setAddress}
|
||||
generatingProof={generatingProof}
|
||||
handleProve={handleProve}
|
||||
step={step}
|
||||
mintText={mintText}
|
||||
proof={proof}
|
||||
proofTime={proofTime}
|
||||
handleMint={handleMint}
|
||||
totalTime={totalTime}
|
||||
setStep={setStep}
|
||||
passportNumber={passportNumber}
|
||||
setPassportNumber={setPassportNumber}
|
||||
dateOfBirth={dateOfBirth}
|
||||
setDateOfBirth={setDateOfBirth}
|
||||
dateOfExpiry={dateOfExpiry}
|
||||
setDateOfExpiry={setDateOfExpiry}
|
||||
/>
|
||||
</YStack>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</YStack>
|
||||
<Toast config={toastConfig} />
|
||||
</YStack>
|
||||
);
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-private-methods": "^7.23.3",
|
||||
"@ethersproject/shims": "^5.7.0",
|
||||
"@tamagui/config": "^1.89.3",
|
||||
"@tamagui/core": "^1.89.3",
|
||||
"@tamagui/lucide-icons": "^1.89.3",
|
||||
"@tamagui/config": "^1.89.10",
|
||||
"@tamagui/core": "^1.89.10",
|
||||
"@tamagui/lucide-icons": "^1.89.10",
|
||||
"axios": "^1.6.3",
|
||||
"body-parser": "^1.20.2",
|
||||
"buffer": "^6.0.3",
|
||||
@@ -30,7 +30,7 @@
|
||||
"react-native-passport-reader": "^1.0.3",
|
||||
"react-native-svg": "13.4.0",
|
||||
"react-native-toast-message": "^2.2.0",
|
||||
"tamagui": "^1.89.3"
|
||||
"tamagui": "^1.89.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
@@ -58,4 +58,4 @@
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ interface AppCardProps {
|
||||
background: string | undefined;
|
||||
id: string | number;
|
||||
onTouchStart?: () => void;
|
||||
eleva?: string;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
const AppCard: React.FC<AppCardProps> = ({
|
||||
@@ -19,20 +19,20 @@ const AppCard: React.FC<AppCardProps> = ({
|
||||
background,
|
||||
id,
|
||||
onTouchStart,
|
||||
eleva
|
||||
selected
|
||||
}) => {
|
||||
return (
|
||||
<Card
|
||||
key={id}
|
||||
borderRadius="$10"
|
||||
elevation={eleva}
|
||||
elevation={0}
|
||||
onTouchStart={onTouchStart}
|
||||
shadowColor="black"
|
||||
bg="transparent"
|
||||
|
||||
>
|
||||
<XStack
|
||||
<XStack w="100%"
|
||||
>
|
||||
<Card.Header w="100%">
|
||||
<XStack w="100%" ai="center" py="$1" >
|
||||
<XStack ai="center" py="$1" >
|
||||
<YStack>
|
||||
<H3 color={colorOfTheText} selectable={false} >{title}</H3>
|
||||
<Text theme="alt2" color={colorOfTheText} selectable={false}>{description}</Text>
|
||||
@@ -41,15 +41,21 @@ const AppCard: React.FC<AppCardProps> = ({
|
||||
<ChevronRight size="$4" color={colorOfTheText} />
|
||||
</XStack>
|
||||
</Card.Header>
|
||||
{background && (
|
||||
<Card.Background>
|
||||
<Image
|
||||
{(
|
||||
<Card.Background
|
||||
animation="quick"
|
||||
borderColor={(selected) ? "#E0E0E0" : "transparent"}
|
||||
borderWidth={(selected) ? 4 : 0}
|
||||
borderRadius="$10"
|
||||
bg="#F0F0F0"
|
||||
|
||||
>
|
||||
{background && <Image
|
||||
flex={1}
|
||||
borderRadius="$10"
|
||||
source={{
|
||||
uri: background
|
||||
}}
|
||||
/>
|
||||
/>}
|
||||
</Card.Background>
|
||||
)}
|
||||
</XStack>
|
||||
|
||||
@@ -40,7 +40,7 @@ const AppScreen: React.FC<AppScreenProps> = ({ selectedApp, setSelectedApp }) =>
|
||||
];
|
||||
|
||||
return (
|
||||
<YStack gap="$5" w="100%" p="$5">
|
||||
<YStack gap="$5" px="$5" pt="$12">
|
||||
|
||||
{cardsData.map(card => (
|
||||
<AppCard
|
||||
@@ -51,7 +51,7 @@ const AppScreen: React.FC<AppScreenProps> = ({ selectedApp, setSelectedApp }) =>
|
||||
background={card.background}
|
||||
id={card.app.id}
|
||||
onTouchStart={() => handleCardSelect(card.app)}
|
||||
eleva={selectedApp && selectedApp.id === card.app.id ? "$0" : "$12"}
|
||||
selected={selectedApp && selectedApp.id === card.app.id ? true : false}
|
||||
/>
|
||||
))}
|
||||
|
||||
|
||||
313
app/src/screens/MainScreen copy.tsx
Normal file
313
app/src/screens/MainScreen copy.tsx
Normal file
@@ -0,0 +1,313 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { YStack, XStack, Text, Button, Tabs, styled, Dialog, Adapt, Sheet, Label, Fieldset, Input, Switch, ThemeableStack, Separator } from 'tamagui'
|
||||
import { Scan, UserCheck, HelpCircle, XCircle, IterationCw, LayoutGrid, Sparkles } from '@tamagui/lucide-icons';
|
||||
import ScanScreen from './ScanScreen';
|
||||
import ProveScreen from './ProveScreen';
|
||||
import { Steps } from '../utils/utils';
|
||||
import AppScreen from './AppScreen';
|
||||
import { App } from '../utils/AppClass';
|
||||
|
||||
|
||||
interface MainScreenProps {
|
||||
onStartCameraScan: () => void;
|
||||
nfcScan: () => void;
|
||||
passportData: any;
|
||||
disclosure: boolean;
|
||||
handleDisclosureChange: (disclosure: boolean) => void;
|
||||
address: string;
|
||||
setAddress: (address: string) => void;
|
||||
generatingProof: boolean;
|
||||
handleProve: () => void;
|
||||
step: number;
|
||||
mintText: string;
|
||||
proof: any;
|
||||
proofTime: number;
|
||||
handleMint: () => void;
|
||||
totalTime: number;
|
||||
setStep: (step: number) => void;
|
||||
passportNumber: string;
|
||||
setPassportNumber: (number: string) => void;
|
||||
dateOfBirth: string;
|
||||
setDateOfBirth: (date: string) => void;
|
||||
dateOfExpiry: string;
|
||||
setDateOfExpiry: (date: string) => void;
|
||||
}
|
||||
|
||||
const MainScreen: React.FC<MainScreenProps> = ({
|
||||
onStartCameraScan,
|
||||
nfcScan,
|
||||
passportData,
|
||||
disclosure,
|
||||
handleDisclosureChange,
|
||||
address,
|
||||
setAddress,
|
||||
generatingProof,
|
||||
handleProve,
|
||||
step,
|
||||
mintText,
|
||||
proof,
|
||||
proofTime,
|
||||
handleMint,
|
||||
totalTime,
|
||||
setStep,
|
||||
passportNumber,
|
||||
setPassportNumber,
|
||||
dateOfBirth,
|
||||
setDateOfBirth,
|
||||
dateOfExpiry,
|
||||
setDateOfExpiry
|
||||
}) => {
|
||||
|
||||
const [selectedTab, setSelectedTab] = useState("scan");
|
||||
const [selectedApp, setSelectedApp] = useState<App | null>(null);
|
||||
const [brokenCamera, setBrokenCamera] = useState(false);
|
||||
const [open, setOpen] = useState(false)
|
||||
const AppCard = styled(ThemeableStack, {
|
||||
hoverTheme: true,
|
||||
pressTheme: true,
|
||||
focusTheme: true,
|
||||
elevate: true
|
||||
})
|
||||
const handleRestart = () => {
|
||||
setStep(Steps.MRZ_SCAN);
|
||||
setSelectedApp(null)
|
||||
setPassportNumber("");
|
||||
setDateOfBirth("");
|
||||
setDateOfExpiry("");
|
||||
|
||||
}
|
||||
const handleSkip = () => {
|
||||
setStep(Steps.NFC_SCAN_COMPLETED);
|
||||
setPassportNumber("");
|
||||
setDateOfBirth("");
|
||||
setDateOfExpiry("");
|
||||
|
||||
}
|
||||
useEffect(() => {
|
||||
// Check if length of each field is correct and move to step MRZ_SCAN_COMPLETED if so
|
||||
if (passportNumber?.length === 9 && (dateOfBirth?.length === 6 && dateOfExpiry?.length === 6)) {
|
||||
setStep(Steps.MRZ_SCAN_COMPLETED);
|
||||
}
|
||||
}, [passportNumber, dateOfBirth, dateOfExpiry]);
|
||||
|
||||
return (
|
||||
<YStack f={1} bc="white">
|
||||
|
||||
<YStack >
|
||||
<XStack jc="space-between" ai="center" p="$2">
|
||||
<XStack w="33%" ></XStack>
|
||||
|
||||
<Text w="33%">
|
||||
{selectedTab === "scan" ? "Scan" : (selectedTab === "app" ? "Apps" : "Prove")}
|
||||
</Text>
|
||||
|
||||
<Dialog
|
||||
modal
|
||||
>
|
||||
<Dialog.Trigger p="$2">
|
||||
<HelpCircle />
|
||||
</Dialog.Trigger>
|
||||
|
||||
<Adapt when="sm" platform="touch">
|
||||
<Sheet animation="medium" zIndex={200000} modal dismissOnSnapToBottom>
|
||||
<Sheet.Frame padding="$4" gap="$4">
|
||||
<Adapt.Contents />
|
||||
</Sheet.Frame>
|
||||
<Sheet.Overlay
|
||||
animation="lazy"
|
||||
enterStyle={{ opacity: 0 }}
|
||||
exitStyle={{ opacity: 0 }}
|
||||
/>
|
||||
</Sheet>
|
||||
</Adapt>
|
||||
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay
|
||||
key="overlay"
|
||||
animation="quick"
|
||||
opacity={0.5}
|
||||
enterStyle={{ opacity: 0 }}
|
||||
exitStyle={{ opacity: 0 }}
|
||||
/>
|
||||
|
||||
<Dialog.Content
|
||||
bordered
|
||||
elevate
|
||||
key="content"
|
||||
animateOnly={['transform', 'opacity']}
|
||||
animation={[
|
||||
'quick',
|
||||
{
|
||||
opacity: {
|
||||
overshootClamping: true,
|
||||
},
|
||||
},
|
||||
]}
|
||||
enterStyle={{ x: 0, y: -20, opacity: 0, scale: 0.9 }}
|
||||
exitStyle={{ x: 0, y: 10, opacity: 0, scale: 0.95 }}
|
||||
gap="$4"
|
||||
>
|
||||
<XStack >
|
||||
<Dialog.Title>Settings</Dialog.Title>
|
||||
|
||||
</XStack>
|
||||
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={200} justifyContent="flex-end" htmlFor="restart" fow="bold">
|
||||
Restart to step 1
|
||||
</Label>
|
||||
<Button size="$4" m="$2" onPress={handleRestart}>
|
||||
<IterationCw />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
|
||||
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={200} justifyContent="flex-end" htmlFor="skip" fow="bold">
|
||||
Use mock passport data
|
||||
</Label>
|
||||
<Button size="$4" m="$2" onPress={handleSkip}>
|
||||
<Sparkles />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={205} justifyContent="flex-end" htmlFor="name" fow="bold">
|
||||
Broken camera
|
||||
</Label>
|
||||
<Switch size="$4" checked={brokenCamera} onCheckedChange={setBrokenCamera}>
|
||||
<Switch.Thumb animation="bouncy" backgroundColor="white" color />
|
||||
</Switch>
|
||||
</Fieldset>
|
||||
{
|
||||
brokenCamera &&
|
||||
<YStack pl="$3">
|
||||
<Fieldset gap="$4" horizontal>
|
||||
<Label width={160} justifyContent="flex-end" htmlFor="name">
|
||||
Passport Number
|
||||
</Label>
|
||||
<Input borderColor={passportNumber?.length === 9 ? "green" : "unset"} flex={1} id="passport_number" onChangeText={(text) => setPassportNumber(text.toUpperCase())} value={passportNumber} keyboardType="default" />
|
||||
</Fieldset>
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={160} justifyContent="flex-end" htmlFor="name">
|
||||
Date of birth (yymmdd)
|
||||
</Label>
|
||||
<Input borderColor={dateOfBirth?.length === 6 ? "green" : "unset"} flex={1} id="date_of_birth" onChangeText={setDateOfBirth} value={dateOfBirth} keyboardType="numeric" />
|
||||
</Fieldset>
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={160} justifyContent="flex-end" htmlFor="name">
|
||||
Date of expiry (yymmdd)
|
||||
</Label>
|
||||
<Input borderColor={dateOfExpiry?.length === 6 ? "green" : "unset"} flex={1} id="date_of_expiry" onChangeText={setDateOfExpiry} value={dateOfExpiry} keyboardType="numeric" />
|
||||
</Fieldset>
|
||||
</YStack>
|
||||
}
|
||||
<YStack flex={1}>
|
||||
<YStack flex={1}></YStack>
|
||||
<Dialog.Close mb="$4" displayWhenAdapted alignSelf='center'>
|
||||
<XCircle size="$3" />
|
||||
</Dialog.Close>
|
||||
|
||||
</YStack>
|
||||
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog>
|
||||
</XStack>
|
||||
|
||||
<YStack w="100%" h={2} backgroundColor="#DCDCDC" opacity={0.16}></YStack>
|
||||
</YStack>
|
||||
|
||||
|
||||
<Tabs f={1} orientation="horizontal" flexDirection="column" defaultValue="scan" onValueChange={setSelectedTab}>
|
||||
<Tabs.Content value="scan" f={1}>
|
||||
<ScanScreen
|
||||
onStartCameraScan={onStartCameraScan}
|
||||
nfcScan={nfcScan}
|
||||
step={step} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="app" f={1}>
|
||||
<AppScreen
|
||||
selectedApp={selectedApp}
|
||||
setSelectedApp={setSelectedApp} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="generate" f={1}>
|
||||
<ProveScreen
|
||||
passportData={passportData}
|
||||
disclosure={disclosure}
|
||||
selectedApp={selectedApp}
|
||||
handleDisclosureChange={handleDisclosureChange}
|
||||
address={address}
|
||||
setAddress={setAddress}
|
||||
generatingProof={generatingProof}
|
||||
handleProve={handleProve}
|
||||
step={step}
|
||||
mintText={mintText}
|
||||
proof={proof}
|
||||
proofTime={proofTime}
|
||||
handleMint={handleMint}
|
||||
totalTime={totalTime} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Separator />
|
||||
<Tabs.List separator={<Separator vertical />}
|
||||
|
||||
pt="$4" pb="$3">
|
||||
|
||||
<Tabs.Tab value="scan" unstyled w="33%">
|
||||
<YStack ai="center">
|
||||
<Scan color='black' />
|
||||
<Text color='black'>Scan</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab value="app" unstyled w="33%">
|
||||
<YStack ai="center" >
|
||||
<LayoutGrid color="black" />
|
||||
<Text color="black">Apps</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab value="generate" unstyled w="33%">
|
||||
<YStack ai="center">
|
||||
<UserCheck color='black' />
|
||||
<Text color='black'>Prove</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
|
||||
</Tabs.List>
|
||||
</Tabs>
|
||||
|
||||
{/*
|
||||
|
||||
<XStack justifyContent='space-between'>
|
||||
|
||||
<Button h="$5" w="33%" unstyled bg="blue" jc='center' ai='center'>
|
||||
<YStack>
|
||||
<Scan color='black' mt={3} />
|
||||
<Text>Scan</Text>
|
||||
</YStack>
|
||||
</Button>
|
||||
<Button h="$5" w="33%" unstyled bg="blue" jc='center' ai='center'>
|
||||
<YStack>
|
||||
<Scan color='black' mt={3} />
|
||||
<Text>Scan</Text>
|
||||
</YStack>
|
||||
</Button>
|
||||
<Button h="$5" w="33%" unstyled bg="blue" jc='center' ai='center'>
|
||||
<YStack>
|
||||
<Scan color='black' mt={3} />
|
||||
<Text>Scan</Text>
|
||||
</YStack>
|
||||
</Button>
|
||||
</XStack>
|
||||
*/}
|
||||
|
||||
|
||||
</YStack >
|
||||
);
|
||||
};
|
||||
|
||||
export default MainScreen;
|
||||
@@ -1,11 +1,12 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { YStack, XStack, Text, Button, Tabs, styled, Dialog, Adapt, Sheet, Label, Fieldset, Input, Switch, ThemeableStack } from 'tamagui'
|
||||
import { YStack, XStack, Text, Button, Tabs, styled, Dialog, Adapt, Sheet, Label, Fieldset, Input, Switch, ThemeableStack, Separator } from 'tamagui'
|
||||
import { Scan, UserCheck, HelpCircle, XCircle, IterationCw, LayoutGrid, Sparkles } from '@tamagui/lucide-icons';
|
||||
import ScanScreen from './ScanScreen';
|
||||
import ProveScreen from './ProveScreen';
|
||||
import { Steps } from '../utils/utils';
|
||||
import AppScreen from './AppScreen';
|
||||
import { App } from '../utils/AppClass';
|
||||
import { Keyboard } from 'react-native';
|
||||
|
||||
|
||||
interface MainScreenProps {
|
||||
@@ -90,13 +91,30 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
}
|
||||
}, [passportNumber, dateOfBirth, dateOfExpiry]);
|
||||
|
||||
return (
|
||||
<YStack f={1} ai="center" jc="space-between" bc="#fff">
|
||||
const [keyboardVisible, setKeyboardVisible] = useState(false);
|
||||
|
||||
<YStack w="100%">
|
||||
<XStack w="100%" jc="space-between" ai="center" ph="$4" pv="$2" bc="#fff" p="$3">
|
||||
<XStack></XStack>
|
||||
<Text>
|
||||
useEffect(() => {
|
||||
const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
|
||||
setKeyboardVisible(true);
|
||||
});
|
||||
const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
|
||||
setKeyboardVisible(false);
|
||||
});
|
||||
|
||||
return () => {
|
||||
showSubscription.remove();
|
||||
hideSubscription.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<YStack f={1} bc="white">
|
||||
|
||||
<YStack >
|
||||
<XStack jc="space-between" ai="center" p="$2">
|
||||
<XStack w="33%" ></XStack>
|
||||
|
||||
<Text w="33%">
|
||||
{selectedTab === "scan" ? "Scan" : (selectedTab === "app" ? "Apps" : "Prove")}
|
||||
</Text>
|
||||
|
||||
@@ -151,8 +169,8 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
|
||||
</XStack>
|
||||
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={160} justifyContent="flex-end" htmlFor="restart" fow="bold">
|
||||
<Fieldset gap="$4" mt="$6" horizontal>
|
||||
<Label width={200} justifyContent="flex-end" htmlFor="restart" fow="bold">
|
||||
Restart to step 1
|
||||
</Label>
|
||||
<Button size="$4" m="$2" onPress={handleRestart}>
|
||||
@@ -162,8 +180,8 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
|
||||
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={160} justifyContent="flex-end" htmlFor="skip" fow="bold">
|
||||
Enter mock passport data
|
||||
<Label width={200} justifyContent="flex-end" htmlFor="skip" fow="bold">
|
||||
Use mock passport data
|
||||
</Label>
|
||||
<Button size="$4" m="$2" onPress={handleSkip}>
|
||||
<Sparkles />
|
||||
@@ -171,7 +189,7 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset gap="$4" mt="$2" horizontal>
|
||||
<Label width={160} justifyContent="flex-end" htmlFor="name" fow="bold">
|
||||
<Label width={205} justifyContent="flex-end" htmlFor="name" fow="bold">
|
||||
Broken camera
|
||||
</Label>
|
||||
<Switch size="$4" checked={brokenCamera} onCheckedChange={setBrokenCamera}>
|
||||
@@ -180,7 +198,7 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
</Fieldset>
|
||||
{
|
||||
brokenCamera &&
|
||||
<YStack space pl="$3">
|
||||
<YStack pl="$3">
|
||||
<Fieldset gap="$4" horizontal>
|
||||
<Label width={160} justifyContent="flex-end" htmlFor="name">
|
||||
Passport Number
|
||||
@@ -212,95 +230,99 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog>
|
||||
|
||||
</XStack>
|
||||
<YStack w="100%" h={2} backgroundColor="#DCDCDC" opacity={0.16}></YStack>
|
||||
<Separator />
|
||||
</YStack>
|
||||
|
||||
|
||||
<Tabs f={1} defaultValue="scan" orientation='horizontal' dir='ltr' shadowColor="black" onValueChange={(newValue) => setSelectedTab(newValue)}>
|
||||
<YStack ai="center" jc="space-between" bc="" >
|
||||
<XStack flexGrow={0} ai="center" />
|
||||
<Tabs f={1} orientation="horizontal" flexDirection="column" defaultValue="scan" onValueChange={setSelectedTab}>
|
||||
<Tabs.Content value="scan" f={1}>
|
||||
<ScanScreen
|
||||
onStartCameraScan={onStartCameraScan}
|
||||
nfcScan={nfcScan}
|
||||
step={step} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="scan">
|
||||
<ScanScreen
|
||||
onStartCameraScan={onStartCameraScan}
|
||||
nfcScan={nfcScan}
|
||||
step={step} />
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="app">
|
||||
<AppScreen
|
||||
selectedApp={selectedApp}
|
||||
setSelectedApp={setSelectedApp}
|
||||
/>
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="generate">
|
||||
<ProveScreen
|
||||
passportData={passportData}
|
||||
disclosure={disclosure}
|
||||
selectedApp={selectedApp}
|
||||
handleDisclosureChange={handleDisclosureChange}
|
||||
address={address}
|
||||
setAddress={setAddress}
|
||||
generatingProof={generatingProof}
|
||||
handleProve={handleProve}
|
||||
step={step}
|
||||
mintText={mintText}
|
||||
proof={proof}
|
||||
proofTime={proofTime}
|
||||
handleMint={handleMint}
|
||||
totalTime={totalTime}
|
||||
/>
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="app" f={1}>
|
||||
<AppScreen
|
||||
selectedApp={selectedApp}
|
||||
setSelectedApp={setSelectedApp} />
|
||||
</Tabs.Content>
|
||||
|
||||
<YStack w="100%" backgroundColor="white">
|
||||
<YStack w="100%" h={2} backgroundColor="#DCDCDC" opacity={0.16}></YStack>
|
||||
<Tabs.Content value="generate" f={1}>
|
||||
<ProveScreen
|
||||
passportData={passportData}
|
||||
disclosure={disclosure}
|
||||
selectedApp={selectedApp}
|
||||
handleDisclosureChange={handleDisclosureChange}
|
||||
address={address}
|
||||
setAddress={setAddress}
|
||||
generatingProof={generatingProof}
|
||||
handleProve={handleProve}
|
||||
step={step}
|
||||
mintText={mintText}
|
||||
proof={proof}
|
||||
proofTime={proofTime}
|
||||
handleMint={handleMint}
|
||||
totalTime={totalTime} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.List w="100%" pt="$4" pb="$3">
|
||||
<Tabs.Tab unstyled value="scan" w="33%" backgroundColor="transparent" >
|
||||
<YStack ai="center">
|
||||
<Scan color={selectedTab === "scan" ? '#3185FC' : 'black'} />
|
||||
<Text color={selectedTab === "scan" ? '#3185FC' : 'black'}>Scan</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
<Separator />
|
||||
|
||||
{step < Steps.NFC_SCAN_COMPLETED ?
|
||||
<Tabs.Tab unstyled value="scan" w="33%" backgroundColor="transparent" >
|
||||
<YStack ai="center">
|
||||
<LayoutGrid color="#eeeeee" />
|
||||
<Text color="#eeeeee">Apps</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
:
|
||||
<Tabs.Tab unstyled value="app" w="33%" backgroundColor="transparent" >
|
||||
<YStack ai="center">
|
||||
<LayoutGrid color={selectedTab === "app" ? '#3185FC' : 'black'} />
|
||||
<Text color={selectedTab === "app" ? '#3185FC' : 'black'}>Apps</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
}
|
||||
{!keyboardVisible ? <Tabs.List separator={<Separator vertical />} pt="$4" pb="$3">
|
||||
|
||||
<Tabs.Tab value="scan" unstyled w="33%">
|
||||
<YStack ai="center">
|
||||
<Scan color={selectedTab === "scan" ? '#3185FC' : 'black'} />
|
||||
<Text color={selectedTab === "scan" ? '#3185FC' : 'black'}>Scan</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
|
||||
<Tabs.Tab value="app" unstyled w="33%">
|
||||
<YStack ai="center">
|
||||
<LayoutGrid color={selectedTab === "app" ? '#3185FC' : 'black'} />
|
||||
<Text color={selectedTab === "app" ? '#3185FC' : 'black'}>Apps</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
|
||||
{selectedApp === null ?
|
||||
<Tabs.Tab unstyled value={step < Steps.NFC_SCAN_COMPLETED ? "scan" : "app"} w="33%" backgroundColor="transparent">
|
||||
<YStack ai="center">
|
||||
<UserCheck color="#eeeeee" />
|
||||
<Text color="#eeeeee">Prove</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
:
|
||||
<Tabs.Tab unstyled value="generate" w="33%" backgroundColor="transparent">
|
||||
<YStack ai="center">
|
||||
<UserCheck color={selectedTab === "generate" ? '#3185FC' : 'black'} />
|
||||
<Text color={selectedTab === "generate" ? '#3185FC' : 'black'}>Prove</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
}
|
||||
</Tabs.List>
|
||||
<Tabs.Tab value="generate" unstyled w="33%">
|
||||
<YStack ai="center">
|
||||
<UserCheck color={selectedTab === "generate" ? '#3185FC' : 'black'} />
|
||||
<Text color={selectedTab === "generate" ? '#3185FC' : 'black'}>Prove</Text>
|
||||
</YStack>
|
||||
</Tabs.Tab>
|
||||
|
||||
</Tabs.List> : (<XStack />)}
|
||||
</Tabs>
|
||||
|
||||
{/*
|
||||
|
||||
// This component is WIP in case tamagui can't afford to deliver Tabs component without error on time
|
||||
|
||||
<XStack justifyContent='space-between'>
|
||||
|
||||
<Button h="$5" w="33%" unstyled bg="blue" jc='center' ai='center'>
|
||||
<YStack>
|
||||
<Scan color='black' mt={3} />
|
||||
<Text>Scan</Text>
|
||||
</YStack>
|
||||
</YStack>
|
||||
</Tabs >
|
||||
</Button>
|
||||
<Button h="$5" w="33%" unstyled bg="blue" jc='center' ai='center'>
|
||||
<YStack>
|
||||
<Scan color='black' mt={3} />
|
||||
<Text>Scan</Text>
|
||||
</YStack>
|
||||
</Button>
|
||||
<Button h="$5" w="33%" unstyled bg="blue" jc='center' ai='center'>
|
||||
<YStack>
|
||||
<Scan color='black' mt={3} />
|
||||
<Text>Scan</Text>
|
||||
</YStack>
|
||||
</Button>
|
||||
</XStack>
|
||||
*/}
|
||||
|
||||
|
||||
</YStack >
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { YStack, XStack, Text, Checkbox, Input, Button, Spinner, Image } from 'tamagui';
|
||||
import { Check } from '@tamagui/lucide-icons';
|
||||
import { YStack, XStack, Text, Checkbox, Input, Button, Spinner, Image, TextArea } from 'tamagui';
|
||||
import { Check, LayoutGrid, Scan, Sparkles } from '@tamagui/lucide-icons';
|
||||
import { getFirstName, formatDuration } from '../../utils/utils';
|
||||
import { attributeToPosition } from '../../../common/src/constants/constants';
|
||||
import { Steps } from '../utils/utils';
|
||||
@@ -44,24 +44,25 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
}) => {
|
||||
|
||||
return (
|
||||
<YStack space="$4" p="$4" >
|
||||
{
|
||||
step < Steps.PROOF_GENERATED ? (
|
||||
<YStack >
|
||||
<YStack w="100%" ai="center">
|
||||
<YStack px="$4" f={1} >
|
||||
{(step >= Steps.NFC_SCAN_COMPLETED && selectedApp != null) ?
|
||||
(step < Steps.PROOF_GENERATED ? (
|
||||
<YStack flex={1} m="$2" gap="$2">
|
||||
<XStack flex={1} />
|
||||
<YStack alignSelf='center'>
|
||||
<Image
|
||||
w="$12"
|
||||
h="$12"
|
||||
flex={1}
|
||||
borderRadius="$10"
|
||||
source={{
|
||||
uri: USER
|
||||
}}
|
||||
/>
|
||||
</YStack>
|
||||
<YStack mt="$12">
|
||||
<Text mb="$1">Hi {getFirstName(passportData.mrz)},</Text>
|
||||
<Text mb="$2">{selectedApp?.name} is asking for the following information:</Text>
|
||||
<XStack flex={1} />
|
||||
<YStack mt="$8">
|
||||
<Text mb="$1" fontWeight="bold">Hi {getFirstName(passportData.mrz)},</Text>
|
||||
<Text mb="$2">{selectedApp?.disclosurephrase}</Text>
|
||||
{selectedApp && Object.keys(selectedApp.disclosure).map((key) => {
|
||||
const key_ = key as keyof typeof disclosure;
|
||||
const indexes = attributeToPosition[key_];
|
||||
@@ -70,8 +71,7 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
const mrzAttributeFormatted = mrzAttribute.replace(/</g, ' ');
|
||||
|
||||
return (
|
||||
<XStack key={key} m="$2" w="$full" gap="$2">
|
||||
|
||||
<XStack key={key} m="$2" gap="$4">
|
||||
<Checkbox
|
||||
value={key}
|
||||
checked={disclosure[key_]}
|
||||
@@ -83,48 +83,75 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
<Check />
|
||||
</Checkbox.Indicator>
|
||||
</Checkbox>
|
||||
|
||||
<Text fontWeight="bold">{keyFormatted}: </Text>
|
||||
<Text>{mrzAttributeFormatted}</Text>
|
||||
</XStack>
|
||||
);
|
||||
})}
|
||||
</YStack>
|
||||
<Text mt="$3">Enter your address or ens</Text>
|
||||
|
||||
<Text mt="$8">Enter your address or ens:</Text>
|
||||
<Input
|
||||
size="md"
|
||||
fontSize={13}
|
||||
mt="$3"
|
||||
placeholder="Your Address or ens name"
|
||||
value={address}
|
||||
onChangeText={setAddress}
|
||||
/>
|
||||
|
||||
<Button borderRadius={100} onPress={handleProve} mt="$6" backgroundColor="#3185FC" >
|
||||
<Button borderRadius={100} onPress={handleProve} mt="$5" mb="$3" backgroundColor="#3185FC" alignSelf='center' >
|
||||
{generatingProof ? (
|
||||
<XStack ai="center">
|
||||
<Spinner />
|
||||
<Text color="white" marginLeft="$2" fow="bold">Generating zk proof</Text>
|
||||
<Text color="white" marginLeft="$2" fow="bold" >Generating ZK proof</Text>
|
||||
</XStack>
|
||||
) : (
|
||||
<Text color="white" fow="bold">Generate zk proof</Text>
|
||||
<Text color="white" fow="bold">Generate ZK proof</Text>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Text fontSize={10} color={generatingProof ? "gray" : "white"} alignSelf='center'>This operation can take about 2 mn</Text>
|
||||
<Text fontSize={9} color={generatingProof ? "gray" : "white"} pb="$2" alignSelf='center'>The application may freeze during this time (hard work)</Text>
|
||||
|
||||
|
||||
</YStack>
|
||||
) : (
|
||||
<YStack m="$2" justifyContent='center' alignItems='center' gap="$5">
|
||||
<Text fontWeight="bold">Zero-knowledge proof generated:</Text>
|
||||
<YStack flex={1} m="$2" justifyContent='center' alignItems='center' gap="$5">
|
||||
<ProofGrid proof={proof} />
|
||||
|
||||
<Text fontWeight="bold" mt="$2">Proof Duration: {formatDuration(proofTime)}</Text>
|
||||
<Text fontWeight="bold">Total Duration: {formatDuration(totalTime)}</Text>
|
||||
<YStack>
|
||||
<Text fontWeight="bold" fontSize="$6" mt="$6">Congrats 🎉</Text>
|
||||
<Text fontWeight="bold" fontSize="$5">You just generated this Zero Knowledge proof !</Text>
|
||||
<Text color="gray" fontSize="$5" mt="$1" fow="bold" textAlign='left'>You can now share this proof with the selected app.</Text>
|
||||
|
||||
<Button borderRadius={100} onPress={handleMint} marginTop="$4" mb="$4" backgroundColor="#3185FC">
|
||||
<Text color="white" fow="bold">Mint Proof of Passport</Text>
|
||||
<Text color="gray" mt="$3">Proof generation duration: {formatDuration(proofTime)}</Text>
|
||||
|
||||
</YStack>
|
||||
|
||||
<XStack flex={1} />
|
||||
|
||||
|
||||
|
||||
{mintText && <Text color="gray">{mintText}</Text>}
|
||||
|
||||
<Button borderRadius={100} onPress={handleMint} marginTop="$4" mb="$8" backgroundColor="#3185FC">
|
||||
<Text color="white" fow="bold" >{selectedApp?.mintphrase}</Text>
|
||||
</Button>
|
||||
|
||||
{mintText && <Text>{mintText}</Text>}
|
||||
</YStack>
|
||||
)
|
||||
) :
|
||||
(
|
||||
<YStack flex={1} justifyContent='center' alignItems='center'>
|
||||
<Text fontSize={18} textAlign='center' fow="bold">Please scan your passport and select an app to generate ZK proof</Text>
|
||||
<XStack mt="$10" gap="$6">
|
||||
<Scan size="$4" color={step < Steps.NFC_SCAN_COMPLETED ? "black" : "#3185FC"} />
|
||||
<LayoutGrid size="$4" color={selectedApp == null ? "black" : "#3185FC"} />
|
||||
</XStack>
|
||||
|
||||
</YStack>
|
||||
|
||||
)
|
||||
}
|
||||
</YStack >
|
||||
);
|
||||
|
||||
@@ -10,8 +10,8 @@ interface ScanScreenProps {
|
||||
|
||||
const ScanScreen: React.FC<ScanScreenProps> = ({ onStartCameraScan, nfcScan, step }) => {
|
||||
return (
|
||||
<YStack gap="$1" >
|
||||
<ZStack alignSelf='center' maxWidth={50} maxHeight={50} width={50} flex={0} space="$0">
|
||||
<YStack f={1} p="$5" gap="$1" px="$5" pt="$12">
|
||||
<ZStack alignSelf='center' maxWidth={50} maxHeight={50} width={50} flex={0} >
|
||||
<Circle
|
||||
alignSelf='center'
|
||||
h={22}
|
||||
@@ -29,10 +29,8 @@ const ScanScreen: React.FC<ScanScreenProps> = ({ onStartCameraScan, nfcScan, ste
|
||||
fow="bold"
|
||||
>1</Text>
|
||||
</ZStack>
|
||||
<Text textAlign='center' mt="$5" px="$4" fow={step === Steps.MRZ_SCAN ? "bold" : "normal"} >Scan the machine readable zone on the main page of your passport</Text>
|
||||
|
||||
|
||||
<ZStack alignSelf='center' mt="$5" maxWidth={50} maxHeight={50} width={50} flex={0} space="$0">
|
||||
<Text textAlign='center' mt="$5" fow={step === Steps.MRZ_SCAN ? "bold" : "normal"} >Scan the machine readable zone on the main page of your passport</Text>
|
||||
<ZStack alignSelf='center' mt="$5" maxWidth={50} maxHeight={50} width={50} flex={0} >
|
||||
<Circle
|
||||
alignSelf='center'
|
||||
h={22}
|
||||
@@ -50,9 +48,9 @@ const ScanScreen: React.FC<ScanScreenProps> = ({ onStartCameraScan, nfcScan, ste
|
||||
fow="bold"
|
||||
>2</Text>
|
||||
</ZStack>
|
||||
<Text textAlign='center' mt="$5" px="$4" fow={(step === Steps.MRZ_SCAN_COMPLETED) || (step === Steps.NFC_SCANNING) ? "bold" : "normal"}>Hold your passport against your device to read the biometric chip</Text>
|
||||
<Text textAlign='center' mt="$5" fow={(step === Steps.MRZ_SCAN_COMPLETED) || (step === Steps.NFC_SCANNING) ? "bold" : "normal"}>Hold your passport against your device to read the biometric chip</Text>
|
||||
|
||||
<ZStack alignSelf='center' mt="$5" maxWidth={50} maxHeight={50} width={50} flex={0} space="$0">
|
||||
<ZStack alignSelf='center' mt="$5" maxWidth={50} maxHeight={50} width={50} flex={0} >
|
||||
<Circle
|
||||
alignSelf='center'
|
||||
h={22}
|
||||
@@ -70,9 +68,9 @@ const ScanScreen: React.FC<ScanScreenProps> = ({ onStartCameraScan, nfcScan, ste
|
||||
fow="bold"
|
||||
>3</Text>
|
||||
</ZStack>
|
||||
<Text textAlign='center' mt="$5" px="$4" fow={step >= Steps.NFC_SCAN_COMPLETED ? "bold" : "normal"}>Select App</Text>
|
||||
<Text textAlign='center' mt="$5" fow={step >= Steps.NFC_SCAN_COMPLETED ? "bold" : "normal"}>Select App</Text>
|
||||
|
||||
<YStack w="100%" ai="center">
|
||||
<YStack ai="center">
|
||||
{
|
||||
step < Steps.NFC_SCAN_COMPLETED
|
||||
? (
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// AppClass.ts
|
||||
|
||||
type Disclosure = {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
@@ -8,15 +6,18 @@ export class App {
|
||||
id: string;
|
||||
name: string;
|
||||
disclosure: Disclosure;
|
||||
mintphrase: string;
|
||||
disclosurephrase: string;
|
||||
|
||||
constructor(id: string, name: string, disclosure: Disclosure) {
|
||||
constructor(id: string, name: string, disclosure: Disclosure, mintphrase: string, disclosurephrase: string) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.disclosure = disclosure;
|
||||
this.disclosurephrase = disclosurephrase;
|
||||
this.mintphrase = mintphrase;
|
||||
}
|
||||
}
|
||||
|
||||
// Create instances of the App class
|
||||
export const gitcoin = new App("gitcoin", "Gitcoin", {});
|
||||
export const soulbond = new App("soulbond", "Soulbond token", { nationality: false, expiry_date: false });
|
||||
export const zuzalu = new App("zuzalu", "Zupass", { date_of_birth: false });
|
||||
export const gitcoin = new App("gitcoin", "Gitcoin", {}, "Add to Gitcoin passport", "Gitcoin passport doesn't require to disclosure any data.");
|
||||
export const soulbond = new App("soulbond", "Soulbond token", { nationality: false, expiry_date: false }, "Mint Soulbond token", "Disclosure the information you want and mint your SBT:");
|
||||
export const zuzalu = new App("zuzalu", "Zupass", { date_of_birth: false }, "Add to Zupass", "Zupass requires the following information:");
|
||||
|
||||
1610
app/yarn.lock
1610
app/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user