Add CSS Themes and Download vc using AID/RID

This commit is contained in:
Sri Kanth Kola
2022-08-07 16:40:07 +05:30
parent 967ce79867
commit 70559604af
61 changed files with 1907 additions and 715 deletions

View File

@@ -4,7 +4,7 @@ import { Popable } from 'react-native-popable';
import { Text } from 'react-native-elements';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { Row } from './ui';
import { Colors } from './ui/styleUtils';
import { Colors, Theme } from './ui/styleUtils';
export const DropdownIcon: React.FC<DropdownProps> = (props) => {
const popover = useRef(null);
@@ -30,7 +30,7 @@ export const DropdownIcon: React.FC<DropdownProps> = (props) => {
<Row>
<Icon
name={item.icon}
color={Colors.Orange}
color={Theme.Colors.Icon}
size={20}
style={{ marginRight: 8 }}
/>
@@ -57,7 +57,7 @@ export const DropdownIcon: React.FC<DropdownProps> = (props) => {
/>
</View>
}>
<Icon name={props.icon} color={Colors.Orange} size={24} />
<Icon name={props.icon} color={Theme.Colors.Icon} size={24} />
</Popable>
</View>
);

View File

@@ -1,11 +1,14 @@
import React from 'react';
import { View, Image } from 'react-native';
import { MosipLogo } from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
export const Logo: React.FC<LogoProps> = (props) => {
return (
<View>
<Image style={{ resizeMode: 'contain', ...props }} source={MosipLogo} />
<Image
style={{ resizeMode: 'contain', ...props }}
source={Theme.MosipLogo}
/>
</View>
);
};

View File

@@ -2,12 +2,12 @@ import React from 'react';
import { Dimensions, StyleSheet } from 'react-native';
import { Overlay, LinearProgress } from 'react-native-elements';
import { Column, Text } from './ui';
import { Colors, elevation } from './ui/styleUtils';
import { elevation, Theme } from './ui/styleUtils';
const styles = StyleSheet.create({
overlay: {
...elevation(5),
backgroundColor: Colors.White,
backgroundColor: Theme.Colors.White,
},
});
@@ -26,7 +26,10 @@ export const MessageOverlay: React.FC<MessageOverlayProps> = (props) => {
)}
{props.message && <Text margin="0 0 12 0">{props.message}</Text>}
{props.hasProgress && (
<LinearProgress variant="indeterminate" color={Colors.Orange} />
<LinearProgress
variant="indeterminate"
color={Theme.Colors.Loading}
/>
)}
</Column>
</Overlay>

View File

@@ -6,13 +6,7 @@ import { Image, ImageBackground } from 'react-native';
import { Icon, ListItem } from 'react-native-elements';
import { VC, CredentialSubject } from '../types/vc';
import { Column, Row, Text } from './ui';
import {
Colors,
OpenCard,
ProfileIcon,
MosipLogo,
Styles,
} from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
import { TextItem } from './ui/TextItem';
import { useReceiveVcModal } from '../screens/Request/ReceiveVcModalController';
@@ -20,7 +14,7 @@ const VerifiedIcon: React.FC = () => {
return (
<Icon
name="check-circle"
color={Colors.Green}
color={Theme.Colors.Green}
size={14}
containerStyle={{ marginStart: 4, bottom: 1 }}
/>
@@ -37,30 +31,33 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
width: '100%',
height: '100%',
}}
source={OpenCard}>
<Row style={Styles.successTag}>
<Icon name="check-circle" color={Colors.White} size={40} />
<Text margin="0 10" color={Colors.White}>
source={Theme.OpenCard}>
<Row style={Theme.Styles.successTag}>
<Icon name="check-circle" color={Theme.Colors.White} size={40} />
<Text margin="0 10" color={Theme.Colors.White}>
{controller.vcLabel.singular} Received
</Text>
</Row>
<Column>
<Column style={Styles.closeDetailsHeader}>
<Column style={Theme.Styles.closeDetailsHeader}>
<Column>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('fullName')}
</Text>
<Text weight="bold" size="smaller">
<Text weight="bold" size="smaller" color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.fullName
)}
</Text>
</Column>
<Image source={MosipLogo} style={Styles.logo} />
<Image source={Theme.MosipLogo} style={Theme.Styles.logo} />
</Column>
<Row style={Styles.openDetailsContainer}>
<Row style={Theme.Styles.openDetailsContainer}>
<ListItem bottomDivider>
<ListItem.Content>
<ListItem.Subtitle>{t('photo')}</ListItem.Subtitle>
@@ -69,28 +66,31 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
source={
props.vc?.credential.biometrics?.face
? { uri: props.vc?.credential.biometrics.face }
: ProfileIcon
: Theme.ProfileIcon
}
style={Styles.openCardImage}
style={Theme.Styles.openCardImage}
/>
</ListItem.Content>
</ListItem.Content>
</ListItem>
<Column style={Styles.details}>
<Column style={Styles.labelPart}>
<Column style={Theme.Styles.details}>
<Column style={Theme.Styles.labelPart}>
<Column
fill
padding="12 16"
margin="0 16 0 0"
style={Styles.labelPart}>
style={Theme.Styles.labelPart}>
<Text
size="smaller"
color={Colors.DetailsText}
color={Theme.Colors.DetailsLabel}
style={{ textTransform: 'uppercase', fontWeight: 'bold' }}>
{props.vc?.idType}
</Text>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{props.vc?.id}
</Text>
</Column>
@@ -98,20 +98,32 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
fill
padding="12 16"
margin="0 16 0 0"
style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('generatedOn')}
</Text>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{new Date(props.vc?.generatedOn).toLocaleDateString()}
</Text>
</Column>
<Column fill padding="12 16" style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
<Column fill padding="12 16" style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('status')}
</Text>
<Row>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{t('valid')}
</Text>
{props.vc?.isVerified && <VerifiedIcon />}
@@ -123,11 +135,17 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
fill
padding="12 16"
margin="0 16 0 0"
style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('gender')}
</Text>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.gender
)}
@@ -138,11 +156,17 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
fill
padding="12 16"
margin="0 16 0 0"
style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('dateOfBirth')}
</Text>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{new Date(
getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.dateOfBirth
@@ -155,11 +179,17 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
fill
padding="12 16"
margin="0 16 0 0"
style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('phoneNumber')}
</Text>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.phone
)}
@@ -170,11 +200,17 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
fill
padding="12 16"
margin="0 16 0 0"
style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('email')}
</Text>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.email
)}
@@ -185,11 +221,17 @@ export const NewVcDetails: React.FC<VcDetailsProps> = (props) => {
fill
padding="12 16"
margin="0 16 0 0"
style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('address')}
</Text>
<Text weight="semibold" size="smaller">
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{getFullAddress(
props.vc?.verifiableCredential.credentialSubject
)}

View File

