mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
use tamagui sheet instead of select component
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { NativeEventEmitter, NativeModules, Linking, Modal, Platform, Pressable } from 'react-native';
|
||||
import { NativeEventEmitter, NativeModules, Linking, Modal, Platform, Pressable, TouchableOpacity, ScrollView } from 'react-native';
|
||||
import { YStack, XStack, Text, Button, Tabs, Sheet, Label, Fieldset, Input, Switch, H2, Image, useWindowDimensions, H4, H3, View, Separator } from 'tamagui'
|
||||
import { HelpCircle, IterationCw, VenetianMask, Cog, CheckCircle2, ChevronLeft, Share, Eraser, ArrowRight, UserPlus, CalendarSearch, X, ShieldCheck } from '@tamagui/lucide-icons';
|
||||
import Telegram from '../images/telegram.png'
|
||||
@@ -36,6 +36,9 @@ import ValidProofScreen from './ValidProofScreen';
|
||||
import WrongProofScreen from './WrongProofScreen';
|
||||
import MockDataScreen from './MockDataScreen';
|
||||
import OPENPASSPORT_LOGO from '../images/openpassport.png'
|
||||
import { countryCodes } from '../../../common/src/constants/constants';
|
||||
import getCountryISO2 from "country-iso-3-to-2";
|
||||
import { flag } from 'country-emoji';
|
||||
|
||||
const emitter = (Platform.OS === 'android')
|
||||
? new NativeEventEmitter(NativeModules.nativeModule)
|
||||
@@ -57,6 +60,10 @@ const MainScreen: React.FC = () => {
|
||||
const [dateOfBirthDatePickerIsOpen, setDateOfBirthDatePickerIsOpen] = useState(false)
|
||||
const [dateOfExpiryDatePickerIsOpen, setDateOfExpiryDatePickerIsOpen] = useState(false)
|
||||
const [isFormComplete, setIsFormComplete] = useState(false);
|
||||
const [countrySheetOpen, setCountrySheetOpen] = useState(false);
|
||||
const [algorithmSheetOpen, setAlgorithmSheetOpen] = useState(false);
|
||||
const [selectedCountry, setSelectedCountry] = useState('USA');
|
||||
const [selectedAlgorithm, setSelectedAlgorithm] = useState('rsa_sha256');
|
||||
|
||||
const {
|
||||
passportNumber,
|
||||
@@ -206,6 +213,16 @@ const MainScreen: React.FC = () => {
|
||||
|
||||
const { height } = useWindowDimensions();
|
||||
|
||||
const handleCountrySelect = (countryCode: string) => {
|
||||
setSelectedCountry(countryCode);
|
||||
setCountrySheetOpen(false);
|
||||
};
|
||||
|
||||
const handleAlgorithmSelect = (algorithm: string) => {
|
||||
setSelectedAlgorithm(algorithm);
|
||||
setAlgorithmSheetOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<YStack f={1}>
|
||||
<ToastViewport portalToRoot flexDirection="column-reverse" top={85} right={0} left={0} />
|
||||
@@ -773,6 +790,82 @@ const MainScreen: React.FC = () => {
|
||||
</Sheet.Frame>
|
||||
</Sheet>
|
||||
|
||||
<Sheet
|
||||
modal
|
||||
open={countrySheetOpen}
|
||||
onOpenChange={setCountrySheetOpen}
|
||||
snapPoints={[60]}
|
||||
animation="medium"
|
||||
disableDrag
|
||||
>
|
||||
<Sheet.Overlay />
|
||||
<Sheet.Frame bg={bgWhite} borderTopLeftRadius="$9" borderTopRightRadius="$9">
|
||||
<YStack p="$4">
|
||||
<XStack ai="center" jc="space-between" mb="$4">
|
||||
<Text fontSize="$8">Select a country</Text>
|
||||
<XStack onPress={() => setCountrySheetOpen(false)} p="$2">
|
||||
<X color={borderColor} size="$1.5" mr="$2" />
|
||||
</XStack>
|
||||
</XStack>
|
||||
<Separator borderColor={separatorColor} mb="$4" />
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{Object.keys(countryCodes).map((countryCode) => (
|
||||
<TouchableOpacity
|
||||
key={countryCode}
|
||||
onPress={() => {
|
||||
handleCountrySelect(countryCode);
|
||||
setCountrySheetOpen(false);
|
||||
}}
|
||||
>
|
||||
<XStack py="$3" px="$2">
|
||||
<Text fontSize="$4">
|
||||
{countryCodes[countryCode as keyof typeof countryCodes]} {flag(getCountryISO2(countryCode))}
|
||||
</Text>
|
||||
</XStack>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
</YStack>
|
||||
</Sheet.Frame>
|
||||
</Sheet>
|
||||
|
||||
<Sheet
|
||||
modal
|
||||
open={algorithmSheetOpen}
|
||||
onOpenChange={setAlgorithmSheetOpen}
|
||||
snapPoints={[40]}
|
||||
animation="medium"
|
||||
disableDrag
|
||||
>
|
||||
<Sheet.Overlay />
|
||||
<Sheet.Frame bg={bgWhite} borderTopLeftRadius="$9" borderTopRightRadius="$9">
|
||||
<YStack p="$4">
|
||||
<XStack ai="center" jc="space-between" mb="$4">
|
||||
<Text fontSize="$8">Select an algorithm</Text>
|
||||
<XStack onPress={() => setAlgorithmSheetOpen(false)} p="$2">
|
||||
<X color={borderColor} size="$1.5" mr="$2" />
|
||||
</XStack>
|
||||
</XStack>
|
||||
<Separator borderColor={separatorColor} mb="$4" />
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{["rsa_sha1", "rsa_sha256", "rsapss_sha256"].map((algorithm) => (
|
||||
<TouchableOpacity
|
||||
key={algorithm}
|
||||
onPress={() => {
|
||||
handleAlgorithmSelect(algorithm);
|
||||
setAlgorithmSheetOpen(false);
|
||||
}}
|
||||
>
|
||||
<XStack py="$3" px="$2">
|
||||
<Text fontSize="$4">{algorithm}</Text>
|
||||
</XStack>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
</YStack>
|
||||
</Sheet.Frame>
|
||||
</Sheet>
|
||||
|
||||
</YStack>
|
||||
|
||||
<Tabs f={1} orientation="horizontal" flexDirection="column" defaultValue={"splash"}
|
||||
@@ -789,7 +882,12 @@ const MainScreen: React.FC = () => {
|
||||
/>
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="mock" f={1}>
|
||||
<MockDataScreen />
|
||||
<MockDataScreen
|
||||
onCountryPress={() => setCountrySheetOpen(true)}
|
||||
onAlgorithmPress={() => setAlgorithmSheetOpen(true)}
|
||||
selectedCountry={selectedCountry}
|
||||
selectedAlgorithm={selectedAlgorithm}
|
||||
/>
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="scan" f={1}>
|
||||
<CameraScreen
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useCallback, useMemo } from 'react';
|
||||
import React, { useState, useCallback, useMemo, useRef } from 'react';
|
||||
import { YStack, XStack, Text, Select, Adapt, Sheet, Fieldset, Button, Spinner, Switch } from 'tamagui';
|
||||
import { Check, ChevronDown, ChevronUp, Cpu, Minus, Plus } from '@tamagui/lucide-icons';
|
||||
import { Check, ChevronDown, ChevronUp, Cpu, Minus, Plus, X } from '@tamagui/lucide-icons';
|
||||
import { bgColor, bgGreen, bgGreen2, blueColor, borderColor, greenColorLight, redColorDark, textBlack } from '../utils/colors';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
@@ -9,14 +9,23 @@ import { genMockPassportData } from '../../../common/src/utils/genMockPassportDa
|
||||
import { countryCodes } from '../../../common/src/constants/constants';
|
||||
import getCountryISO2 from "country-iso-3-to-2";
|
||||
import { flag } from 'country-emoji';
|
||||
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
const MockDataScreen: React.FC = () => {
|
||||
const [signatureAlgorithm, setSignatureAlgorithm] = useState("rsa_sha256");
|
||||
const listOfSignatureAlgorithms = ["rsa_sha1", "rsa_sha256", "rsapss_sha256"];
|
||||
interface MockDataScreenProps {
|
||||
onCountryPress: () => void;
|
||||
onAlgorithmPress: () => void;
|
||||
selectedCountry: string;
|
||||
selectedAlgorithm: string;
|
||||
}
|
||||
|
||||
const MockDataScreen: React.FC<MockDataScreenProps> = ({
|
||||
onCountryPress,
|
||||
onAlgorithmPress,
|
||||
selectedCountry,
|
||||
selectedAlgorithm,
|
||||
}) => {
|
||||
const [age, setAge] = useState(24);
|
||||
const [expiryYears, setExpiryYears] = useState(5);
|
||||
const [nationality, setNationality] = useState("FRA");
|
||||
const [isGenerating, setIsGenerating] = useState(false);
|
||||
const [isInOfacList, setIsInOfacList] = useState(false);
|
||||
const castDate = (yearsOffset: number) => {
|
||||
@@ -34,8 +43,8 @@ const MockDataScreen: React.FC = () => {
|
||||
let mockPassportData;
|
||||
if (isInOfacList) {
|
||||
mockPassportData = genMockPassportData(
|
||||
signatureAlgorithm as "rsa_sha256" | "rsa_sha1" | "rsapss_sha256",
|
||||
nationality as keyof typeof countryCodes,
|
||||
selectedAlgorithm as "rsa_sha256" | "rsa_sha1" | "rsapss_sha256",
|
||||
selectedCountry as keyof typeof countryCodes,
|
||||
castDate(-age),
|
||||
castDate(expiryYears),
|
||||
randomPassportNumber,
|
||||
@@ -44,8 +53,8 @@ const MockDataScreen: React.FC = () => {
|
||||
);
|
||||
} else {
|
||||
mockPassportData = genMockPassportData(
|
||||
signatureAlgorithm as "rsa_sha256" | "rsa_sha1" | "rsapss_sha256",
|
||||
nationality as keyof typeof countryCodes,
|
||||
selectedAlgorithm as "rsa_sha256" | "rsa_sha1" | "rsapss_sha256",
|
||||
selectedCountry as keyof typeof countryCodes,
|
||||
castDate(-age),
|
||||
castDate(expiryYears),
|
||||
randomPassportNumber,
|
||||
@@ -65,149 +74,30 @@ const MockDataScreen: React.FC = () => {
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
useNavigationStore.getState().setSelectedTab("next");
|
||||
}, [signatureAlgorithm, nationality, age, expiryYears, isInOfacList]);
|
||||
const countryOptions = useMemo(() => {
|
||||
return Object.keys(countryCodes).map((countryCode, index) => ({
|
||||
countryCode,
|
||||
countryName: countryCodes[countryCode as keyof typeof countryCodes],
|
||||
flagEmoji: flag(getCountryISO2(countryCode)),
|
||||
index,
|
||||
}));
|
||||
}, []);
|
||||
}, [selectedAlgorithm, selectedCountry, age, expiryYears, isInOfacList]);
|
||||
|
||||
return (
|
||||
<YStack f={1} gap="$4" >
|
||||
<Text my="$9" textAlign="center" fontSize="$9" color={textBlack}>Generate passport data</Text>
|
||||
<XStack ai="center" >
|
||||
<Text f={1} fontSize="$5">
|
||||
Encryption
|
||||
</Text>
|
||||
<Select
|
||||
id="signature-algorithm"
|
||||
value={signatureAlgorithm}
|
||||
onValueChange={setSignatureAlgorithm}
|
||||
native
|
||||
>
|
||||
<Select.Trigger w="$16" iconAfter={ChevronDown}>
|
||||
<Select.Value placeholder="Select algorithm" />
|
||||
</Select.Trigger>
|
||||
|
||||
<Adapt when="sm" platform="touch">
|
||||
<Sheet
|
||||
modal
|
||||
dismissOnSnapToBottom
|
||||
animationConfig={{
|
||||
type: 'spring',
|
||||
damping: 20,
|
||||
mass: 1.2,
|
||||
stiffness: 250,
|
||||
}}
|
||||
>
|
||||
<Sheet.Frame>
|
||||
<Text fontSize="$8" p="$3">Encryption method</Text>
|
||||
<Sheet.ScrollView>
|
||||
<Adapt.Contents />
|
||||
</Sheet.ScrollView>
|
||||
</Sheet.Frame>
|
||||
<Sheet.Overlay
|
||||
animation="lazy"
|
||||
enterStyle={{ opacity: 0 }}
|
||||
exitStyle={{ opacity: 0 }}
|
||||
/>
|
||||
</Sheet>
|
||||
</Adapt>
|
||||
|
||||
<Select.Content zIndex={200000}>
|
||||
<Select.ScrollUpButton ai="center" jc="center" pos="relative" w="100%" h="$3">
|
||||
<ChevronUp size={20} />
|
||||
</Select.ScrollUpButton>
|
||||
|
||||
<Select.Viewport minWidth={200}>
|
||||
<Select.Group>
|
||||
{listOfSignatureAlgorithms.map((algorithm, index) => (
|
||||
<Select.Item key={algorithm} index={index} value={algorithm}>
|
||||
<Select.ItemText >{algorithm}</Select.ItemText>
|
||||
<Select.ItemIndicator marginLeft="auto">
|
||||
<Check size={16} />
|
||||
</Select.ItemIndicator>
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Group>
|
||||
</Select.Viewport>
|
||||
|
||||
<Select.ScrollDownButton ai="center" jc="center" pos="relative" w="100%" h="$3">
|
||||
<ChevronDown size={20} />
|
||||
</Select.ScrollDownButton>
|
||||
</Select.Content>
|
||||
</Select>
|
||||
<XStack ai="center">
|
||||
<Text f={1} fontSize="$5">Encryption</Text>
|
||||
<Button onPress={onAlgorithmPress} p="$2" px="$3" bg="white" borderColor={borderColor} borderWidth={1} borderRadius="$4" >
|
||||
<XStack ai="center" gap="$2">
|
||||
<Text fontSize="$4">{selectedAlgorithm}</Text>
|
||||
<ChevronDown size={20} />
|
||||
</XStack>
|
||||
</Button>
|
||||
</XStack>
|
||||
|
||||
|
||||
<XStack ai="center" gap="$2">
|
||||
<Text f={1} fontSize="$5">
|
||||
Nationality
|
||||
</Text>
|
||||
<Select
|
||||
id="nationality"
|
||||
value={nationality}
|
||||
onValueChange={setNationality}
|
||||
native
|
||||
>
|
||||
<Select.Trigger width="$16" iconAfter={ChevronDown}>
|
||||
<Select.Value placeholder="Select algorithm" />
|
||||
</Select.Trigger>
|
||||
|
||||
<Adapt when="sm" platform="touch">
|
||||
<Sheet
|
||||
modal
|
||||
dismissOnSnapToBottom
|
||||
animationConfig={{
|
||||
type: 'spring',
|
||||
damping: 20,
|
||||
mass: 1.2,
|
||||
stiffness: 250,
|
||||
}}
|
||||
>
|
||||
<Sheet.Frame >
|
||||
<Text fontSize="$8" p="$3">Nationality</Text>
|
||||
<Sheet.ScrollView>
|
||||
<Adapt.Contents />
|
||||
</Sheet.ScrollView>
|
||||
</Sheet.Frame>
|
||||
<Sheet.Overlay
|
||||
animation="lazy"
|
||||
enterStyle={{ opacity: 0 }}
|
||||
exitStyle={{ opacity: 0 }}
|
||||
/>
|
||||
</Sheet>
|
||||
</Adapt>
|
||||
|
||||
<Select.Content zIndex={200000}>
|
||||
<Select.ScrollUpButton ai="center" jc="center" pos="relative" w="100%" h="$3">
|
||||
<ChevronUp size={20} />
|
||||
</Select.ScrollUpButton>
|
||||
|
||||
<Select.Viewport minWidth={200}>
|
||||
<Select.Group>
|
||||
{countryOptions.map(({ countryCode, countryName, flagEmoji, index }) => (
|
||||
<Select.Item key={countryCode} index={index} value={countryCode}>
|
||||
<Select.ItemText>{countryName} {flagEmoji}</Select.ItemText>
|
||||
<Select.ItemIndicator marginLeft="auto">
|
||||
<Check size={16} />
|
||||
</Select.ItemIndicator>
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Group>
|
||||
</Select.Viewport>
|
||||
|
||||
<Select.ScrollDownButton ai="center" jc="center" pos="relative" w="100%" h="$3">
|
||||
<ChevronDown size={20} />
|
||||
</Select.ScrollDownButton>
|
||||
</Select.Content>
|
||||
</Select>
|
||||
<XStack ai="center">
|
||||
<Text f={1} fontSize="$5">Nationality</Text>
|
||||
<Button onPress={onCountryPress} p="$2" px="$3" bg="white" borderColor={borderColor} borderWidth={1} borderRadius="$4">
|
||||
<XStack ai="center" gap="$2">
|
||||
<Text fontSize="$4">{countryCodes[selectedCountry as keyof typeof countryCodes]} {flag(getCountryISO2(selectedCountry))}</Text>
|
||||
<ChevronDown size={20} />
|
||||
</XStack>
|
||||
</Button>
|
||||
</XStack>
|
||||
|
||||
|
||||
|
||||
<Fieldset mt="$2" gap="$2" horizontal>
|
||||
<Text color={textBlack} width={160} justifyContent="flex-end" fontSize="$5">
|
||||
Age (🎂)
|
||||
|
||||
Reference in New Issue
Block a user