mirror of
https://github.com/status-im/keycard-exit.git
synced 2025-01-20 15:49:42 +00:00
added insert pin
This commit is contained in:
parent
660960db1a
commit
5855b788ec
@ -1,6 +1,11 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "org.jetbrains.kotlin.android"
|
||||
apply plugin: "com.facebook.react"
|
||||
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
|
||||
|
||||
project.ext.vectoricons = [
|
||||
iconFontNames: [ 'Feather.ttf' ]
|
||||
]
|
||||
|
||||
/**
|
||||
* This is the configuration block to customize your React Native Android app.
|
||||
|
53
package-lock.json
generated
53
package-lock.json
generated
@ -11,7 +11,8 @@
|
||||
"react": "18.3.1",
|
||||
"react-native": "0.75.2",
|
||||
"react-native-modal": "^13.0.1",
|
||||
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.39"
|
||||
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.39",
|
||||
"react-native-vector-icons": "^10.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
@ -12043,6 +12044,56 @@
|
||||
"resolved": "git+ssh://git@github.com/status-im/react-native-status-keycard.git#93dd64754e676172310e6ea7187cc49f2dc013c6",
|
||||
"license": "MPL 2.0"
|
||||
},
|
||||
"node_modules/react-native-vector-icons": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-10.1.0.tgz",
|
||||
"integrity": "sha512-fdQjCHIdoXmRoTZ5gvN1FmT4sGLQ2wmQiNZHKJQUYnE2tkIwjGnxNch+6Nd4lHAACvMWO7LOzBNot2u/zlOmkw==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2",
|
||||
"yargs": "^16.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"fa-upgrade.sh": "bin/fa-upgrade.sh",
|
||||
"fa5-upgrade": "bin/fa5-upgrade.sh",
|
||||
"fa6-upgrade": "bin/fa6-upgrade.sh",
|
||||
"generate-icon": "bin/generate-icon.js"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-vector-icons/node_modules/cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-vector-icons/node_modules/yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
|
||||
"dependencies": {
|
||||
"cliui": "^7.0.2",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.0",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^20.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-vector-icons/node_modules/yargs-parser": {
|
||||
"version": "20.2.9",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native/node_modules/@jest/types": {
|
||||
"version": "26.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
|
||||
|
@ -13,7 +13,8 @@
|
||||
"react": "18.3.1",
|
||||
"react-native": "0.75.2",
|
||||
"react-native-modal": "^13.0.1",
|
||||
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.39"
|
||||
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.39",
|
||||
"react-native-vector-icons": "^10.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
|
14
src/Main.tsx
14
src/Main.tsx
@ -111,12 +111,16 @@ const Main = () => {
|
||||
return connectCard();
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
setStep(Step.Discovery);
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={[backgroundStyle, styles.container]}>
|
||||
{step == Step.Discovery && <DiscoveryScreen onPressFunc={connectCard}></DiscoveryScreen>}
|
||||
{step == Step.Initialization && <InitializationScreen onPressFunc={initPin} ></InitializationScreen>}
|
||||
{step == Step.Loading && <MnemonicScreen onPressFunc={loadMnemonic} pinRequired={pinRef.current ? false : true}></MnemonicScreen>}
|
||||
{step == Step.Authentication && <AuthenticationScreen onPressFunc={() => {}}></AuthenticationScreen>}
|
||||
{step == Step.Initialization && <InitializationScreen onPressFunc={initPin} onCancelFunc={cancel}></InitializationScreen>}
|
||||
{step == Step.Loading && <MnemonicScreen onPressFunc={loadMnemonic} pinRequired={pinRef.current ? false : true} onCancelFunc={cancel}></MnemonicScreen>}
|
||||
{step == Step.Authentication && <AuthenticationScreen onPressFunc={() => {} } onCancelFunc={cancel}></AuthenticationScreen>}
|
||||
<NFCModal isVisible={isModalVisible} onChangeFunc={setIsModalVisible}></NFCModal>
|
||||
</SafeAreaView>
|
||||
);
|
||||
@ -124,10 +128,8 @@ const Main = () => {
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
paddingTop: '30%',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
paddingLeft: '6%',
|
||||
paddingRight: '6%'
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -27,10 +27,9 @@ const buttonStyle = StyleSheet.create({
|
||||
textAlign: 'center',
|
||||
paddingTop: 25,
|
||||
paddingBottom: 15,
|
||||
justifyContent: 'flex-start'
|
||||
justifyContent: 'flex-start',
|
||||
},
|
||||
button: {
|
||||
|
||||
},
|
||||
title: {
|
||||
fontSize: 15,
|
||||
|
73
src/components/CustomDialpad.tsx
Normal file
73
src/components/CustomDialpad.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import { SafeAreaView, StyleSheet, Text, View, Dimensions } from "react-native";
|
||||
import React, {FC, useState } from "react";
|
||||
import DialpadKeypad from "./DialpadKeypad";
|
||||
import Button from "./Button";
|
||||
|
||||
const { width, height } = Dimensions.get("window");
|
||||
|
||||
type CustomDialpadProps = {
|
||||
onCancelFunc: () => void;
|
||||
onNextFunc: (p?: string) => void;
|
||||
};
|
||||
|
||||
const CustomDialpad: FC<CustomDialpadProps> = props => {
|
||||
const {onNextFunc, onCancelFunc} = props;
|
||||
const dialPadContent = [1, 2, 3, 4, 5, 6, 7, 8, 9, "", 0, "X"];
|
||||
const dialPadSize = width * 0.2;
|
||||
const dialPadTextSize = dialPadSize * 0.36;
|
||||
const [code, setCode] = useState([]);
|
||||
|
||||
const pinLength = 6;
|
||||
|
||||
const updateCode = (item: never) => {
|
||||
if (item === "X") {
|
||||
setCode((prev) => prev.slice(0, -1));
|
||||
} else {
|
||||
setCode((prev) => [...prev, item]);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={styles.pinText}>Create PIN</Text>
|
||||
<Text style={styles.pinSubText}>Enter your secure six-digit code</Text>
|
||||
<DialpadKeypad dialPadContent={dialPadContent} pinLength={pinLength} dialPadSize={dialPadSize} dialPadTextSize={dialPadTextSize} setCode={updateCode} code={code}/>
|
||||
</View>
|
||||
<View style={styles.btnContainer}>
|
||||
<Button label="Cancel" disabled={false} btnColor="#4A646C" btnWidth="50%" onChangeFunc={onCancelFunc} btnJustifyContent='center'></Button>
|
||||
<Button label="Next" disabled={false} btnColor="#4A646C" btnWidth="50%" onChangeFunc={onNextFunc} btnJustifyContent='center'></Button>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: "#4A646C55",
|
||||
height: '100%'
|
||||
},
|
||||
textContainer: {
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
marginTop: 40,
|
||||
position: "relative",
|
||||
},
|
||||
pinText: {
|
||||
fontSize: 30,
|
||||
fontWeight: "medium",
|
||||
color: "white",
|
||||
},
|
||||
pinSubText: {
|
||||
fontSize: 18,
|
||||
fontWeight: "medium",
|
||||
color: "white",
|
||||
marginVertical: 30,
|
||||
},
|
||||
btnContainer: {
|
||||
flexDirection: 'row',
|
||||
width: '100%',
|
||||
alignItems: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
export default CustomDialpad;
|
60
src/components/DialpadKeypad.tsx
Normal file
60
src/components/DialpadKeypad.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import {FC } from "react";
|
||||
import { StyleSheet, Text, View, FlatList, TouchableOpacity } from "react-native";
|
||||
import Icon from 'react-native-vector-icons/Feather';
|
||||
|
||||
type DialpadKeypadProps = {
|
||||
dialPadContent: any[];
|
||||
pinLength: number;
|
||||
dialPadSize: number;
|
||||
dialPadTextSize: number;
|
||||
code: number[];
|
||||
setCode: (item: never) => void;
|
||||
};
|
||||
|
||||
const DialpadKeypad: FC<DialpadKeypadProps> = props => {
|
||||
const {dialPadContent, pinLength, dialPadSize, dialPadTextSize} = props;
|
||||
|
||||
return (
|
||||
<FlatList data={dialPadContent} numColumns={3} keyExtractor={(_, index) => index.toString()} renderItem={({ item }) => {
|
||||
return (
|
||||
<TouchableOpacity disabled={item === ""}>
|
||||
<View style={[
|
||||
{
|
||||
backgroundColor: item === "" ? "transparent" : "#fff",
|
||||
width: dialPadSize,
|
||||
height: dialPadSize,
|
||||
},
|
||||
styles.dialPadContainer,
|
||||
]}
|
||||
>
|
||||
{item === "X" ? (
|
||||
<Icon name="delete" size={24} color="#3F1D38" />
|
||||
) : (
|
||||
<Text
|
||||
style={[{ fontSize: dialPadTextSize }, styles.dialPadText]}
|
||||
>
|
||||
{item}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
dialPadContainer: {
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
margin: 15,
|
||||
borderRadius: 45,
|
||||
padding: 0,
|
||||
borderColor: "transparent",
|
||||
},
|
||||
dialPadText: {
|
||||
color: "#3F1D38",
|
||||
}
|
||||
});
|
||||
|
||||
export default DialpadKeypad;
|
0
src/components/PinInput.tsx
Normal file
0
src/components/PinInput.tsx
Normal file
@ -1,17 +1,20 @@
|
||||
import {FC } from "react";
|
||||
import { StyleSheet, Text, View } from "react-native";
|
||||
import Button from "../Button";
|
||||
|
||||
type AuthenticationScreenProps = {
|
||||
onPressFunc: () => void;
|
||||
onCancelFunc: () => void;
|
||||
};
|
||||
|
||||
const AuthenticationScreen: FC<AuthenticationScreenProps> = props => {
|
||||
const {onPressFunc} = props;
|
||||
const {onPressFunc, onCancelFunc} = props;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View>
|
||||
<Text style={styles.heading}> Success</Text>
|
||||
<Button label="Cancel" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={onCancelFunc} btnJustifyContent='center'></Button>
|
||||
</View>
|
||||
</View>
|
||||
)};
|
||||
|
@ -1,21 +1,24 @@
|
||||
import {FC, useState } from "react";
|
||||
import { StyleSheet, Text, TextInput, View } from "react-native";
|
||||
import Button from "../Button";
|
||||
import CustomDialpad from "../CustomDialpad";
|
||||
|
||||
enum PinSteps {
|
||||
NumPad,
|
||||
InsertPin,
|
||||
RepeatPin
|
||||
}
|
||||
|
||||
type InitializationScreenProps = {
|
||||
onPressFunc: (pin: string) => void;
|
||||
onCancelFunc: () => void;
|
||||
};
|
||||
|
||||
const InitializationScreen: FC<InitializationScreenProps> = props => {
|
||||
const {onPressFunc} = props;
|
||||
const {onPressFunc, onCancelFunc} = props;
|
||||
const [pin, onChangePin] = useState('');
|
||||
const [btnDisabled, setBtnDisabled] = useState(true);
|
||||
const [step, setStep] = useState(PinSteps.InsertPin);
|
||||
const [step, setStep] = useState(PinSteps.NumPad);
|
||||
|
||||
const checkPin = (p: string) => {
|
||||
pin === p ? setBtnDisabled(false) : setBtnDisabled(true);
|
||||
@ -23,11 +26,13 @@ const InitializationScreen: FC<InitializationScreenProps> = props => {
|
||||
|
||||
return (
|
||||
<View>
|
||||
<CustomDialpad onCancelFunc={() => {}} onNextFunc={() => {}}></CustomDialpad>
|
||||
{ step == PinSteps.InsertPin &&
|
||||
<View>
|
||||
<Text style={styles.heading}> Insert pin</Text>
|
||||
<TextInput onChangeText={onChangePin} value={pin} keyboardType="number-pad" maxLength={6}/>
|
||||
<Button label="Next" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={() => setStep(PinSteps.RepeatPin)} btnJustifyContent='center'></Button>
|
||||
<Button label="Cancel" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={onCancelFunc} btnJustifyContent='center'></Button>
|
||||
</View>
|
||||
}
|
||||
|
||||
@ -36,6 +41,7 @@ const InitializationScreen: FC<InitializationScreenProps> = props => {
|
||||
<Text style={styles.heading}> Repeat pin</Text>
|
||||
<TextInput onChangeText={(val) => {checkPin(val)}} keyboardType="number-pad" maxLength={6}/>
|
||||
<Button label="Next" disabled={btnDisabled} btnColor="#4A646C" btnWidth="100%" onChangeFunc={() => {onPressFunc(pin)}} btnJustifyContent='center'></Button>
|
||||
<Button label="Back" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={() => setStep(PinSteps.InsertPin)} btnJustifyContent='center'></Button>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
|
@ -11,10 +11,11 @@ enum LoadMnemonicSteps {
|
||||
type MnemonicScreenProps = {
|
||||
pinRequired: boolean;
|
||||
onPressFunc: (mn: string, pin?: string) => void;
|
||||
onCancelFunc: () => void;
|
||||
};
|
||||
|
||||
const MnemonicScreen: FC<MnemonicScreenProps> = props => {
|
||||
const {pinRequired, onPressFunc} = props;
|
||||
const {pinRequired, onPressFunc, onCancelFunc} = props;
|
||||
const [mnemonic, setMnemonic] = useState('');
|
||||
const [pin, setPin] = useState('');
|
||||
const [errMessage, setErrMessage] = useState('');
|
||||
@ -49,6 +50,7 @@ const MnemonicScreen: FC<MnemonicScreenProps> = props => {
|
||||
<Text style={styles.heading}> Load mnemonic</Text>
|
||||
<TextInput editable multiline numberOfLines={6} onChangeText={(val) => setMnemonic(val)} value={mnemonic} style={{backgroundColor: '#4A646C'}} />
|
||||
<Button label="Next" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={() => updateMnemonic(mnemonic)} btnJustifyContent='center'></Button>
|
||||
<Button label="Cancel" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={onCancelFunc} btnJustifyContent='center'></Button>
|
||||
<Text>{errMessage}</Text>
|
||||
</View>
|
||||
}
|
||||
@ -57,6 +59,7 @@ const MnemonicScreen: FC<MnemonicScreenProps> = props => {
|
||||
<Text style={styles.heading}> Insert pin</Text>
|
||||
<TextInput onChangeText={setPin} value={pin} keyboardType="number-pad" maxLength={6}/>
|
||||
<Button label="Next" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={() => {onPressFunc(mnemonic, pin)}} btnJustifyContent='center'></Button>
|
||||
<Button label="Back" disabled={false} btnColor="#4A646C" btnWidth="100%" onChangeFunc={() => setStep(LoadMnemonicSteps.InsertMnemonic)} btnJustifyContent='center'></Button>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
|
Loading…
x
Reference in New Issue
Block a user