@@ -3,7 +3,7 @@ import { Dimensions, Modal as RNModal, StyleSheet } from 'react-native';
import { Icon } from 'react-native-elements';
import { PasscodeVerify } from '../components/PasscodeVerify';
import { Column, Text } from '../components/ui';
import { Colors } from '../components/ui/styleUtils';
import { Theme } from '../components/ui/styleUtils';
const styles = StyleSheet.create({
modal: {
@@ -19,8 +19,8 @@ export const Passcode: React.FC<PasscodeProps> = (props) => {
style={styles.modal}
visible={true}
onRequestClose={props.onDismiss}>
<Column fill padding="32" backgroundColor={Colors.White}>
<Icon name="lock" color={Colors.Orange} size={60} />
<Column fill padding="32" backgroundColor={Theme.Colors.White}>
<Icon name="lock" color={Theme.Colors.Icon} size={60} />
<Column fill align="space-between" width="100%">
<Text align="center">Enter your passcode</Text>
<PasscodeVerify
@@ -30,7 +30,7 @@ export const Passcode: React.FC<PasscodeProps> = (props) => {
/>
</Column>
<Column fill>
<Text align="center" color={Colors.Red}>
<Text align="center" color={Theme.Colors.Red}>
{props.error}
</Text>
</Column>

View File

@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import { TextInput } from 'react-native';
import { usePinInput } from '../machines/pinInput';
import { Row } from './ui';
import { Colors, Styles } from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
export const PinInput: React.FC<PinInputProps> = (props) => {
const { state, send, events } = usePinInput(props.length);
@@ -22,8 +22,8 @@ export const PinInput: React.FC<PinInputProps> = (props) => {
selectTextOnFocus
keyboardType="numeric"
maxLength={1}
selectionColor={Colors.Orange}
style={Styles.input}
selectionColor={Theme.Colors.Orange}
style={Theme.Styles.input}
key={index}
ref={input}
value={values[index]}

View File

@@ -3,7 +3,7 @@ import Icon from 'react-native-vector-icons/MaterialIcons';
import { Camera } from 'expo-camera';
import { BarCodeEvent, BarCodeScanner } from 'expo-barcode-scanner';
import { Linking, TouchableOpacity, View } from 'react-native';
import { Colors, Styles } from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
import { Column, Button, Text } from './ui';
import { GlobalContext } from '../shared/GlobalContext';
import { useSelector } from '@xstate/react';
@@ -46,7 +46,7 @@ export const QrScanner: React.FC<QrScannerProps> = (props) => {
if (hasPermission === false) {
return (
<Column fill align="space-between">
<Text align="center" color={Colors.Red}>
<Text align="center" color={Theme.Colors.Red}>
{t('missingPermissionText')}
</Text>
<Button title={t('allowCameraButton')} onPress={openSettings} />
@@ -56,9 +56,9 @@ export const QrScanner: React.FC<QrScannerProps> = (props) => {
return (
<View>
<View style={Styles.scannerContainer}>
<View style={Theme.Styles.scannerContainer}>
<Camera
style={Styles.scanner}
style={Theme.Styles.scanner}
barCodeScannerSettings={{
barcodeTypes: [BarCodeScanner.Constants.BarCodeType.qr],
}}
@@ -68,7 +68,7 @@ export const QrScanner: React.FC<QrScannerProps> = (props) => {
</View>
<Column margin="24 0">
<TouchableOpacity
style={Styles.flipIconButton}
style={Theme.Styles.flipIconButton}
onPress={() => {
setType(
type === Camera.Constants.Type.back
@@ -76,7 +76,7 @@ export const QrScanner: React.FC<QrScannerProps> = (props) => {
: Camera.Constants.Type.back
);
}}>
<Icon name="flip-camera-ios" color={Colors.Black} size={64} />
<Icon name="flip-camera-ios" color={Theme.Colors.Black} size={64} />
</TouchableOpacity>
</Column>
</View>

View File

@@ -1,7 +1,7 @@
import React, { useContext, useRef } from 'react';
import { useInterpret, useSelector } from '@xstate/react';
import { Image, ImageBackground } from 'react-native';
import { CheckBox, Icon } from 'react-native-elements';
import { Icon } from 'react-native-elements';
import { ActorRefFrom } from 'xstate';
import {
createVcItemMachine,
@@ -12,7 +12,7 @@ import {
vcItemMachine,
} from '../machines/vcItem';
import { Column, Row, Text } from './ui';
import { Colors, CloseCard, ProfileIcon, Styles } from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
import { GlobalContext } from '../shared/GlobalContext';
import { useTranslation } from 'react-i18next';
@@ -20,7 +20,7 @@ const VerifiedIcon: React.FC = () => {
return (
<Icon
name="check-circle"
color={Colors.Green}
color={Theme.Colors.Green}
size={14}
containerStyle={{ marginStart: 4, bottom: 1 }}
/>
@@ -45,49 +45,40 @@ export const SingleVcItem: React.FC<VcItemProps> = (props) => {
const context = useSelector(service, selectVerifiableCredential);
const generatedOn = useSelector(service, selectGeneratedOn);
const selectableOrCheck = props.selectable ? (
<CheckBox
checked={props.selected}
checkedIcon={<Icon name="radio-button-checked" />}
uncheckedIcon={<Icon name="radio-button-unchecked" />}
onPress={() => props.onPress(service)}
/>
) : null;
return (
<Column style={Styles.bgContainer} onShow={props.onShow(service)}>
<Column onShow={props.onShow(service)}>
<ImageBackground
source={!context.verifiableCredential ? null : CloseCard}
source={!context.verifiableCredential ? null : Theme.CloseCard}
style={
!context.verifiableCredential
? Styles.loadingContainer
: Styles.closeDetailsContainer
? Theme.Styles.loadingContainer
: Theme.Styles.closeDetailsContainer
}>
<Row
crossAlign="center"
style={
!context.verifiableCredential
? Styles.loadingContainer
: Styles.closeDetailsContainer
? Theme.Styles.loadingContainer
: Theme.Styles.closeDetailsContainer
}>
<Column
style={
!context.verifiableCredential
? Styles.loadingContainer
: Styles.closeDetailsContainer
? Theme.Styles.loadingContainer
: Theme.Styles.closeDetailsContainer
}>
<Image
source={
!context.verifiableCredential
? ProfileIcon
? Theme.ProfileIcon
: { uri: context.credential.biometrics.face }
}
style={Styles.closeCardImage}
style={Theme.Styles.closeCardImage}
/>
<Column margin="0 0 0 50">
<Column>
<Text color={Colors.DetailsText} size="smaller">
<Text color={Theme.Colors.DetailsLabel} size="smaller">
Full name
</Text>
<Text
@@ -95,8 +86,8 @@ export const SingleVcItem: React.FC<VcItemProps> = (props) => {
size="smaller"
style={
!context.verifiableCredential
? Styles.loadingTitle
: Styles.title
? Theme.Styles.loadingTitle
: Theme.Styles.title
}>
{!context.verifiableCredential
? ''
@@ -107,7 +98,7 @@ export const SingleVcItem: React.FC<VcItemProps> = (props) => {
</Column>
<Column>
<Text color={Colors.DetailsText} size="smaller">
<Text color={Theme.Colors.DetailsLabel} size="smaller">
UIN
</Text>
<Text
@@ -115,14 +106,14 @@ export const SingleVcItem: React.FC<VcItemProps> = (props) => {
size="smaller"
style={
!context.verifiableCredential
? Styles.loadingTitle
: Styles.title
? Theme.Styles.loadingTitle
: Theme.Styles.title
}>
{!context.verifiableCredential ? '' : tag || uin}
</Text>
</Column>
<Column>
<Text color={Colors.DetailsText} size="smaller">
<Text color={Theme.Colors.DetailsLabel} size="smaller">
Generated on
</Text>
<Text
@@ -131,14 +122,14 @@ export const SingleVcItem: React.FC<VcItemProps> = (props) => {
size="smaller"
style={
!context.verifiableCredential
? Styles.loadingTitle
: Styles.subtitle
? Theme.Styles.loadingTitle
: Theme.Styles.subtitle
}>
{!context.verifiableCredential ? '' : generatedOn}
</Text>
</Column>
<Column>
<Text size="smaller" color={Colors.DetailsText}>
<Text size="smaller" color={Theme.Colors.DetailsLabel}>
{t('status')}
</Text>
<Row>
@@ -147,8 +138,8 @@ export const SingleVcItem: React.FC<VcItemProps> = (props) => {
size="smaller"
style={
!context.verifiableCredential
? Styles.loadingTitle
: Styles.subtitle
? Theme.Styles.loadingTitle
: Theme.Styles.subtitle
}>
{!context.verifiableCredential ? '' : t('valid')}
</Text>

View File

@@ -2,13 +2,13 @@ import React from 'react';
import { Dimensions, StyleSheet } from 'react-native';
import { Overlay, LinearProgress } from 'react-native-elements';
import { Column, Text } from './ui';
import { Colors, elevation } from './ui/styleUtils';
import { elevation, Theme } from './ui/styleUtils';
import { Icon } from 'react-native-elements';
const styles = StyleSheet.create({
overlay: {
...elevation(5),
backgroundColor: Colors.White,
backgroundColor: Theme.Colors.White,
},
});
@@ -37,7 +37,7 @@ export const TimerBasedMessageOverlay: React.FC<MessageOverlayProps> = (
</Text>
)}
{props.hasProgress && (
<LinearProgress variant="indeterminate" color={Colors.Orange} />
<LinearProgress variant="indeterminate" color={Theme.Colors.Orange} />
)}
</Column>
</Overlay>

View File

@@ -2,24 +2,18 @@ import { formatDistanceToNow } from 'date-fns';
import React from 'react';
import * as DateFnsLocale from '../lib/date-fns/locale';
import { useTranslation } from 'react-i18next';
import { Image, View, ImageBackground } from 'react-native';
import { Icon, ListItem } from 'react-native-elements';
import { Image, ImageBackground } from 'react-native';
import { Icon } from 'react-native-elements';
import { VC, CredentialSubject } from '../types/vc';
import { Column, Row, Text } from './ui';
import {
Colors,
Styles,
ProfileIcon,
MosipLogo,
OpenCard,
} from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
import { TextItem } from './ui/TextItem';
const VerifiedIcon: React.FC = () => {
return (
<Icon
name="check-circle"
color={Colors.Green}
color={Theme.Colors.Green}
size={14}
containerStyle={{ marginStart: 4, bottom: 1 }}
/>
@@ -30,125 +24,145 @@ export const UpdatedVcDetails: React.FC<VcDetailsProps> = (props) => {
const { t, i18n } = useTranslation('VcDetails');
return (
<ImageBackground style={Styles.bgContainer} source={OpenCard}>
<View style={Styles.closeDetailsHeader}>
<View>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
<ImageBackground
borderRadius={10}
style={Theme.Styles.openCardBgContainer}
source={Theme.OpenCard}>
<Row style={Theme.Styles.openDetailsHeader}>
<Column>
<Text weight="bold" size="smaller" color={Theme.Colors.DetailsLabel}>
{t('fullName')}
</Text>
<Text weight="bold" size="smaller">
<Text weight="bold" size="smaller" color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.fullName
)}
</Text>
</View>
<Image source={MosipLogo} style={Styles.logo} />
</View>
</Column>
<Image source={Theme.MosipLogo} style={Theme.Styles.logo} />
</Row>
<Row style={Styles.openDetailsContainer}>
<ListItem bottomDivider>
<ListItem.Content>
<ListItem.Subtitle>{t('photo')}</ListItem.Subtitle>
<ListItem.Content>
<Image
source={
props.vc?.credential.biometrics?.face
? { uri: props.vc?.credential.biometrics.face }
: ProfileIcon
}
style={Styles.openCardImage}
/>
</ListItem.Content>
</ListItem.Content>
</ListItem>
<Row style={Theme.Styles.openDetailsContainer}>
<Image
source={
props.vc?.credential.biometrics?.face
? { uri: props.vc?.credential.biometrics.face }
: Theme.ProfileIcon
}
style={Theme.Styles.openCardImage}
/>
<Column style={Styles.details}>
<Column style={Styles.labelPart}>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{props.vc?.idType}
</Text>
<Text weight="semibold" size="smaller">
{props.vc?.id}
</Text>
</Column>
<Column style={Theme.Styles.labelPartContainer}>
<Column fill>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{props.vc?.idType}
</Text>
<Text weight="semibold" size="smaller" color={Theme.Colors.Details}>
{props.vc?.id}
</Text>
</Column>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{t('generatedOn')}
</Text>
<Text weight="semibold" size="smaller">
{new Date(props.vc?.generatedOn).toLocaleDateString()}
</Text>
</Column>
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('generatedOn')}
</Text>
<Text weight="semibold" size="smaller" color={Theme.Colors.Details}>
{new Date(props.vc?.generatedOn).toLocaleDateString()}
</Text>
</Column>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{t('status')}
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('status')}
</Text>
<Row>
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{t('valid')}
</Text>
<Row>
<Text weight="semibold" size="smaller">
{t('valid')}
</Text>
{props.vc?.isVerified && <VerifiedIcon />}
</Row>
</Column>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{t('gender')}
</Text>
<Text weight="semibold" size="smaller">
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.gender
)}
</Text>
</Column>
{props.vc?.isVerified && <VerifiedIcon />}
</Row>
</Column>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{t('dateOfBirth')}
</Text>
<Text weight="semibold" size="smaller">
{new Date(
getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.dateOfBirth
)
).toLocaleDateString()}
</Text>
</Column>
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('gender')}
</Text>
<Text weight="semibold" size="smaller" color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.gender
)}
</Text>
</Column>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{t('phoneNumber')}
</Text>
<Text weight="semibold" size="smaller">
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.phone
)}
</Text>
</Column>
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('dateOfBirth')}
</Text>
<Text weight="semibold" size="smaller" color={Theme.Colors.Details}>
{new Date(
getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.dateOfBirth
)
).toLocaleDateString()}
</Text>
</Column>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{t('email')}
</Text>
<Text weight="semibold" size="smaller">
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.email
)}
</Text>
</Column>
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('phoneNumber')}
</Text>
<Text weight="semibold" size="smaller" color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.phone
)}
</Text>
</Column>
<Column fill style={Styles.labelPart}>
<Text weight="bold" size="smaller" color={Colors.DetailsText}>
{t('address')}
</Text>
<Text weight="semibold" size="smaller">
{getFullAddress(
props.vc?.verifiableCredential.credentialSubject
)}
</Text>
</Column>
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('email')}
</Text>
<Text weight="semibold" size="smaller" color={Theme.Colors.Details}>
{getLocalizedField(
props.vc?.verifiableCredential.credentialSubject.email
)}
</Text>
</Column>
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('address')}
</Text>
<Text weight="semibold" size="smaller" color={Theme.Colors.Details}>
{getFullAddress(props.vc?.verifiableCredential.credentialSubject)}
</Text>
</Column>
{props.vc?.reason?.length > 0 && (

View File

@@ -12,7 +12,7 @@ import {
vcItemMachine,
} from '../machines/vcItem';
import { Column, Row, Text } from './ui';
import { Colors, CloseCard, ProfileIcon, Styles } from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
import { RotatingIcon } from './RotatingIcon';
import { GlobalContext } from '../shared/GlobalContext';
import { useTranslation } from 'react-i18next';
@@ -21,7 +21,7 @@ const VerifiedIcon: React.FC = () => {
return (
<Icon
name="check-circle"
color={Colors.Green}
color={Theme.Colors.Green}
size={14}
containerStyle={{ marginStart: 4, bottom: 1 }}
/>
@@ -29,17 +29,21 @@ const VerifiedIcon: React.FC = () => {
};
const getDetails = (arg1, arg2, context) => {
if (arg1 === 'Full name') {
if (arg1 === 'Full Name') {
return (
<Column>
<Text color={Colors.DetailsText} size="smaller">
<Text color={Theme.Colors.DetailsLabel} size="smaller">
{arg1}
</Text>
<Text
color={Theme.Colors.Details}
numLines={1}
weight="bold"
size="smaller"
style={
!context.verifiableCredential ? Styles.loadingTitle : Styles.title
!context.verifiableCredential
? Theme.Styles.loadingTitle
: Theme.Styles.subtitle
}>
{!context.verifiableCredential ? '' : arg2}
</Text>
@@ -49,17 +53,18 @@ const getDetails = (arg1, arg2, context) => {
if (arg1 === 'Status') {
return (
<Column>
<Text size="smaller" color={Colors.DetailsText}>
<Text size="smaller" color={Theme.Colors.DetailsLabel}>
{arg1}
</Text>
<Row>
<Text
weight="bold"
color={Theme.Colors.Details}
size="smaller"
style={
!context.verifiableCredential
? Styles.loadingTitle
: Styles.subtitle
? Theme.Styles.loadingTitle
: Theme.Styles.subtitle
}>
{!context.verifiableCredential ? '' : arg2}
</Text>
@@ -70,17 +75,18 @@ const getDetails = (arg1, arg2, context) => {
} else {
return (
<Column>
<Text color={Colors.DetailsText} size="smaller">
<Text color={Theme.Colors.DetailsLabel} size="smaller">
{arg1}
</Text>
<Text
numLines={1}
color={Theme.Colors.Details}
weight="bold"
size="smaller"
style={
!context.verifiableCredential
? Styles.loadingTitle
: Styles.subtitle
? Theme.Styles.loadingTitle
: Theme.Styles.subtitle
}>
{arg2}
</Text>
@@ -124,38 +130,45 @@ export const UpdatedVcItem: React.FC<VcItemProps> = (props) => {
<Pressable
onPress={() => props.onPress(service)}
disabled={!context.verifiableCredential}
style={Styles.bgContainer}>
style={Theme.Styles.closeCardBgContainer}>
<ImageBackground
source={!context.verifiableCredential ? null : CloseCard}
source={!context.verifiableCredential ? null : Theme.CloseCard}
resizeMode="stretch"
style={
!context.verifiableCredential
? Styles.loadingContainer
: Styles.detailsContainer
? Theme.Styles.vertloadingContainer
: Theme.Styles.backgroundImageContainer
}>
<Row style={Theme.Styles.homeCloseCardDetailsHeader}>
<Image
source={Theme.MosipLogo}
style={Theme.Styles.logo}
resizeMethod="auto"
/>
</Row>
<Row
crossAlign="center"
margin="5 0 0 0"
style={
!context.verifiableCredential
? Styles.loadingContainer
: Styles.detailsContainer
!context.verifiableCredential ? Theme.Styles.loadingContainer : null
}>
<Column
style={
!context.verifiableCredential
? Styles.loadingContainer
: Styles.closeDetailsContainer
? Theme.Styles.loadingContainer
: Theme.Styles.closeDetails
}>
<Image
source={
!context.verifiableCredential
? ProfileIcon
? Theme.ProfileIcon
: { uri: context.credential.biometrics.face }
}
style={Styles.closeCardImage}
style={Theme.Styles.closeCardImage}
/>
<Column margin="0 0 0 20">
{getDetails('Full name', fullName, context)}
<Column margin="0 0 0 10">
{getDetails('Full Name', fullName, context)}
{getDetails('UIN', tag || uin, context)}
{getDetails('Generated On', generatedOn, context)}
{getDetails('Status', t('valid'), context)}
@@ -165,7 +178,7 @@ export const UpdatedVcItem: React.FC<VcItemProps> = (props) => {
{context.verifiableCredential ? (
selectableOrCheck
) : (
<RotatingIcon name="sync" color={Colors.Grey5} />
<RotatingIcon name="sync" color={Theme.Colors.Grey5} />
)}
</Row>
</ImageBackground>

View File

@@ -6,14 +6,14 @@ import { Image } from 'react-native';
import { Icon, ListItem } from 'react-native-elements';
import { VC, CredentialSubject } from '../types/vc';
import { Column, Row, Text } from './ui';
import { Colors } from './ui/styleUtils';
import { Theme } from './ui/styleUtils';
import { TextItem } from './ui/TextItem';
const VerifiedIcon: React.FC = () => {
return (
<Icon
name="check-circle"
color={Colors.Green}
color={Theme.Colors.Green}
size={14}
containerStyle={{ marginStart: 4, bottom: 1 }}
/>
@@ -27,7 +27,7 @@ export const VcDetails: React.FC<VcDetailsProps> = (props) => {
<Column>
<Row padding="16 24">
<Column fill elevation={1} padding="12 16" margin="0 16 0 0">
<Text size="smaller" color={Colors.Grey}>
<Text size="smaller" color={Theme.Colors.Grey}>
{t('generatedOn')}
</Text>
<Text weight="bold" size="smaller">
@@ -37,7 +37,7 @@ export const VcDetails: React.FC<VcDetailsProps> = (props) => {
<Column fill elevation={1} padding="12 16" margin="0 16 0 0">
<Text
size="smaller"
color={Colors.Grey}
color={Theme.Colors.Grey}
style={{ textTransform: 'uppercase' }}>
{props.vc?.idType}
</Text>
@@ -46,7 +46,7 @@ export const VcDetails: React.FC<VcDetailsProps> = (props) => {
</Text>
</Column>
<Column fill elevation={1} padding="12 16">
<Text size="smaller" color={Colors.Grey}>
<Text size="smaller" color={Theme.Colors.Grey}>
{t('status')}
</Text>
<Row>

View File

@@ -10,21 +10,21 @@ import {
ViewStyle,
} from 'react-native';
import { Text } from './Text';
import { Colors, spacing } from './styleUtils';
import { Theme, spacing } from './styleUtils';
const styles = StyleSheet.create({
fill: {
flex: 1,
},
solid: {
backgroundColor: Colors.Orange,
backgroundColor: Theme.Colors.AddIdBtnBg,
},
clear: {
backgroundColor: 'transparent',
},
outline: {
backgroundColor: 'transparent',
borderColor: Colors.Orange,
borderColor: Theme.Colors.Orange,
},
container: {
minHeight: 48,
@@ -34,10 +34,10 @@ const styles = StyleSheet.create({
opacity: 0.5,
},
addId: {
backgroundColor: Colors.AddIdBtnBg,
backgroundColor: Theme.Colors.AddIdBtnBg,
},
clearAddIdBtnBg: {
backgroundColor: Colors.ClearAddIdBtnBg,
backgroundColor: Theme.Colors.ClearAddIdBtnBg,
},
});
@@ -68,7 +68,9 @@ export const Button: React.FC<ButtonProps> = (props) => {
weight="semibold"
align="center"
color={
type === 'solid' || type === 'addId' ? Colors.White : Colors.Orange
type === 'solid' || type === 'addId'
? Theme.Colors.White
: Theme.Colors.AddIdBtnTxt
}>
{props.title}
</Text>

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Dimensions, Modal as RNModal, StyleSheet } from 'react-native';
import { Icon } from 'react-native-elements';
import { Column, Row, Text } from '.';
import { Colors, ElevationLevel } from './styleUtils';
import { ElevationLevel, Theme } from './styleUtils';
const styles = StyleSheet.create({
modal: {
@@ -25,7 +25,7 @@ export const Modal: React.FC<ModalProps> = (props) => {
<Icon
name="chevron-left"
onPress={props.onDismiss}
color={Colors.Orange}
color={Theme.Colors.Icon}
/>
) : null}

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Dimensions, Modal as RNModal, StyleSheet } from 'react-native';
import { Icon } from 'react-native-elements';
import { Column, Row } from '.';
import { Colors, ElevationLevel } from './styleUtils';
import { Theme, ElevationLevel } from './styleUtils';
const styles = StyleSheet.create({
modal: {
@@ -24,20 +24,9 @@ export const Modal: React.FC<ModalProps> = (props) => {
<Icon
name="chevron-left"
onPress={props.onDismiss}
color={Colors.Orange}
color={Theme.Colors.Orange}
/>
) : null}
{/* <Row fill align="center">
<Text weight="semibold">{props.headerTitle}</Text>
</Row> */}
{/* {props.headerRight || (
<Icon //Modal closing Nav-bar part
name="close"
onPress={props.onDismiss}
color={Colors.Orange}
/>
)} */}
</Row>
{props.children}
</Column>

View File

@@ -1,11 +1,9 @@
import { ViewStyle, StyleSheet } from 'react-native';
import { ViewStyle } from 'react-native';
import { DefaultTheme } from './themes/DefaultTheme';
export const Theme = DefaultTheme;
export const Colors = {
TabItemText: '#F2811D',
DetailsText: '#F2811D',
AddIdBtnBg: '#F2811D',
ClearAddIdBtnBg: 'transparent',
IconBg: '#F2811D',
Black: '#231F20',
Grey: '#B0B0B0',
Grey5: '#E0E0E0',
@@ -17,165 +15,6 @@ export const Colors = {
Green: '#219653',
};
export const OpenCard = require('../../assets/ID-open.png');
export const CloseCard = require('../../assets/ID-closed.png');
export const ProfileIcon = require('../../assets/placeholder-photo.png');
export const MosipLogo = require('../../assets/mosip-logo.png');
export const Styles = StyleSheet.create({
title: {
color: Colors.Black,
backgroundColor: 'transparent',
},
loadingTitle: {
color: 'transparent',
backgroundColor: Colors.Grey5,
borderRadius: 4,
},
subtitle: {
backgroundColor: 'transparent',
},
loadingSubtitle: {
backgroundColor: Colors.Grey,
borderRadius: 4,
},
detailsContainer: {
borderRadius: 10,
},
loadingContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: Colors.Grey6,
borderRadius: 4,
margin: 5,
},
closeDetailsContainer: {
flex: 1,
flexDirection: 'row',
padding: 10,
},
logoContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
marginLeft: 300,
},
bgContainer: {
borderRadius: 10,
margin: 5,
backgroundColor: '#fff',
shadowColor: '#000',
shadowOffset: { width: -1, height: 1 },
shadowOpacity: 0.4,
shadowRadius: 3,
elevation: 4,
},
successTag: {
backgroundColor: Colors.Green,
height: 43,
flex: 1,
alignItems: 'center',
paddingLeft: 6,
},
closeDetailsHeader: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingLeft: 18,
margin: 6,
},
logo: {
height: 48,
width: 40,
marginRight: 10,
},
openDetailsContainer: {
flex: 2,
padding: 10,
},
details: {
width: 290,
marginLeft: 110,
marginTop: 0,
},
labelPart: {
borderRadius: 0,
borderWidth: 0,
width: 240,
borderBottomWidth: 0,
backgroundColor: 'transparent',
marginLeft: 4,
paddingTop: 10,
paddingBottom: 10,
paddingLeft: 15,
paddingRight: 15,
},
closeCardImage: {
width: 130,
height: 150,
resizeMode: 'cover',
},
openCardImage: {
width: 130,
height: 160,
resizeMode: 'cover',
borderRadius: 5,
marginTop: -25,
marginLeft: -14,
padding: 10,
},
input: {
borderBottomWidth: 1,
borderColor: Colors.Grey,
color: Colors.Black,
flex: 1,
fontFamily: 'Poppins_600SemiBold',
fontSize: 18,
fontWeight: '600',
height: 40,
lineHeight: 28,
margin: 8,
textAlign: 'center',
},
scannerContainer: {
borderWidth: 4,
borderColor: Colors.Black,
borderRadius: 32,
justifyContent: 'center',
height: 300,
width: 300,
overflow: 'hidden',
},
scanner: {
height: 400,
width: '100%',
margin: 'auto',
},
flipIconButton: {
alignSelf: 'center',
alignItems: 'center',
},
tabIndicator: {
backgroundColor: Colors.Orange,
},
tabContainer: {
backgroundColor: 'transparent',
justifyContent: 'center',
},
tabView: {
flex: 1,
},
detailsText: {
fontWeight: 'bold',
fontSize: 15,
fontFamily: 'Poppins_700Bold',
},
});
export function spacing(type: 'margin' | 'padding', values: string) {
const [top, end, bottom, start] = values.split(' ').map(Number);

View File

@@ -0,0 +1,66 @@
# CSS Themes
We can customize the application by adding a new file under components/ui/themes and import that file in components/ui/styleUtils.ts and assign that file to Theme variable
```
components/ui/styleUtils.ts
eg:-
import { PurpleTheme } from './PurpleTheme';
export const Theme = PurpleTheme;
```
## **Logo and Background Images :**
To change the mosip logo
```
MosipLogo = require(path of logo you want to use, in string format)
*logo can be png or svg
eg:-
MosipLogo = require('../../assets/mosip-logo.png')
```
To change the profile logo which is available as a demo while loading the vc details
```
ProfileIcon = require(path of logo you want to use, in string format)
*logo can be png or svg
eg:-
ProfileIcon: require('../../assets/placeholder-photo.png')
```
To change the close card details background
```
CloseCard = require(path of image you want to use, in string format)
*Image can be png or svg
-width: 363 pixels
-height: 236 pixels
eg:-
CloseCard: require('../../assets/ID-closed.png')
```
To change the OpenCard card details background
```
OpenCard = require(path of image you want to use, in string format)
*Image can be png or svg
-width: 363 pixels
-height: 623 pixels
eg:-
OpenCard: require('../../assets/ID-open.png')
```
## **Colors :**
To change the color of

View File

@@ -0,0 +1,260 @@
import { StyleSheet } from 'react-native';
const colors = {
Black: '#231F20',
Grey: '#B0B0B0',
Grey5: '#E0E0E0',
Grey6: '#F2F2F2',
Orange: '#F2811D',
LightGrey: '#FAF9FF',
White: '#FFFFFF',
Red: '#EB5757',
Green: '#219653',
Transparent: 'transparent',
};
export const DefaultTheme = {
Colors: {
TabItemText: colors.Orange,
Details: colors.Black,
DetailsLabel: colors.Orange,
AddIdBtnBg: colors.Orange,
AddIdBtnTxt: colors.Orange,
ClearAddIdBtnBg: colors.Transparent,
Loading: colors.Orange,
noUinText: colors.Orange,
IconBg: colors.Orange,
Icon: colors.Orange,
Black: '#231F20',
Grey: '#B0B0B0',
Grey5: '#E0E0E0',
Grey6: '#F2F2F2',
Orange: '#F2811D',
LightGrey: '#FAF9FF',
White: '#FFFFFF',
Red: '#EB5757',
Green: '#219653',
},
Styles: StyleSheet.create({
title: {
color: colors.Black,
backgroundColor: colors.Transparent,
},
loadingTitle: {
color: colors.Transparent,
backgroundColor: colors.Grey,
borderRadius: 4,
},
subtitle: {
backgroundColor: colors.Transparent,
},
loadingSubtitle: {
backgroundColor: colors.Grey,
borderRadius: 4,
},
closeDetails: {
flex: 1,
flexDirection: 'row',
paddingRight: 90,
},
loadingContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: colors.Grey6,
borderRadius: 4,
},
vertloadingContainer: {
flex: 1,
backgroundColor: colors.Grey6,
borderRadius: 4,
padding: 5,
},
closeDetailsContainer: {
flex: 1,
justifyContent: 'flex-start',
},
logoContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
marginLeft: 300,
},
closeCardBgContainer: {
borderRadius: 10,
margin: 8,
backgroundColor: '#fff',
shadowColor: '#000',
shadowOffset: { width: -1, height: 1 },
shadowOpacity: 0.4,
shadowRadius: 3,
elevation: 4,
},
labelPartContainer: {
marginLeft: 16,
},
labelPart: {
marginTop: 10,
},
openCardBgContainer: {
borderRadius: 10,
margin: 8,
backgroundColor: '#fff',
shadowColor: '#000',
shadowOffset: { width: -1, height: 1 },
shadowOpacity: 0.4,
shadowRadius: 3,
elevation: 4,
padding: 10,
},
backgroundImageContainer: {
flex: 1,
padding: 10,
},
successTag: {
backgroundColor: colors.Green,
height: 43,
flex: 1,
alignItems: 'center',
paddingLeft: 6,
},
closeDetailsHeader: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingLeft: 18,
margin: 6,
},
openDetailsHeader: {
flex: 1,
justifyContent: 'space-between',
},
logo: {
height: 30,
width: 30,
},
homeCloseCardDetailsHeader: {
flex: 1,
justifyContent: 'flex-end',
},
details: {
width: 290,
marginLeft: 110,
marginTop: 0,
},
openDetailsContainer: {
flex: 1,
justifyContent: 'space-between',
padding: 10,
},
closeCardImage: {
width: 100,
height: 100,
borderRadius: 5,
},
openCardImage: {
width: 100,
height: 100,
borderRadius: 5,
},
input: {
borderBottomWidth: 1,
borderColor: colors.Grey,
color: colors.Black,
flex: 1,
fontFamily: 'Poppins_600SemiBold',
fontSize: 18,
fontWeight: '600',
height: 40,
lineHeight: 28,
margin: 8,
textAlign: 'center',
},
scannerContainer: {
borderWidth: 4,
borderColor: colors.Black,
borderRadius: 32,
justifyContent: 'center',
height: 300,
width: 300,
overflow: 'hidden',
},
scanner: {
height: 400,
width: '100%',
margin: 'auto',
},
flipIconButton: {
alignSelf: 'center',
alignItems: 'center',
},
tabIndicator: {
backgroundColor: colors.Orange,
},
tabContainer: {
backgroundColor: colors.Transparent,
justifyContent: 'center',
},
tabView: {
flex: 1,
},
detailsText: {
fontWeight: 'bold',
fontSize: 15,
fontFamily: 'Poppins_700Bold',
},
getId: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 10,
},
placeholder: {
fontFamily: 'Poppins_400Regular',
},
overlay: {
padding: 24,
bottom: 86,
backgroundColor: colors.Transparent,
shadowColor: colors.Transparent,
},
slide: {
width: '100%',
padding: 20,
},
slider: {
backgroundColor: colors.Orange,
minHeight: 280,
width: '100%',
margin: 0,
borderRadius: 4,
},
appSlider: {},
sliderTitle: {
color: colors.White,
marginBottom: 20,
fontFamily: 'Poppins_700Bold',
},
text: {
color: colors.White,
},
paginationContainer: {
margin: 10,
},
paginationDots: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 20,
},
closeIcon: {
alignItems: 'flex-end',
end: 16,
top: 40,
zIndex: 1,
},
}),
OpenCard: require('../../../assets/ID-open.png'),
CloseCard: require('../../../assets/ID-closed.png'),
ProfileIcon: require('../../../assets/placeholder-photo.png'),
MosipLogo: require('../../../assets/mosip-logo.png'),
};

View File

@@ -0,0 +1,259 @@
import { StyleSheet } from 'react-native';
const colors = {
Black: '#231F20',
Grey: '#B0B0B0',
Grey5: '#E0E0E0',
Grey6: '#F2F2F2',
Orange: '#F2811D',
LightGrey: '#FAF9FF',
White: '#FFFFFF',
Red: '#EB5757',
Green: '#219653',
Purple: '#70308C',
};
export const PurpleTheme = {
Colors: {
TabItemText: colors.Purple,
Details: colors.White,
DetailsLabel: colors.White,
AddIdBtnBg: colors.Purple,
AddIdBtnTxt: colors.Purple,
ClearAddIdBtnBg: 'transparent',
noUinText: colors.Purple,
IconBg: colors.Purple,
Icon: colors.Purple,
Loading: colors.Purple,
Black: '#231F20',
Grey: '#B0B0B0',
Grey5: '#E0E0E0',
Grey6: '#F2F2F2',
Orange: '#F2811D',
LightGrey: '#FAF9FF',
White: '#FFFFFF',
Red: '#EB5757',
Green: '#219653',
Purple: '#70308C',
},
Styles: StyleSheet.create({
title: {
color: '#231F20',
backgroundColor: 'transparent',
},
loadingTitle: {
color: 'transparent',
backgroundColor: '#B0B0B0',
borderRadius: 4,
},
subtitle: {
backgroundColor: 'transparent',
},
loadingSubtitle: {
backgroundColor: '#B0B0B0',
borderRadius: 4,
},
closeDetails: {
flex: 1,
flexDirection: 'row',
paddingRight: 90,
},
loadingContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: '#F2F2F2',
borderRadius: 4,
margin: 5,
},
vertloadingContainer: {
flex: 1,
backgroundColor: '#F2F2F2',
borderRadius: 4,
margin: 5,
},
closeDetailsContainer: {
flex: 1,
justifyContent: 'flex-start',
},
logoContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
marginLeft: 300,
},
closeCardBgContainer: {
marginBottom: 10,
backgroundColor: '#fff',
shadowColor: '#000',
shadowOffset: { width: -1, height: 1 },
shadowOpacity: 0.4,
shadowRadius: 3,
elevation: 4,
},
labelPartContainer: {
marginLeft: 16,
},
labelPart: {
marginTop: 10,
},
openCardBgContainer: {
margin: 8,
shadowColor: '#000',
shadowOffset: { width: -1, height: 1 },
shadowOpacity: 1,
shadowRadius: 3,
elevation: 5,
padding: 10,
},
backgroundImageContainer: {
flex: 1,
padding: 10,
},
successTag: {
backgroundColor: '#219653',
height: 43,
flex: 1,
alignItems: 'center',
paddingLeft: 6,
},
closeDetailsHeader: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingLeft: 18,
margin: 6,
},
openDetailsHeader: {
flex: 1,
justifyContent: 'space-between',
},
homeCloseCardDetailsHeader: {
flex: 1,
justifyContent: 'space-between',
},
logo: {
height: 30,
width: 30,
},
openDetailsContainer: {
flex: 1,
justifyContent: 'space-between',
padding: 10,
},
closeCardImage: {
width: 100,
height: 100,
borderRadius: 5,
},
details: {
width: 290,
marginLeft: 110,
marginTop: 0,
},
openCardImage: {
width: 100,
height: 100,
borderRadius: 5,
},
input: {
borderBottomWidth: 1,
borderColor: '#B0B0B0',
color: '#231F20',
flex: 1,
fontFamily: 'Poppins_600SemiBold',
fontSize: 18,
fontWeight: '600',
height: 40,
lineHeight: 28,
margin: 8,
textAlign: 'center',
},
scannerContainer: {
borderWidth: 4,
borderColor: '#231F20',
borderRadius: 32,
justifyContent: 'center',
height: 300,
width: 300,
overflow: 'hidden',
},
scanner: {
height: 400,
width: '100%',
margin: 'auto',
},
flipIconButton: {
alignSelf: 'center',
alignItems: 'center',
},
tabIndicator: {
backgroundColor: '#70308C',
},
tabContainer: {
backgroundColor: 'transparent',
justifyContent: 'center',
},
tabView: {
flex: 1,
},
detailsText: {
fontWeight: 'bold',
fontSize: 15,
fontFamily: 'Poppins_700Bold',
},
getId: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 10,
},
placeholder: {
fontFamily: 'Poppins_400Regular',
},
overlay: {
padding: 24,
bottom: 86,
backgroundColor: 'transparent',
shadowColor: 'transparent',
},
slide: {
width: '100%',
padding: 20,
},
slider: {
backgroundColor: '#70308C',
minHeight: 280,
width: '100%',
margin: 0,
borderRadius: 4,
},
appSlider: {},
sliderTitle: {
color: '#FFFFFF',
marginBottom: 20,
fontFamily: 'Poppins_700Bold',
},
text: {
color: '#FFFFFF',
},
paginationContainer: {
margin: 10,
},
paginationDots: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 20,
},
closeIcon: {
alignItems: 'flex-end',
end: 16,
top: 40,
zIndex: 1,
},
}),
OpenCard: require('../../../purpleAassets/bg_cart_one.png'),
CloseCard: require('../../../purpleAassets/cart_unsel.png'),
ProfileIcon: require('../../../purpleAassets/profile_icon_unsel.png'),
MosipLogo: require('../../../purpleAassets/logo.png'),
};

View File

@@ -67,6 +67,22 @@
}
}
},
"GetVcModal": {
"retrievingId": "Retrieving UID/VID...",
"applicationProcessing": "Your application is still being processed. Please try again after a few days",
"errors": {
"input": {
"empty": "The input cannot be empty",
"invalidFormat": "The input format is incorrect"
},
"backend": {
"invalidOtp": "OTP is invalid",
"applicationProcessing": "Your application is still being processed. Please try again after a few days",
"invalidAid": "AID is not ready",
"timeOut": "Requesting Time Out"
}
}
},
"DownloadingVcModal": {
"header": "Downloading your {{vcLabel}}",
"bodyText": "This may take some time, we will notify you when your {{vcLabel}} has been downloaded and is available",
@@ -75,7 +91,13 @@
"IdInputModal": {
"header": "Enter the MOSIP-provided UIN or VID of the {{vcLabel}} you wish to retrieve",
"generateVc": "Generate {{vcLabel}}",
"enterId": "Enter your {{idType}}"
"enterId": "Enter your {{idType}}",
"noUIN/VID": "Don't have your UIN/VID? Get it here"
},
"GetIdInputModal": {
"header": "To retrieve your UIN or VID, enter your Application {{vcLabel}} number",
"getUIN": "Get UIN/VID",
"applicationId": "Application {{vcLabel}} number"
},
"OtpVerificationModal": {
"enterOtp": "Enter the 6-digit verification code we sent you"

View File

@@ -2,24 +2,14 @@
export interface Typegen0 {
'@@xstate/typegen': true;
'eventsCausingActions': {
setAppInfo: 'APP_INFO_RECEIVED';
setBackendInfo: 'BACKEND_INFO_RECEIVED';
requestDeviceInfo: 'REQUEST_DEVICE_INFO';
spawnStoreActor: 'xstate.init';
logStoreEvents: 'xstate.init';
spawnServiceActors: 'READY';
logServiceEvents: 'READY';
forwardToServices: 'ACTIVE' | 'INACTIVE' | 'ONLINE' | 'OFFLINE';
};
'internalEvents': {
'xstate.init': { type: 'xstate.init' };
};
'invokeSrcNameMap': {
getAppInfo: 'done.invoke.app.init.info:invocation[0]';
getBackendInfo: 'done.invoke.app.init.devinfo:invocation[0]';
checkFocusState: 'done.invoke.app.ready.focus:invocation[0]';
checkNetworkState: 'done.invoke.app.ready.network:invocation[0]';
getAppInfo: 'done.invoke.app.init.info:invocation[0]';
getBackendInfo: 'done.invoke.app.init.devinfo:invocation[0]';
};
'missingImplementations': {
actions: never;
@@ -27,37 +17,47 @@ export interface Typegen0 {
guards: never;
delays: never;
};
'eventsCausingActions': {
forwardToServices: 'ACTIVE' | 'INACTIVE' | 'OFFLINE' | 'ONLINE';
logServiceEvents: 'READY';
logStoreEvents: 'xstate.init';
requestDeviceInfo: 'REQUEST_DEVICE_INFO';
setAppInfo: 'APP_INFO_RECEIVED';
setBackendInfo: 'BACKEND_INFO_RECEIVED';
spawnServiceActors: 'READY';
spawnStoreActor: 'xstate.init';
};
'eventsCausingServices': {
checkFocusState: 'BACKEND_INFO_RECEIVED';
checkNetworkState: 'BACKEND_INFO_RECEIVED';
getAppInfo: 'READY';
getBackendInfo: 'APP_INFO_RECEIVED';
checkFocusState: 'xstate.init';
checkNetworkState: 'xstate.init';
};
'eventsCausingGuards': {};
'eventsCausingDelays': {};
'matchesStates':
| 'init'
| 'init.store'
| 'init.services'
| 'init.info'
| 'init.devinfo'
| 'init.info'
| 'init.services'
| 'init.store'
| 'ready'
| 'ready.focus'
| 'ready.focus.checking'
| 'ready.focus.active'
| 'ready.focus.checking'
| 'ready.focus.inactive'
| 'ready.network'
| 'ready.network.checking'
| 'ready.network.online'
| 'ready.network.offline'
| 'ready.network.online'
| {
init?: 'store' | 'services' | 'info' | 'devinfo';
init?: 'devinfo' | 'info' | 'services' | 'store';
ready?:
| 'focus'
| 'network'
| {
focus?: 'checking' | 'active' | 'inactive';
network?: 'checking' | 'online' | 'offline';
focus?: 'active' | 'checking' | 'inactive';
network?: 'checking' | 'offline' | 'online';
};
};
'tags': never;

View File

@@ -2,46 +2,20 @@
export interface Typegen0 {
'@@xstate/typegen': true;
'eventsCausingActions': {
setReceiverInfo: 'RECEIVE_DEVICE_INFO';
setSenderInfo: 'EXCHANGE_DONE';
setIncomingVc: 'VC_RECEIVED';
removeLoggers:
| 'SCREEN_BLUR'
| 'xstate.after(CLEAR_DELAY)#clearingConnection'
| 'DISMISS'
| 'GOBACK';
disconnect: '';
registerLoggers:
| 'xstate.after(CLEAR_DELAY)#clearingConnection'
| 'DISMISS'
| 'GOBACK';
generateConnectionParams:
| 'xstate.after(CLEAR_DELAY)#clearingConnection'
| 'DISMISS'
| 'GOBACK';
requestReceiverInfo: 'CONNECTED';
requestReceivedVcs: 'xstate.init';
requestExistingVc: 'VC_RESPONSE';
mergeIncomingVc: 'STORE_RESPONSE';
prependReceivedVc: 'VC_RESPONSE';
storeVc: 'STORE_RESPONSE';
sendVcReceived: 'STORE_RESPONSE';
logReceived: 'STORE_RESPONSE';
};
'internalEvents': {
'': { type: '' };
'xstate.after(CLEAR_DELAY)#clearingConnection': {
type: 'xstate.after(CLEAR_DELAY)#clearingConnection';
};
'': { type: '' };
'xstate.init': { type: 'xstate.init' };
'xstate.stop': { type: 'xstate.stop' };
};
'invokeSrcNameMap': {
checkBluetoothService: 'done.invoke.request.checkingBluetoothService.checking:invocation[0]';
requestBluetooth: 'done.invoke.request.checkingBluetoothService.requesting:invocation[0]';
advertiseDevice: 'done.invoke.waitingForConnection:invocation[0]';
checkBluetoothService: 'done.invoke.request.checkingBluetoothService.checking:invocation[0]';
exchangeDeviceInfo: 'done.invoke.request.exchangingDeviceInfo:invocation[0]';
receiveVc: 'done.invoke.request.waitingForVc:invocation[0]';
requestBluetooth: 'done.invoke.request.checkingBluetoothService.requesting:invocation[0]';
sendVcResponse:
| 'done.invoke.accepted:invocation[0]'
| 'done.invoke.request.reviewing.rejected:invocation[0]';
@@ -52,60 +26,90 @@ export interface Typegen0 {
guards: never;
delays: never;
};
'eventsCausingActions': {
disconnect:
| ''
| 'DISMISS'
| 'GOBACK'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'xstate.stop';
generateConnectionParams:
| 'DISMISS'
| 'xstate.after(CLEAR_DELAY)#clearingConnection';
logReceived: 'STORE_RESPONSE';
mergeIncomingVc: 'STORE_RESPONSE';
prependReceivedVc: 'VC_RESPONSE';
registerLoggers: 'DISMISS' | 'xstate.after(CLEAR_DELAY)#clearingConnection';
removeLoggers:
| 'DISMISS'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'xstate.after(CLEAR_DELAY)#clearingConnection'
| 'xstate.init';
requestExistingVc: 'VC_RESPONSE';
requestReceivedVcs: 'ACCEPT';
requestReceiverInfo: 'CONNECTED';
sendVcReceived: 'STORE_RESPONSE';
setIncomingVc: 'VC_RECEIVED';
setReceiverInfo: 'RECEIVE_DEVICE_INFO';
setSenderInfo: 'EXCHANGE_DONE';
storeVc: 'STORE_RESPONSE';
};
'eventsCausingServices': {
checkBluetoothService: 'xstate.init';
requestBluetooth: 'BLUETOOTH_DISABLED';
advertiseDevice: 'xstate.after(CLEAR_DELAY)#clearingConnection' | 'DISMISS';
advertiseDevice: 'DISMISS' | 'xstate.after(CLEAR_DELAY)#clearingConnection';
checkBluetoothService: 'SCREEN_FOCUS';
exchangeDeviceInfo: 'RECEIVE_DEVICE_INFO';
receiveVc: 'EXCHANGE_DONE';
sendVcResponse: 'REJECT' | 'CANCEL' | 'STORE_RESPONSE';
requestBluetooth: 'BLUETOOTH_DISABLED';
sendVcResponse: 'CANCEL' | 'REJECT' | 'STORE_RESPONSE';
};
'eventsCausingGuards': {
hasExistingVc: 'VC_RESPONSE';
};
'eventsCausingDelays': {
CLEAR_DELAY: 'xstate.init';
CLEAR_DELAY: '' | 'GOBACK';
};
'matchesStates':
| 'inactive'
| 'bluetoothDenied'
| 'checkingBluetoothService'
| 'checkingBluetoothService.checking'
| 'checkingBluetoothService.requesting'
| 'checkingBluetoothService.enabled'
| 'bluetoothDenied'
| 'checkingBluetoothService.requesting'
| 'clearingConnection'
| 'waitingForConnection'
| 'preparingToExchangeInfo'
| 'disconnected'
| 'exchangingDeviceInfo'
| 'waitingForVc'
| 'inactive'
| 'preparingToExchangeInfo'
| 'reviewing'
| 'reviewing.idle'
| 'reviewing.accepted'
| 'reviewing.accepting'
| 'reviewing.accepting.requestingReceivedVcs'
| 'reviewing.accepting.requestingExistingVc'
| 'reviewing.accepting.mergingIncomingVc'
| 'reviewing.accepting.prependingReceivedVc'
| 'reviewing.accepting.requestingExistingVc'
| 'reviewing.accepting.requestingReceivedVcs'
| 'reviewing.accepting.storingVc'
| 'reviewing.accepted'
| 'reviewing.rejected'
| 'reviewing.idle'
| 'reviewing.navigatingToHome'
| 'reviewing.navigatingToTimeBasedRequest'
| 'disconnected'
| 'reviewing.rejected'
| 'waitingForConnection'
| 'waitingForVc'
| {
checkingBluetoothService?: 'checking' | 'requesting' | 'enabled';
checkingBluetoothService?: 'checking' | 'enabled' | 'requesting';
reviewing?:
| 'idle'
| 'accepting'
| 'accepted'
| 'rejected'
| 'accepting'
| 'idle'
| 'navigatingToHome'
| 'navigatingToTimeBasedRequest'
| 'rejected'
| {
accepting?:
| 'requestingReceivedVcs'
| 'requestingExistingVc'
| 'mergingIncomingVc'
| 'prependingReceivedVc'
| 'requestingExistingVc'
| 'requestingReceivedVcs'
| 'storingVc';
};
};

View File

@@ -2,39 +2,17 @@
export interface Typegen0 {
'@@xstate/typegen': true;
'eventsCausingActions': {
openSettings: 'LOCATION_REQUEST';
setConnectionParams: 'SCAN';
setSenderInfo: 'RECEIVE_DEVICE_INFO';
setReceiverInfo: 'EXCHANGE_DONE';
setReason: 'UPDATE_REASON';
setSelectedVc: 'SELECT_VC';
removeLoggers:
| 'SCREEN_BLUR'
| 'xstate.after(CLEAR_DELAY)#clearingConnection'
| 'CANCEL'
| 'DISMISS';
requestToDisableFlightMode: 'FLIGHT_REQUEST';
requestToEnableLocation: 'LOCATION_DISABLED' | 'LOCATION_REQUEST';
disconnect: 'LOCATION_ENABLED';
registerLoggers:
| 'xstate.after(CLEAR_DELAY)#clearingConnection'
| 'CANCEL'
| 'DISMISS';
requestSenderInfo: 'SCAN';
clearReason: 'xstate.init';
logShared: 'VC_ACCEPTED';
};
'internalEvents': {
'xstate.after(CLEAR_DELAY)#clearingConnection': {
type: 'xstate.after(CLEAR_DELAY)#clearingConnection';
};
'xstate.init': { type: 'xstate.init' };
'xstate.stop': { type: 'xstate.stop' };
};
'invokeSrcNameMap': {
checkAirplaneMode: 'done.invoke.scan.checkingAirplaneMode.checkingStatus:invocation[0]';
checkLocationStatus: 'done.invoke.checkingLocationService:invocation[0]';
checkLocationPermission: 'done.invoke.scan.checkingLocationService.checkingPermission:invocation[0]';
checkLocationStatus: 'done.invoke.checkingLocationService:invocation[0]';
discoverDevice: 'done.invoke.scan.connecting:invocation[0]';
exchangeDeviceInfo: 'done.invoke.scan.exchangingDeviceInfo:invocation[0]';
sendVc: 'done.invoke.scan.reviewing.sendingVc:invocation[0]';
@@ -45,10 +23,48 @@ export interface Typegen0 {
guards: never;
delays: never;
};
'eventsCausingActions': {
clearReason:
| 'CANCEL'
| 'DISCONNECT'
| 'DISMISS'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'xstate.stop';
disconnect:
| 'CANCEL'
| 'DISCONNECT'
| 'DISMISS'
| 'LOCATION_ENABLED'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'xstate.stop';
logShared: 'VC_ACCEPTED';
openSettings: 'LOCATION_REQUEST';
registerLoggers:
| 'CANCEL'
| 'DISMISS'
| 'xstate.after(CLEAR_DELAY)#clearingConnection';
removeLoggers:
| 'CANCEL'
| 'DISMISS'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'xstate.after(CLEAR_DELAY)#clearingConnection'
| 'xstate.init';
requestSenderInfo: 'SCAN';
requestToDisableFlightMode: 'FLIGHT_REQUEST';
requestToEnableLocation: 'LOCATION_DISABLED' | 'LOCATION_REQUEST';
setConnectionParams: 'SCAN';
setReason: 'UPDATE_REASON';
setReceiverInfo: 'EXCHANGE_DONE';
setSelectedVc: 'SELECT_VC';
setSenderInfo: 'RECEIVE_DEVICE_INFO';
};
'eventsCausingServices': {
checkAirplaneMode: 'APP_ACTIVE';
checkAirplaneMode: 'APP_ACTIVE' | 'FLIGHT_ENABLED' | 'SCREEN_FOCUS';
checkLocationPermission: 'APP_ACTIVE' | 'LOCATION_ENABLED';
checkLocationStatus: 'FLIGHT_DISABLED';
checkLocationPermission: 'LOCATION_ENABLED' | 'APP_ACTIVE';
discoverDevice: 'RECEIVE_DEVICE_INFO';
exchangeDeviceInfo: 'CONNECTED';
sendVc: 'SELECT_VC';
@@ -57,54 +73,54 @@ export interface Typegen0 {
isQrValid: 'SCAN';
};
'eventsCausingDelays': {
CLEAR_DELAY: 'xstate.init';
CLEAR_DELAY: 'LOCATION_ENABLED';
};
'matchesStates':
| 'inactive'
| 'checkingAirplaneMode'
| 'checkingAirplaneMode.checkingStatus'
| 'checkingAirplaneMode.requestingToDisable'
| 'checkingAirplaneMode.enabled'
| 'checkingAirplaneMode.requestingToDisable'
| 'checkingLocationService'
| 'checkingLocationService.checkingStatus'
| 'checkingLocationService.requestingToEnable'
| 'checkingLocationService.checkingPermission'
| 'checkingLocationService.checkingStatus'
| 'checkingLocationService.denied'
| 'checkingLocationService.disabled'
| 'checkingLocationService.requestingToEnable'
| 'clearingConnection'
| 'findingConnection'
| 'preparingToConnect'
| 'connecting'
| 'disconnected'
| 'exchangingDeviceInfo'
| 'findingConnection'
| 'inactive'
| 'invalid'
| 'preparingToConnect'
| 'reviewing'
| 'reviewing.accepted'
| 'reviewing.cancelled'
| 'reviewing.idle'
| 'reviewing.navigatingToHome'
| 'reviewing.rejected'
| 'reviewing.selectingVc'
| 'reviewing.sendingVc'
| 'reviewing.accepted'
| 'reviewing.rejected'
| 'reviewing.cancelled'
| 'reviewing.navigatingToHome'
| 'disconnected'
| 'invalid'
| {
checkingAirplaneMode?:
| 'checkingStatus'
| 'requestingToDisable'
| 'enabled';
| 'enabled'
| 'requestingToDisable';
checkingLocationService?:
| 'checkingStatus'
| 'requestingToEnable'
| 'checkingPermission'
| 'checkingStatus'
| 'denied'
| 'disabled';
| 'disabled'
| 'requestingToEnable';
reviewing?:
| 'idle'
| 'selectingVc'
| 'sendingVc'
| 'accepted'
| 'rejected'
| 'cancelled'
| 'navigatingToHome';
| 'idle'
| 'navigatingToHome'
| 'rejected'
| 'selectingVc'
| 'sendingVc';
};
'tags': never;
}

View File

@@ -89,7 +89,6 @@
"name": "mosip-resident-app",
"version": "1.0.0",
"lint-staged": {
"*.{ts,tsx}": "eslint --cache --fix",
"*.{ts,tsx,js,css,md}": "prettier --write",
"*.strings.json": "node scripts/compile-strings.js"
}

BIN
purpleAassets/_cart_sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
purpleAassets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
purpleAassets/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -8,7 +8,7 @@ import { LanguageSelector } from '../components/LanguageSelector';
import { authRoutes, baseRoutes } from '../routes';
import { useAppLayout } from './AppLayoutController';
import { Icon } from 'react-native-elements';
import { Colors } from '../components/ui/styleUtils';
import { Theme } from '../components/ui/styleUtils';
const { Navigator, Screen } = createNativeStackNavigator();
@@ -21,7 +21,7 @@ export const AppLayout: React.FC = () => {
headerShadowVisible: false,
headerRight: () => (
<LanguageSelector
triggerComponent={<Icon name="language" color={Colors.Orange} />}
triggerComponent={<Icon name="language" color={Theme.Colors.Icon} />}
/>
),
headerBackVisible: false,

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { Icon } from 'react-native-elements';
import { MessageOverlay } from '../components/MessageOverlay';
import { Button, Centered, Column, Text } from '../components/ui';
import { Colors } from '../components/ui/styleUtils';
import { Theme } from '../components/ui/styleUtils';
import { RootRouteProps } from '../routes';
import { useAuthScreen } from './AuthScreenController';
@@ -12,7 +12,7 @@ export const AuthScreen: React.FC<RootRouteProps> = (props) => {
const controller = useAuthScreen(props);
return (
<Column fill padding="32" backgroundColor={Colors.White}>
<Column fill padding="32" backgroundColor={Theme.Colors.White}>
<MessageOverlay
isVisible={controller.alertMsg != ''}
onBackdropPress={controller.hideAlert}
@@ -22,7 +22,7 @@ export const AuthScreen: React.FC<RootRouteProps> = (props) => {
<Text align="center">{t('header')}</Text>
</Column>
<Centered fill>
<Icon name="fingerprint" size={180} color={Colors.Orange} />
<Icon name="fingerprint" size={180} color={Theme.Colors.Icon} />
</Centered>
<Column>
<Button

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { TouchableOpacity } from 'react-native';
import { Icon } from 'react-native-elements';
import { Button, Centered, Column } from '../components/ui';
import { Colors } from '../components/ui/styleUtils';
import { Theme } from '../components/ui/styleUtils';
import { RootRouteProps } from '../routes';
import { useBiometricScreen } from './BiometricScreenController';
@@ -12,10 +12,10 @@ export const BiometricScreen: React.FC<RootRouteProps> = (props) => {
const controller = useBiometricScreen(props);
return (
<Column fill padding="32" backgroundColor={Colors.White}>
<Column fill padding="32" backgroundColor={Theme.Colors.White}>
<Centered fill>
<TouchableOpacity onPress={controller.useBiometrics}>
<Icon name="fingerprint" size={180} color={Colors.Orange} />
<Icon name="fingerprint" size={180} color={Theme.Colors.Icon} />
</TouchableOpacity>
</Centered>

View File

@@ -1,8 +1,7 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { Tab } from 'react-native-elements';
import { Column, Text } from '../../components/ui';
import { Colors, Styles } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { HomeRouteProps } from '../../routes/main';
import { HistoryTab } from './HistoryTab';
import { MyVcsTab } from './MyVcsTab';
@@ -20,11 +19,11 @@ export const HomeScreen: React.FC<HomeRouteProps> = (props) => {
return (
<React.Fragment>
<Column fill backgroundColor={Colors.LightGrey}>
<Column fill backgroundColor={Theme.Colors.LightGrey}>
<Tab
value={controller.activeTab}
onChange={controller.SELECT_TAB}
indicatorStyle={Styles.tabIndicator}>
indicatorStyle={Theme.Styles.tabIndicator}>
{TabItem(t('myVcsTab', { vcLabel: controller.vcLabel.plural }))}
{TabItem(t('receivedVcsTab', { vcLabel: controller.vcLabel.plural }))}
{TabItem(t('historyTab'))}
@@ -64,9 +63,9 @@ export const HomeScreen: React.FC<HomeRouteProps> = (props) => {
function TabItem(title: string) {
return (
<Tab.Item
containerStyle={Styles.tabContainer}
containerStyle={Theme.Styles.tabContainer}
title={
<Text align="center" color={Colors.TabItemText}>
<Text align="center" color={Theme.Colors.TabItemText}>
{title}
</Text>
}

View File

@@ -15,6 +15,7 @@ export const AddVcModal: React.FC<AddVcModalProps> = (props) => {
service={props.service}
isVisible={true}
onDismiss={controller.DISMISS}
onPress={props.onPress}
/>
<OtpVerificationModal

View File

@@ -26,4 +26,5 @@ export function useAddVcModal({ service }: AddVcModalProps) {
export interface AddVcModalProps {
service: ActorRefFrom<typeof AddVcModalMachine>;
onPress?: () => void;
}

View File

@@ -49,6 +49,11 @@ export const AddVcModalMachine =
},
id: 'AddVcModal',
initial: 'acceptingIdInput',
on: {
INPUT_ID: {
actions: 'setId',
},
},
states: {
acceptingIdInput: {
entry: ['setTransactionId', 'clearOtp'],
@@ -276,10 +281,13 @@ export const AddVcModalMachine =
services: {
requestOtp: async (context) => {
return request('POST', '/req/otp', {
id: 'mosip.identity.otp.internal',
individualId: context.id,
individualIdType: context.idType,
otpChannel: ['EMAIL', 'PHONE'],
metadata: {},
otpChannel: ['PHONE', 'EMAIL'],
requestTime: String(new Date().toISOString()),
transactionID: context.transactionId,
version: '1.0',
});
},

View File

@@ -2,32 +2,17 @@
export interface Typegen0 {
'@@xstate/typegen': true;
'eventsCausingActions': {
forwardToParent: 'DISMISS';
setIdInputRef: 'READY';
setId: 'INPUT_ID';
setIdType: 'SELECT_ID_TYPE';
clearId: 'SELECT_ID_TYPE';
clearIdError: 'INPUT_ID';
setIdBackendError:
| 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]';
setOtp: 'INPUT_OTP';
setRequestId: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
setOtpError: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
setTransactionId: 'xstate.init';
clearOtp:
| 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]';
focusInput:
| 'xstate.after(100)#AddVcModal.acceptingIdInput.focusing'
| 'INPUT_ID'
| 'SELECT_ID_TYPE'
| 'DISMISS';
setIdErrorEmpty: 'VALIDATE_INPUT';
setIdErrorWrongFormat: 'VALIDATE_INPUT';
};
'internalEvents': {
'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.AddVcModal.requestingCredential:invocation[0]': {
type: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
@@ -36,24 +21,14 @@ export interface Typegen0 {
type: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
data: unknown;
};
'done.invoke.AddVcModal.requestingCredential:invocation[0]': {
type: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'xstate.after(100)#AddVcModal.acceptingIdInput.focusing': {
type: 'xstate.after(100)#AddVcModal.acceptingIdInput.focusing';
};
'xstate.init': { type: 'xstate.init' };
};
'invokeSrcNameMap': {
requestOtp: 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
requestCredential: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
requestOtp: 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
};
'missingImplementations': {
actions: never;
@@ -61,37 +36,70 @@ export interface Typegen0 {
guards: never;
delays: never;
};
'eventsCausingActions': {
clearId: 'SELECT_ID_TYPE';
clearIdError: 'INPUT_ID';
clearOtp:
| 'DISMISS'
| 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.init';
focusInput:
| 'DISMISS'
| 'INPUT_ID'
| 'SELECT_ID_TYPE'
| 'VALIDATE_INPUT'
| 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.after(100)#AddVcModal.acceptingIdInput.focusing';
forwardToParent: 'DISMISS';
setId: 'INPUT_ID';
setIdBackendError:
| 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]';
setIdErrorEmpty: 'VALIDATE_INPUT';
setIdErrorWrongFormat: 'VALIDATE_INPUT';
setIdInputRef: 'READY';
setIdType: 'SELECT_ID_TYPE';
setOtp: 'INPUT_OTP';
setOtpError: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
setRequestId: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
setTransactionId:
| 'DISMISS'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.init';
};
'eventsCausingServices': {
requestOtp: 'VALIDATE_INPUT';
requestCredential: 'INPUT_OTP';
requestOtp: 'VALIDATE_INPUT';
};
'eventsCausingGuards': {
isEmptyId: 'VALIDATE_INPUT';
isWrongIdFormat: 'VALIDATE_INPUT';
isIdInvalid: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
isWrongIdFormat: 'VALIDATE_INPUT';
};
'eventsCausingDelays': {};
'matchesStates':
| 'acceptingIdInput'
| 'acceptingIdInput.rendering'
| 'acceptingIdInput.focusing'
| 'acceptingIdInput.idle'
| 'acceptingIdInput.invalid'
| 'acceptingIdInput.invalid.backend'
| 'acceptingIdInput.invalid.empty'
| 'acceptingIdInput.invalid.format'
| 'acceptingIdInput.invalid.backend'
| 'acceptingIdInput.rendering'
| 'acceptingIdInput.requestingOtp'
| 'acceptingOtpInput'
| 'requestingCredential'
| 'done'
| 'requestingCredential'
| {
acceptingIdInput?:
| 'rendering'
| 'focusing'
| 'idle'
| 'invalid'
| 'rendering'
| 'requestingOtp'
| { invalid?: 'empty' | 'format' | 'backend' };
| { invalid?: 'backend' | 'empty' | 'format' };
};
'tags': never;
}

View File

@@ -9,7 +9,10 @@ export const DownloadingVcModal: React.FC<ModalProps> = (props) => {
const controller = useDownloadingVcModal();
return (
<Modal isVisible={props.isVisible} onDismiss={props.onDismiss}>
<Modal
isVisible={props.isVisible}
onDismiss={props.onDismiss}
onShow={props.onShow}>
<Column fill padding="32 24" align="space-between">
<Column fill>
<Text weight="semibold" align="center">

View File

@@ -0,0 +1,64 @@
import React from 'react';
import { Icon, Input } from 'react-native-elements';
import { Button, Column, Row, Text } from '../../../components/ui';
import { Modal } from '../../../components/ui/Modal';
import { Theme } from '../../../components/ui/styleUtils';
import {
GetIdInputModalProps,
useGetIdInputModal,
} from './GetIdInputModalController';
import { useTranslation } from 'react-i18next';
export const GetIdInputModal: React.FC<GetIdInputModalProps> = (props) => {
const { t } = useTranslation('GetIdInputModal');
const controller = useGetIdInputModal(props);
const inputLabel = t('applicationId', {
vcLabel: controller.vcLabel.singular,
});
return (
<Modal onDismiss={props.onDismiss} isVisible={props.isVisible}>
<Column fill align="space-between" padding="32 24">
<Text align="center">
{t('header', { vcLabel: controller.vcLabel.singular })}
</Text>
<Column>
<Row crossAlign="flex-end">
<Column fill>
<Input
placeholder={!controller.id ? inputLabel : ''}
label={controller.id ? inputLabel : ''}
labelStyle={{
color: controller.isInvalid
? Theme.Colors.Red
: Theme.Colors.Black,
}}
style={Theme.Styles.placeholder}
value={controller.id}
keyboardType="number-pad"
rightIcon={
controller.isInvalid ? (
<Icon name="error" size={18} color="red" />
) : (
<Icon name="help" size={18} />
)
}
errorStyle={{ color: Theme.Colors.Red }}
errorMessage={controller.idError}
onChangeText={controller.INPUT_ID}
ref={(node) => !controller.idInputRef && controller.READY(node)}
/>
</Column>
</Row>
<Button
title={t('getUIN', { vcLabel: controller.vcLabel.singular })}
margin="24 0 0 0"
onPress={controller.VALIDATE_INPUT}
loading={controller.isRequestingOtp}
/>
</Column>
</Column>
</Modal>
);
};

View File

@@ -0,0 +1,46 @@
import { useContext } from 'react';
import { useSelector } from '@xstate/react';
import { selectVcLabel } from '../../../machines/settings';
import { GlobalContext } from '../../../shared/GlobalContext';
import { ActorRefFrom } from 'xstate';
import { TextInput } from 'react-native';
import { ModalProps } from '../../../components/ui/Modal';
import {
GetVcModalEvents,
GetVcModalMachine,
selectIsAcceptingOtpInput,
selectIsInvalid,
selectIsRequestingOtp,
selectOtpError,
selectId,
selectIdError,
selectIdInputRef,
} from './GetVcModalMachine';
export function useGetIdInputModal({ service }: GetIdInputModalProps) {
const { appService } = useContext(GlobalContext);
const settingsService = appService.children.get('settings');
return {
id: useSelector(service, selectId),
idInputRef: useSelector(service, selectIdInputRef),
vcLabel: useSelector(settingsService, selectVcLabel),
idError: useSelector(service, selectIdError),
otpError: useSelector(service, selectOtpError),
isInvalid: useSelector(service, selectIsInvalid),
isAcceptingOtpInput: useSelector(service, selectIsAcceptingOtpInput),
isRequestingOtp: useSelector(service, selectIsRequestingOtp),
INPUT_ID: (id: string) => service.send(GetVcModalEvents.INPUT_ID(id)),
VALIDATE_INPUT: () => service.send(GetVcModalEvents.VALIDATE_INPUT()),
INPUT_OTP: (otp: string) => service.send(GetVcModalEvents.INPUT_OTP(otp)),
READY: (input: TextInput) => service.send(GetVcModalEvents.READY(input)),
DISMISS: () => service.send(GetVcModalEvents.DISMISS()),
};
}
export interface GetIdInputModalProps extends ModalProps {
service: ActorRefFrom<typeof GetVcModalMachine>;
onPress?: () => void;
}

View File

@@ -0,0 +1,34 @@
import React from 'react';
import { MessageOverlay } from '../../../components/MessageOverlay';
import { useGetVcModal, GetVcModalProps } from './GetVcModalController';
import { OtpVerificationModal } from './OtpVerificationModal';
import { GetIdInputModal } from './GetIdInputModal';
import { useTranslation } from 'react-i18next';
export const GetVcModal: React.FC<GetVcModalProps> = (props) => {
const { t } = useTranslation('GetVcModal');
const controller = useGetVcModal(props);
return (
<React.Fragment>
<GetIdInputModal
service={props.service}
isVisible={true}
onDismiss={controller.DISMISS}
/>
<OtpVerificationModal
isVisible={controller.isAcceptingOtpInput}
onDismiss={controller.DISMISS}
onInputDone={controller.INPUT_OTP}
error={controller.otpError}
/>
<MessageOverlay
isVisible={controller.isRequestingCredential}
title={t('retrievingId')}
hasProgress
/>
</React.Fragment>
);
};

View File

@@ -0,0 +1,30 @@
import { useSelector } from '@xstate/react';
import { ActorRefFrom } from 'xstate';
import {
GetVcModalEvents,
GetVcModalMachine,
selectIsAcceptingOtpInput,
selectIsRequestingCredential,
selectOtpError,
selectIsAcceptingIdInput,
} from './GetVcModalMachine';
export function useGetVcModal({ service }: GetVcModalProps) {
return {
isRequestingCredential: useSelector(service, selectIsRequestingCredential),
otpError: useSelector(service, selectOtpError),
isAcceptingUinInput: useSelector(service, selectIsAcceptingIdInput),
isAcceptingOtpInput: useSelector(service, selectIsAcceptingOtpInput),
INPUT_OTP: (otp: string) => service.send(GetVcModalEvents.INPUT_OTP(otp)),
DISMISS: () => service.send(GetVcModalEvents.DISMISS()),
};
}
export interface GetVcModalProps {
service: ActorRefFrom<typeof GetVcModalMachine>;
onPress?: () => void;
}

View File

@@ -0,0 +1,339 @@
import { TextInput } from 'react-native';
import {
assign,
ErrorPlatformEvent,
EventFrom,
DoneInvokeEvent,
sendParent,
StateFrom,
} from 'xstate';
import { createModel } from 'xstate/lib/model';
import { BackendResponseError, request } from '../../../shared/request';
import i18n from '../../../i18n';
import { AddVcModalMachine } from './AddVcModalMachine';
import { GET_INDIVIDUAL_ID } from '../../../shared/constants';
const model = createModel(
{
idInputRef: null as TextInput,
id: '',
idError: '',
otp: '',
otpError: '',
transactionId: '',
child: null,
},
{
events: {
INPUT_ID: (id: string) => ({ id }),
INPUT_OTP: (otp: string) => ({ otp }),
VALIDATE_INPUT: () => ({}),
READY: (idInputRef: TextInput) => ({ idInputRef }),
DISMISS: () => ({}),
GOT_ID: (id: string) => ({ id }),
},
}
);
export const GetVcModalEvents = model.events;
export const GetVcModalMachine =
/** @xstate-layout N4IgpgJg5mDOIC5QEEIQGoGMCyB7CAhgDYB0BmmYADgC4CWAdlAJITMNUCuNJATmAwhhejKAGIASgFFkAEQCaiUFVyw69XAyUgAHogC0ARgAsATgDMJAEynjhgBzmArE-v2AbDYA0IAJ4GrAHZ3EkCnKxMrc0NDc1NA+ycAXySfVAwcfGIyCmp6JlZ2Lh4AM1xMTjUmMR1YGgIaMDISxt4ACkMABk6ASjF0rDxCUnJKWlFCjm4SMoqqqG0VNQ0tJF0DWM6QwOjXQydjYyDbH38EIycQ+M6PI6t7TsNTdxS0tEGskdzxgrYpnjoECIYDEzAAcgAFACqABUAPrMWSLVTqOiabR6c6GdxOQIkRydcJRQnudweU6IezGEjGezxKxRQJPTamV4gAaZYY5Mb5Fh-YokQHAsToZAAGURyBhUgRkNhyOWaNWoExRisLmsuPMgSCgUC8XM9gpCCCThI5huNkNpme2qc5jZHKG2VGeQm-OmQpBAGUpGKpABheGIuEw+QQqQK1Hotaq-b2QwkTqmVzBTqBQnmdXGoyGKyheI6xnmYzmMmGR3vTku768yYCxgAN2IgNBcuDSLWS2jyvWWM6ZdCA6c6eMYQtuJz8WshuxHhcVkzDtS7Krzq+PPdRU9DGbRFboolsilMvB0JhUZWGIMpcs+1METHycSnWMxsfSdcZfM2pLFsNlYZOu3Jur824AruLYQGIvr+kGCKyKG4aRl2KJXrGGyEp0JCmPeOKJP+ZbGu4pg4XSOp0q+jgJKyK5Op8IE-Hy4F8GAACOnBwLyADyNBUGIECaE0Ta4AA1k09Fcq6TH1tM-AcVxoi8VQCAiZgDRKgA2p0AC6l5Kte-ZuNYpJ6par6XIExr2DYNI2bigRmDqJKAR8Um1lu-ysQpdRKXxYjCLwuC8CQVBEA0ZS8AAtiQkk1puYFefJnG+Uwymqbu5QaZo2l6ahioxiqBjxPYJAxFseZpnY0TGmYIROA43QPAOpkvHRa4MdJdYejQYiyMw3rYAN3r6YVfb6MY7jUtiWYllY7jYpE7jWWEZVPPcTILQ1FbtUBnUeWlfHgW255wtxMIQqNvZxnE1Iph4i4Wo8LXGqYhJJs1RwPj+32udWG6gVAynHf1g3DVdhkXDsSYJJ0VhmAyDi0rVGopqYVLww8jkmMubx7VyyWKUwAb8EIDD0MQAlCYKmXibFHUE+xKW8iTkACBTRAZY2WUrLlEMYVi2LYfc+xmDaJhklYxpdBaoSixE7gDjcxjJLtbnZITqVQKzZMcwFvBBSFYURcFMVxaQmss6T7N0MQXM81pun80VWKHImMS0sccPuHqUt+IgMTBGVDKLvquLUcYKQrgw+BwNo5uMd1LH8IIwiiM743YvqJBTQ+GZPDstJvv75zzZYYQKz9pYPG1ePqwDMk9TM5SVOn+U9pDsR5kOA4pjirjzU4OZl6E4QzbdhpbH9wFdZ5DZAmAGdxqW1JRM4Nrat0JimMaTJkfSwTGDcWY7XX-2J3PO57oCJBgFFtBnMoaEGQL+g7Hi9g6p49oq735jSzZT8jgEw+1worSOatz6z0Sg2SC+4IDN2ig0JeBhgj5hcIaT++wnhUiNCXEseILQ2TcGEDMP5T6rnxvFQGskILXwQQAI3IOJQQKDzgkUTJmDwOJFY4gsMaEcpEGoPBMGObU7hojT32glZiXkmxQTYW-DwJAMEkOwejZGJdJpAO1HSQ4U1QFSPcjI2h3lmZ+SoIo8qH9nC0gahYBIpJiLahwg+H25FXxxFrpQ+uF8YHcCsWQnOCN84GiLjmUs2wx5mGEdjIx1CmLA3+FYzwpEggPEmgaMueCzj6jxJ7A4r4VbagfPEi2TMiba2tuTW2RArGTXzA4cWJIdieGlo8UqEQDgYPTAQspJBBIMEXu3dCLt9B0ksIrRwtgDi4RtO00scsDiHATCWDJZTAlBGCXnR4YSqQ5kEaPLphgdjpntFSKOSQgA */
model.createMachine(
{
tsTypes: {} as import('./GetVcModalMachine.typegen').Typegen0,
schema: {
context: model.initialContext,
events: {} as EventFrom<typeof model>,
},
id: 'GetVcModal',
initial: 'acceptingIdInput',
states: {
acceptingIdInput: {
entry: ['setTransactionId', 'clearOtp'],
initial: 'rendering',
states: {
rendering: {
on: {
READY: {
actions: 'setIdInputRef',
target: 'focusing',
},
},
},
focusing: {
after: {
'100': {
description:
'Small delay to properly show the keyboard when focusing input.',
target: 'idle',
},
},
},
idle: {
entry: 'focusInput',
invoke: {
id: 'AddVcModal',
src: AddVcModalMachine,
},
on: {
INPUT_ID: {
actions: 'setId',
},
VALIDATE_INPUT: [
{
cond: 'isEmptyId',
target: '#GetVcModal.acceptingIdInput.invalid.empty',
},
{
cond: 'isWrongIdFormat',
target: '#GetVcModal.acceptingIdInput.invalid.format',
},
{
target: 'requestingOtp',
},
],
},
},
invalid: {
entry: 'focusInput',
states: {
empty: {
entry: 'setIdErrorEmpty',
},
format: {
entry: 'setIdErrorWrongFormat',
},
backend: {},
},
on: {
INPUT_ID: {
actions: ['setId', 'clearIdError'],
target: 'idle',
},
VALIDATE_INPUT: [
{
cond: 'isEmptyId',
target: '.empty',
},
{
cond: 'isWrongIdFormat',
target: '.format',
},
{
target: 'requestingOtp',
},
],
},
},
requestingOtp: {
invoke: {
src: 'requestOtp',
onDone: [
{
target: '#GetVcModal.acceptingOtpInput',
},
],
onError: [
{
actions: 'setIdBackendError',
target: '#GetVcModal.acceptingIdInput.invalid.backend',
},
],
},
},
},
on: {
DISMISS: {
actions: 'forwardToParent',
},
},
},
acceptingOtpInput: {
entry: 'clearOtp',
on: {
INPUT_OTP: {
actions: 'setOtp',
target: 'requestingUinVid',
},
DISMISS: {
target: '#GetVcModal.acceptingIdInput.idle',
},
},
},
requestingUinVid: {
invoke: {
src: 'requestingUinVid',
onDone: [
{
actions: ['setIndividualId'],
target: 'done',
},
],
onError: [
{
actions: 'setIdBackendError',
cond: 'isIdInvalid',
target: '#GetVcModal.acceptingIdInput.invalid.backend',
},
{
actions: 'setOtpError',
target: 'acceptingOtpInput',
},
],
},
},
done: {
type: 'final',
},
},
},
{
actions: {
forwardToParent: sendParent('DISMISS'),
setId: model.assign({
id: (_context, event) => event.id,
}),
setOtp: model.assign({
otp: (_context, event) => event.otp,
}),
setTransactionId: assign({
transactionId: () => String(new Date().valueOf()).substring(3, 13),
}),
setIndividualId: (_context, event) =>
GET_INDIVIDUAL_ID((event as DoneInvokeEvent<string>).data),
setIdBackendError: assign({
idError: (context, event) => {
if ((event as ErrorPlatformEvent).data == 'IDA-MLC-001') {
return i18n.t('errors.backend.timeOut', { ns: 'GetVcModal' });
}
const message = (event as ErrorPlatformEvent).data.message;
const ID_ERRORS_MAP = {
'AID is not ready': 'applicationProcessing',
};
return ID_ERRORS_MAP[message]
? i18n.t(`errors.backend.${ID_ERRORS_MAP[message]}`, {
ns: 'GetVcModal',
})
: message;
},
}),
clearIdError: model.assign({ idError: '' }),
setIdErrorEmpty: model.assign({
idError: () => i18n.t('errors.input.empty', { ns: 'GetVcModal' }),
}),
setIdErrorWrongFormat: model.assign({
idError: () =>
i18n.t('errors.input.invalidFormat', { ns: 'GetVcModal' }),
}),
setOtpError: assign({
otpError: (_context, event) => {
const message = (event as ErrorPlatformEvent).data.message;
const OTP_ERRORS_MAP = {
'OTP is invalid': 'invalidOtp',
};
return OTP_ERRORS_MAP[message]
? i18n.t(`errors.backend.${OTP_ERRORS_MAP[message]}`, {
ns: 'GetVcModal',
})
: message;
},
}),
setIdInputRef: model.assign({
idInputRef: (_context, event) => event.idInputRef,
}),
clearOtp: assign({ otp: '' }),
focusInput: (context) => context.idInputRef.focus(),
},
services: {
requestOtp: async (context) => {
return await request('POST', '/req/individualId/otp', {
id: 'mosip.identity.otp.internal',
aid: context.id,
metadata: {},
otpChannel: ['EMAIL', 'PHONE'],
requestTime: String(new Date().toISOString()),
transactionID: context.transactionId,
version: '1.0',
});
},
requestingUinVid: async (context) => {
const response = await request('POST', '/aid/get-individual-id', {
request: {
aid: context.id,
transactionID: context.transactionId,
otp: context.otp,
},
requesttime: String(new Date().toISOString()),
id: 'mosip.resident.checkstatus',
version: 'v1',
});
return response.response.individualId;
},
},
guards: {
isEmptyId: ({ id }) => !id || !id.length,
isWrongIdFormat: ({ id }) => !/^\d{14,29}$/.test(id),
isIdInvalid: (_context, event: unknown) =>
['RES-SER-449', 'IDA-MLC-001'].includes(
(event as BackendResponseError).name
),
},
}
);
type State = StateFrom<typeof GetVcModalMachine>;
export function selectId(state: State) {
return state.context.id;
}
export function selectIdInputRef(state: State) {
return state.context.idInputRef;
}
export function selectIdError(state: State) {
return state.context.idError;
}
export function selectOtpError(state: State) {
return state.context.otpError;
}
export function selectIsAcceptingIdInput(state: State) {
return state.matches('acceptingIdInput');
}
export function selectIsInvalid(state: State) {
return state.matches('acceptingIdInput.invalid');
}
export function selectIsAcceptingOtpInput(state: State) {
return state.matches('acceptingOtpInput');
}
export function selectIsRequestingOtp(state: State) {
return state.matches('acceptingIdInput.requestingOtp');
}
export function selectIsRequestingCredential(state: State) {
return state.matches('requestingUinVid');
}

View File

@@ -0,0 +1,102 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
'internalEvents': {
'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.GetVcModal.requestingUinVid:invocation[0]': {
type: 'done.invoke.GetVcModal.requestingUinVid:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
};
'error.platform.GetVcModal.requestingUinVid:invocation[0]': {
type: 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
data: unknown;
};
'xstate.after(100)#GetVcModal.acceptingIdInput.focusing': {
type: 'xstate.after(100)#GetVcModal.acceptingIdInput.focusing';
};
'xstate.init': { type: 'xstate.init' };
};
'invokeSrcNameMap': {
requestOtp: 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]';
requestingUinVid: 'done.invoke.GetVcModal.requestingUinVid:invocation[0]';
};
'missingImplementations': {
actions: never;
services: never;
guards: never;
delays: never;
};
'eventsCausingActions': {
clearIdError: 'INPUT_ID';
clearOtp:
| 'DISMISS'
| 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.init';
focusInput:
| 'DISMISS'
| 'INPUT_ID'
| 'VALIDATE_INPUT'
| 'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.after(100)#GetVcModal.acceptingIdInput.focusing';
forwardToParent: 'DISMISS';
setId: 'INPUT_ID';
setIdBackendError:
| 'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
setIdErrorEmpty: 'VALIDATE_INPUT';
setIdErrorWrongFormat: 'VALIDATE_INPUT';
setIdInputRef: 'READY';
setIndividualId: 'done.invoke.GetVcModal.requestingUinVid:invocation[0]';
setOtp: 'INPUT_OTP';
setOtpError: 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
setTransactionId:
| 'DISMISS'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.init';
};
'eventsCausingServices': {
requestOtp: 'VALIDATE_INPUT';
requestingUinVid: 'INPUT_OTP';
};
'eventsCausingGuards': {
isEmptyId: 'VALIDATE_INPUT';
isIdInvalid: 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
isWrongIdFormat: 'VALIDATE_INPUT';
};
'eventsCausingDelays': {};
'matchesStates':
| 'acceptingIdInput'
| 'acceptingIdInput.focusing'
| 'acceptingIdInput.idle'
| 'acceptingIdInput.invalid'
| 'acceptingIdInput.invalid.backend'
| 'acceptingIdInput.invalid.empty'
| 'acceptingIdInput.invalid.format'
| 'acceptingIdInput.rendering'
| 'acceptingIdInput.requestingOtp'
| 'acceptingOtpInput'
| 'done'
| 'requestingUinVid'
| {
acceptingIdInput?:
| 'focusing'
| 'idle'
| 'invalid'
| 'rendering'
| 'requestingOtp'
| { invalid?: 'backend' | 'empty' | 'format' };
};
'tags': never;
}

View File

@@ -3,18 +3,33 @@ import { Icon, Input } from 'react-native-elements';
import { Picker } from '@react-native-picker/picker';
import { Button, Column, Row, Text } from '../../../components/ui';
import { Modal } from '../../../components/ui/Modal';
import { Colors } from '../../../components/ui/styleUtils';
import { Theme } from '../../../components/ui/styleUtils';
import { IdInputModalProps, useIdInputModal } from './IdInputModalController';
import { useTranslation } from 'react-i18next';
import { TouchableOpacity } from 'react-native';
import { individualId } from '../../../shared/constants';
import { GET_INDIVIDUAL_ID } from '../../../shared/constants';
export const IdInputModal: React.FC<IdInputModalProps> = (props) => {
const { t } = useTranslation('IdInputModal');
const controller = useIdInputModal(props);
const setIndividualID = () => {
controller.INPUT_ID(individualId);
};
const dismissInput = () => {
props.onDismiss();
GET_INDIVIDUAL_ID('');
};
const inputLabel = t('enterId', { idType: controller.idType });
return (
<Modal onDismiss={props.onDismiss} isVisible={props.isVisible}>
<Modal
onDismiss={dismissInput}
isVisible={props.isVisible}
onShow={setIndividualID}>
<Column fill align="space-between" padding="32 24">
<Text align="center">
{t('header', { vcLabel: controller.vcLabel.singular })}
@@ -25,7 +40,7 @@ export const IdInputModal: React.FC<IdInputModalProps> = (props) => {
width="33%"
style={{
borderBottomWidth: 1,
borderColor: Colors.Grey,
borderColor: Theme.Colors.Grey,
bottom: 24,
}}>
<Picker
@@ -35,12 +50,15 @@ export const IdInputModal: React.FC<IdInputModalProps> = (props) => {
<Picker.Item label="VID" value="VID" />
</Picker>
</Column>
<Column fill>
<Input
placeholder={!controller.id ? inputLabel : ''}
label={controller.id ? inputLabel : ''}
labelStyle={{
color: controller.isInvalid ? Colors.Red : Colors.Black,
color: controller.isInvalid
? Theme.Colors.Red
: Theme.Colors.Black,
}}
value={controller.id}
keyboardType="number-pad"
@@ -49,7 +67,7 @@ export const IdInputModal: React.FC<IdInputModalProps> = (props) => {
<Icon name="error" size={18} color="red" />
) : null
}
errorStyle={{ color: Colors.Red }}
errorStyle={{ color: Theme.Colors.Red }}
errorMessage={controller.idError}
onChangeText={controller.INPUT_ID}
ref={(node) => !controller.idInputRef && controller.READY(node)}
@@ -62,6 +80,14 @@ export const IdInputModal: React.FC<IdInputModalProps> = (props) => {
onPress={controller.VALIDATE_INPUT}
loading={controller.isRequestingOtp}
/>
{!controller.id && (
<TouchableOpacity
activeOpacity={1}
onPress={props.onPress}
style={Theme.Styles.getId}>
<Text color={Theme.Colors.AddIdBtnBg}>{t('noUIN/VID')}</Text>
</TouchableOpacity>
)}
</Column>
</Column>
</Modal>

View File

@@ -47,4 +47,5 @@ export function useIdInputModal({ service }: IdInputModalProps) {
export interface IdInputModalProps extends ModalProps {
service: ActorRefFrom<typeof AddVcModalMachine>;
onPress?: () => void;
}

View File

@@ -4,7 +4,7 @@ import { Icon } from 'react-native-elements';
import { PinInput } from '../../../components/PinInput';
import { Column, Text } from '../../../components/ui';
import { Modal, ModalProps } from '../../../components/ui/Modal';
import { Colors } from '../../../components/ui/styleUtils';
import { Theme } from '../../../components/ui/styleUtils';
export const OtpVerificationModal: React.FC<OtpVerificationModalProps> = (
props
@@ -14,10 +14,10 @@ export const OtpVerificationModal: React.FC<OtpVerificationModalProps> = (
return (
<Modal isVisible={props.isVisible} onDismiss={props.onDismiss}>
<Column fill padding="32">
<Icon name="lock" color={Colors.Orange} size={60} />
<Icon name="lock" color={Theme.Colors.Icon} size={60} />
<Column fill align="space-between">
<Text align="center">{t('enterOtp')}</Text>
<Text align="center" color={Colors.Red} margin="16 0 0 0">
<Text align="center" color={Theme.Colors.Red} margin="16 0 0 0">
{props.error}
</Text>
<PinInput length={6} onDone={props.onInputDone} />

View File

@@ -1,21 +1,32 @@
import React from 'react';
import { Button, Column, Text, Centered } from '../../components/ui';
import { Icon } from 'react-native-elements';
import { Colors } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { RefreshControl } from 'react-native';
import { useMyVcsTab } from './MyVcsTabController';
import { HomeScreenTabProps } from './HomeScreen';
import { AddVcModal } from './MyVcs/AddVcModal';
import { GetVcModal } from './MyVcs/GetVcModal';
import { DownloadingVcModal } from './MyVcs/DownloadingVcModal';
import { OnboardingOverlay } from './OnboardingOverlay';
import { useTranslation } from 'react-i18next';
import GestureRecognizer from 'react-native-swipe-gestures';
import { UpdatedVcItem } from '../../components/UpdatedVcItem';
import { GET_INDIVIDUAL_ID } from '../../shared/constants';
export const MyVcsTab: React.FC<HomeScreenTabProps> = (props) => {
const { t } = useTranslation('MyVcsTab');
const controller = useMyVcsTab(props);
const getId = () => {
controller.DISMISS();
controller.GET_VC();
};
const clearIndividualId = () => {
GET_INDIVIDUAL_ID('');
};
return (
<React.Fragment>
<Column fill style={{ display: props.isVisible ? 'flex' : 'none' }}>
@@ -60,7 +71,7 @@ export const MyVcsTab: React.FC<HomeScreenTabProps> = (props) => {
<Text weight="semibold" margin="0 0 8 0">
{t('generateVc', { vcLabel: controller.vcLabel.plural })}
</Text>
<Text color={Colors.Grey} align="center">
<Text color={Theme.Colors.Grey} align="center">
{t('generateVcDescription', {
vcLabel: controller.vcLabel.singular,
})}
@@ -68,7 +79,7 @@ export const MyVcsTab: React.FC<HomeScreenTabProps> = (props) => {
<Icon
name="arrow-downward"
containerStyle={{ marginTop: 20 }}
color={Colors.Orange}
color={Theme.Colors.Icon}
/>
</Centered>
@@ -88,12 +99,18 @@ export const MyVcsTab: React.FC<HomeScreenTabProps> = (props) => {
</Column>
{controller.AddVcModalService && (
<AddVcModal service={controller.AddVcModalService} />
<AddVcModal service={controller.AddVcModalService} onPress={getId} />
)}
{controller.GetVcModalService && (
<GetVcModal service={controller.GetVcModalService} />
)}
{controller.isRequestSuccessful && (
<DownloadingVcModal
isVisible={controller.isRequestSuccessful}
onDismiss={controller.DISMISS}
onShow={clearIndividualId}
/>
)}

View File

@@ -7,7 +7,7 @@ import {
selectMyVcs,
VcEvents,
} from '../../machines/vc';
import { vcItemMachine } from '../../machines/vcItem';
import { vcItemMachine } from '../../machines/vcItem';
import { GlobalContext } from '../../shared/GlobalContext';
import { HomeScreenTabProps } from './HomeScreen';
import {
@@ -16,6 +16,7 @@ import {
selectAddVcModal,
selectIsOnboarding,
selectIsRequestSuccessful,
selectGetVcModal,
} from './MyVcsTabMachine';
export function useMyVcsTab(props: HomeScreenTabProps) {
@@ -27,6 +28,7 @@ export function useMyVcsTab(props: HomeScreenTabProps) {
return {
service,
AddVcModalService: useSelector(service, selectAddVcModal),
GetVcModalService: useSelector(service, selectGetVcModal),
vcKeys: useSelector(vcService, selectMyVcs),
vcLabel: useSelector(settingsService, selectVcLabel),
@@ -39,9 +41,11 @@ export function useMyVcsTab(props: HomeScreenTabProps) {
ADD_VC: () => service.send(MyVcsTabEvents.ADD_VC()),
GET_VC: () => service.send(MyVcsTabEvents.GET_VC()),
REFRESH: () => vcService.send(VcEvents.REFRESH_MY_VCS()),
VIEW_VC: (vcRef: ActorRefFrom<typeof vcItemMachine>) => {
VIEW_VC: (vcRef: ActorRefFrom<typeof vcItemMachine>) => {
return service.send(MyVcsTabEvents.VIEW_VC(vcRef));
},

View File

@@ -16,6 +16,7 @@ import {
ONBOARDING_STATUS_STORE_KEY,
} from '../../shared/constants';
import { AddVcModalMachine } from './MyVcs/AddVcModalMachine';
import { GetVcModalMachine } from './MyVcs/GetVcModalMachine';
const model = createModel(
{
@@ -30,6 +31,7 @@ const model = createModel(
DISMISS: () => ({}),
STORE_RESPONSE: (response?: unknown) => ({ response }),
ADD_VC: () => ({}),
GET_VC: () => ({}),
ONBOARDING_DONE: () => ({}),
},
}
@@ -75,6 +77,7 @@ export const MyVcsTabMachine = model.createMachine(
on: {
ADD_VC: 'addingVc',
VIEW_VC: 'viewingVc',
GET_VC: 'gettingVc',
},
},
viewingVc: {
@@ -111,6 +114,20 @@ export const MyVcsTabMachine = model.createMachine(
},
},
},
gettingVc: {
invoke: {
id: 'GetVcModal',
src: GetVcModalMachine,
onDone: 'addingVc',
},
on: {
DISMISS: 'idle',
},
initial: 'waitingForvcKey',
states: {
waitingForvcKey: {},
},
},
},
},
{
@@ -168,6 +185,10 @@ export function selectAddVcModal(state: State) {
return state.children.AddVcModal as ActorRefFrom<typeof AddVcModalMachine>;
}
export function selectGetVcModal(state: State) {
return state.children.GetVcModal as ActorRefFrom<typeof GetVcModalMachine>;
}
export function selectIsOnboarding(state: State) {
return state.matches('onboarding');
}

View File

@@ -1,58 +1,14 @@
import React, { useRef, useContext } from 'react';
import AppIntroSlider from 'react-native-app-intro-slider';
import { SafeAreaView, ScrollView, StyleSheet, View } from 'react-native';
import { SafeAreaView, ScrollView, View } from 'react-native';
import { Icon, Overlay } from 'react-native-elements';
import { Button, Column, Text } from '../../components/ui';
import { Colors } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { useSelector } from '@xstate/react';
import { GlobalContext } from '../../shared/GlobalContext';
import { selectVcLabel } from '../../machines/settings';
import { useTranslation } from 'react-i18next';
const styles = StyleSheet.create({
overlay: {
padding: 24,
bottom: 86,
backgroundColor: 'transparent',
shadowColor: 'transparent',
},
slide: {
width: '100%',
padding: 20,
},
slider: {
backgroundColor: Colors.Orange,
minHeight: 280,
width: '100%',
margin: 0,
borderRadius: 4,
},
appSlider: {},
title: {
color: Colors.White,
marginBottom: 20,
fontFamily: 'Poppins_700Bold',
},
text: {
color: Colors.White,
},
paginationContainer: {
margin: 10,
},
paginationDots: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 20,
},
closeIcon: {
alignItems: 'flex-end',
end: 16,
top: 40,
zIndex: 1,
},
});
export const OnboardingOverlay: React.FC<OnboardingProps> = (props) => {
const slider = useRef<AppIntroSlider>();
@@ -90,10 +46,10 @@ export const OnboardingOverlay: React.FC<OnboardingProps> = (props) => {
const renderItem = ({ item }) => {
return (
<View style={styles.slide}>
<View style={Theme.Styles.slide}>
<ScrollView showsVerticalScrollIndicator={true}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.text}>{item.text}</Text>
<Text style={Theme.Styles.sliderTitle}>{item.title}</Text>
<Text style={Theme.Styles.text}>{item.text}</Text>
{item.footer}
</ScrollView>
</View>
@@ -102,14 +58,14 @@ export const OnboardingOverlay: React.FC<OnboardingProps> = (props) => {
const renderPagination = (activeIndex: number) => {
return (
<View style={styles.paginationContainer}>
<View style={Theme.Styles.paginationContainer}>
<SafeAreaView>
<View style={styles.paginationDots}>
<View style={Theme.Styles.paginationDots}>
{slides.length > 1 &&
slides.map((_, i) => (
<Icon
key={i}
color={Colors.White}
color={Theme.Colors.White}
size={10}
name="circle"
style={{ opacity: i === activeIndex ? 1 : 0.6, margin: 2 }}
@@ -124,21 +80,21 @@ export const OnboardingOverlay: React.FC<OnboardingProps> = (props) => {
return (
<Overlay
isVisible={props.isVisible}
overlayStyle={styles.overlay}
overlayStyle={Theme.Styles.overlay}
transparent
onBackdropPress={props.onDone}>
<Column fill align="flex-end">
<Icon
name="close"
color={Colors.White}
color={Theme.Colors.White}
onPress={props.onDone}
containerStyle={styles.closeIcon}
containerStyle={Theme.Styles.closeIcon}
/>
<View style={styles.slider}>
<View style={Theme.Styles.slider}>
<AppIntroSlider
renderItem={renderItem}
data={slides}
style={styles.appSlider}
style={Theme.Styles.appSlider}
ref={slider}
renderPagination={renderPagination}
/>

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { RefreshControl } from 'react-native';
import { Icon } from 'react-native-elements';
import { Centered, Column, Text } from '../../components/ui';
import { Colors } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { HomeScreenTabProps } from './HomeScreen';
import { useReceivedVcsTab } from './ReceivedVcsTabController';
import { UpdatedVcItem } from '../../components/UpdatedVcItem';
@@ -44,7 +44,7 @@ export const ReceivedVcsTab: React.FC<HomeScreenTabProps> = (props) => {
vcLabel: controller.vcLabel.plural,
})}
</Text>
<Text align="center" color={Colors.Grey}>
<Text align="center" color={Theme.Colors.Grey}>
{t('noReceivedVcsText', {
vcLabel: controller.vcLabel.singular,
})}

View File

@@ -3,7 +3,7 @@ import { Icon } from 'react-native-elements';
import { TextEditOverlay } from '../../components/TextEditOverlay';
import { Column } from '../../components/ui';
import { Modal } from '../../components/ui/Modal';
import { Colors } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { MessageOverlay } from '../../components/MessageOverlay';
import { ToastItem } from '../../components/ui/ToastItem';
import { Passcode } from '../../components/Passcode';
@@ -23,7 +23,11 @@ export const ViewVcModal: React.FC<ViewVcModalProps> = (props) => {
headerTitle={controller.vc.tag || controller.vc.id}
headerElevation={2}
headerRight={
<Icon name="edit" onPress={controller.EDIT_TAG} color={Colors.Orange} />
<Icon
name="edit"
onPress={controller.EDIT_TAG}
color={Theme.Colors.Icon}
/>
}>
<Column scroll>
<Column fill>

View File

@@ -7,7 +7,7 @@ import { Icon } from 'react-native-elements';
import { mainRoutes } from '../routes/main';
import { RootRouteProps } from '../routes';
import { LanguageSelector } from '../components/LanguageSelector';
import { Colors } from '../components/ui/styleUtils';
import { Theme } from '../components/ui/styleUtils';
import { useTranslation } from 'react-i18next';
const { Navigator, Screen } = createBottomTabNavigator();
@@ -16,11 +16,11 @@ export const MainLayout: React.FC<RootRouteProps> = () => {
const { t } = useTranslation('MainLayout');
const options: BottomTabNavigationOptions = {
headerLeft: () => <Icon name="notifications" color={Colors.Orange} />,
headerLeft: () => <Icon name="notifications" color={Theme.Colors.Icon} />,
headerLeftContainerStyle: { paddingStart: 16 },
headerRight: () => (
<LanguageSelector
triggerComponent={<Icon name="language" color={Colors.Orange} />}
triggerComponent={<Icon name="language" color={Theme.Colors.Icon} />}
/>
),
headerRightContainerStyle: { paddingEnd: 16 },
@@ -42,7 +42,7 @@ export const MainLayout: React.FC<RootRouteProps> = () => {
tabBarIcon: ({ focused }) => (
<Icon
name={route.icon}
color={focused ? Colors.IconBg : Colors.Grey}
color={focused ? Theme.Colors.IconBg : Theme.Colors.Icon}
reverse={focused}
/>
),

View File

@@ -4,7 +4,7 @@ import { Icon } from 'react-native-elements';
import { MAX_PIN, PasscodeVerify } from '../components/PasscodeVerify';
import { PinInput } from '../components/PinInput';
import { Column, Text } from '../components/ui';
import { Colors } from '../components/ui/styleUtils';
import { Theme } from '../components/ui/styleUtils';
import { PasscodeRouteProps } from '../routes';
import { usePasscodeScreen } from './PasscodeScreenController';
@@ -30,8 +30,8 @@ export const PasscodeScreen: React.FC<PasscodeRouteProps> = (props) => {
);
return (
<Column fill padding="32" backgroundColor={Colors.White}>
<Icon name="lock" color={Colors.Orange} size={60} />
<Column fill padding="32" backgroundColor={Theme.Colors.White}>
<Icon name="lock" color={Theme.Colors.Icon} size={60} />
{props.route.params?.setup ? (
<Column fill align="space-between" width="100%">
{passcodeSetup}
@@ -48,7 +48,7 @@ export const PasscodeScreen: React.FC<PasscodeRouteProps> = (props) => {
)}
<Column fill>
<Text align="center" color={Colors.Red}>
<Text align="center" color={Theme.Colors.Red}>
{controller.error}
</Text>
</Column>

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Column } from '../../components/ui';
import { Colors } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { Modal, ModalProps } from '../../components/ui/Modal';
import { useReceiveVcModal } from './ReceiveVcModalController';
import { NewVcDetails } from '../../components/NewVcDetails';
@@ -18,7 +18,10 @@ export const TimerBasedReceiveVcModal: React.FC<ReceveVcModalProps> = (
props.onAccept();
}, 5000)
}>
<Column scroll padding="0 0 48 0" backgroundColor={Colors.LightGrey}>
<Column
scroll
padding="0 0 48 0"
backgroundColor={Theme.Colors.LightGrey}>
<NewVcDetails vc={controller.incomingVc} />
</Column>
</Modal>

View File

@@ -1,7 +1,7 @@
import React from 'react';
import QRCode from 'react-native-qrcode-svg';
import { Centered, Column, Text } from '../../components/ui';
import { Colors } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { MainRouteProps } from '../../routes/main';
import { TimerBasedReceiveVcModal } from './TimerBasedReceiveVcModal';
import { MessageOverlay } from '../../components/MessageOverlay';
@@ -16,10 +16,10 @@ export const TimerBasedRequestScreen: React.FC<MainRouteProps> = (props) => {
const isFocused = useIsFocused();
return (
<Column fill padding="98 24 24 24" backgroundColor={Colors.LightGrey}>
<Column fill padding="98 24 24 24" backgroundColor={Theme.Colors.LightGrey}>
<Column>
{controller.isBluetoothDenied ? (
<Text color={Colors.Red} align="center">
<Text color={Theme.Colors.Red} align="center">
Please enable Bluetooth to be able to request{' '}
{controller.vcLabel.singular}
</Text>
@@ -36,7 +36,7 @@ export const TimerBasedRequestScreen: React.FC<MainRouteProps> = (props) => {
<QRCode
size={200}
value={controller.connectionParams}
backgroundColor={Colors.LightGrey}
backgroundColor={Theme.Colors.LightGrey}
/>
) : null}
</Centered>

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Input } from 'react-native-elements';
import { DeviceInfoList } from '../../components/DeviceInfoList';
import { Button, Column } from '../../components/ui';
import { Colors } from '../../components/ui/styleUtils';
import { Theme } from '../../components/ui/styleUtils';
import { MessageOverlay } from '../../components/MessageOverlay';
import { Modal, ModalProps } from '../../components/ui/Modal';
import { useSendVcModal } from './SendVcModalController';
@@ -34,7 +34,7 @@ export const UpdatedSendVcModal: React.FC<SendVcModalProps> = (props) => {
return (
<Modal {...props}>
<Column fill backgroundColor={Colors.LightGrey}>
<Column fill backgroundColor={Theme.Colors.LightGrey}>
<Column padding="16 0" scroll>
<DeviceInfoList of="receiver" deviceInfo={controller.receiverInfo} />
<Column padding="24">
@@ -71,7 +71,7 @@ export const UpdatedSendVcModal: React.FC<SendVcModalProps> = (props) => {
</Column>
</Column>
<Column
backgroundColor={Colors.White}
backgroundColor={Theme.Colors.White}
padding="16 24"
margin="2 0 0 0"
elevation={2}>

View File

@@ -1,9 +1,6 @@
import { VC } from '../types/vc';
import Constants from 'expo-constants';
export const HOST =
Constants.manifest.extra.backendServiceUrl ||
'https://resident-app.newlogic.dev';
export const HOST = 'https://api-internal.dev3.mosip.net/resident/v1/';
export const MY_VCS_STORE_KEY = 'myVCs';
@@ -12,6 +9,12 @@ export const RECEIVED_VCS_STORE_KEY = 'receivedVCs';
export const VC_ITEM_STORE_KEY = (vc: Partial<VC>) =>
`vc:${vc.idType}:${vc.id}:${vc.requestId}`;
export let individualId = '';
export const GET_INDIVIDUAL_ID = (ind_Id: string) => {
individualId = ind_Id;
};
export const ACTIVITY_LOG_STORE_KEY = 'activityLog';
export const SETTINGS_STORE_KEY = 'settings';