INJI-473) Code clean up and fixing metro errors/warnings (#947)

* feat(INJI-473) - Removed unused injiTourGuide action.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Removed unused logKey action.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Removed unused backendInfo api and state.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - simplify isPasscodeSet logic.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Move logState to commonUtil to remove cyclic dependency.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Delete unused code.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Refactor code to use util function for iOS or isAndroid.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Move Issuers_Key_Ref into utils.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Remove profile related resource from setting screen

Signed-off-by: Swati Goel <meet2swati@gmail.com>

* feat(INJI-473) - Remove unused code for locales.

Signed-off-by: Swati Goel <meet2swati@gmail.com>

---------

Signed-off-by: Swati Goel <meet2swati@gmail.com>
This commit is contained in:
Swati Goel
2023-10-20 12:50:39 +05:30
committed by GitHub
parent 86840edcc1
commit 142228b0db
80 changed files with 172 additions and 1278 deletions

View File

@@ -24,22 +24,32 @@ fileignoreconfig:
- filename: screens/AuthScreenController.ts
checksum: 18af825821bc95e1056050623b804a5a8e7435b9e3383916a5d63024eeba9553
- filename: screens/WelcomeScreenController.ts
checksum: d8fe74404c80bf435459f4d20427a661fb622f0ee9f754345616abd346b98d14
- filename: machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine.ts
checksum: 237a2640b7db70770d65da67c79f2929581e32f1162517e50b8d37e409f3387d
- filename: machines/store.ts
checksum: b9884f86b498dfbff75816d1f0d521c79971c8c28afa7824122d025b2699cdc4
- filename: shared/cryptoutil/cryptoUtil.ts
checksum: b785ff3f01ab9530119072c4d38195048bfeee6155c54ea7dd031559acb722f3
checksum: 71917c8c543a4a5b7ab61df259b785d233a80718123b0c8edf6ec81e1b3a81e0
- filename: shared/telemetry/TelemetryUtils.js
checksum: ffe9aac2dcc590b98b0d588885c088eff189504ade653a77f74b67312bfd27ad
- filename: shared/fileStorage.ts
checksum: 07cb337dc1d5b0f0eef56270ac4f4f589260ee5e490183c024cf98a2aeafb139
- filename: shared/storage.ts
checksum: c8d874aa373bdf526bf59192139822f56915e702ef673bac4e0d7549b0fea3d0
checksum: f9711b617b986af9bb733a31373e49494667ef07b74988fbf09688cb50ca73bd
- filename: screens/Home/IntroSlidersScreen.tsx
checksum: 72ef913857448ef05763e52e32356faa2d1f3de8130a1c638d1897f44823031f
- filename: shared/commonUtil.ts
checksum: 01c3fdcd2f1c1757eae0c6a27fe04eb70c2aaf8660c604f3301997484592b66c
- filename: screens/Home/MyVcs/GetIdInputModal.tsx
checksum: 5c736ed79a372d0ffa7c02eb33d0dc06edbbb08d120978ff287f5f06cd6c7746
- filename: shared/openId4VCI/Utils.ts
checksum: 2bd39d84099d700e5bddeebe87dfb3b0e3075edc0a4d06ce48b428b0a85e238f
- filename: machines/issuersMachine.ts
checksum: b925df13236145867fc7a1a2a703faca854e8c937dac9451008399e3937592fb
- filename: machines/issuersMachine.typegen.ts
checksum: f5e2c89f9029b1e590173e37b2cf6586d5229ecb7d4dfd4c5f050f9416d3c1cd
- filename: machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine.ts
checksum: eec77ca61540327ff7cab3489ebdfd47aa373fd20b3ff87a6c322cd48d35fe8f
- filename: machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine.typegen.ts
checksum: f1f504bd8c14496ee71f8eb7f40d54411cc05be03347d644dcc2cca187a20678
version: ""
- filename: machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine.ts
checksum: 237a2640b7db70770d65da67c79f2929581e32f1162517e50b8d37e409f3387d
- filename: machines/store.ts
checksum: 0695d833df9ec1e1f6ae2bd81631630bb1039dec387718acb153bcb843c952cd
- filename: shared/cryptoutil/cryptoUtil.ts
checksum: b785ff3f01ab9530119072c4d38195048bfeee6155c54ea7dd031559acb722f3

View File

@@ -1,18 +0,0 @@
{
"VC_SHARED": "shared",
"VC_RECEIVED": "received",
"VC_RECEIVED_NOT_SAVED": "received was not saved",
"VC_DELETED": "deleted",
"VC_DOWNLOADED": "downloaded",
"VC_REVOKED": "revoked",
"VC_SHARED_WITH_VERIFICATION_CONSENT": "shared. Consent is given for presence verification",
"VC_RECEIVED_WITH_PRESENCE_VERIFIED": "received. Presence verified",
"VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "received. Presence verification failed",
"PRESENCE_VERIFIED_AND_VC_SHARED": "verified and shared",
"PRESENCE_VERIFICATION_FAILED": "verification failed",
"QRLOGIN_SUCCESFULL": "QRLogin successful",
"WALLET_BINDING_SUCCESSFULL": "Activation successful",
"WALLET_BINDING_FAILURE": "Activation failed",
"VC_REMOVED": "Removed from wallet",
"TAMPERED_VC_REMOVED": "Some cards removed due to malicious activity"
}

View File

@@ -1,6 +0,0 @@
{
"requestedBy": "Requested by",
"sentBy": "Sent by",
"deviceRefNumber": "Device reference number",
"name": "Name"
}

View File

@@ -38,16 +38,16 @@ export const EditableListItem: React.FC<EditableListItemProps> = props => {
/>
<ListItem.Content>
<ListItem.Title>
<Text weight="semibold" color={Theme.Colors.profileLabel}>
<Text weight="semibold" color={props.titleColor}>
{props.title}
</Text>
</ListItem.Title>
<Text color={Theme.Colors.profileValue}>{props.content}</Text>
<Text color={Theme.Colors.textLabel}>{props.content}</Text>
</ListItem.Content>
<Icon
name="chevron-right"
size={21}
color={Theme.Colors.profileLanguageValue}
color={Theme.Colors.chevronRightColor}
/>
<Overlay
overlayStyle={{padding: 24, elevation: 6}}
@@ -120,6 +120,7 @@ interface EditableListItemProps {
onCancel: () => void;
progress?: boolean;
errorMessage?: string;
titleColor: string;
}
interface ListItemProps {

View File

@@ -1 +0,0 @@
{}

View File

@@ -26,6 +26,7 @@ import {GlobalContext} from '../shared/GlobalContext';
import {selectIsActive} from '../machines/app';
import {RotatingIcon} from './RotatingIcon';
import {Theme} from './ui/styleUtils';
import {isIOS} from '../shared/constants';
export const FaceScanner: React.FC<FaceScannerProps> = props => {
const {t} = useTranslation('FaceScanner');
@@ -130,7 +131,7 @@ export const FaceScanner: React.FC<FaceScannerProps> = props => {
</Row>
)}
{/* TODO: remove warning when iOS SDK is ready */}
{Platform.OS === 'ios' && (
{isIOS() && (
<Text size="smaller" color={Theme.Colors.textLabel} align="center">
(face-matching in iOS is mocked)
</Text>

View File

@@ -1,8 +1,9 @@
import React from 'react';
import {useInterpret} from '@xstate/react';
import {appMachine, logState} from '../machines/app';
import {appMachine} from '../machines/app';
import {GlobalContext} from '../shared/GlobalContext';
import {logState} from '../shared/commonUtil';
export const GlobalContextProvider: React.FC = props => {
const appService = useInterpret(appMachine, {devTools: __DEV__});

View File

@@ -1,5 +0,0 @@
{
"title": "OIDC Authentication",
"text": "To be replaced with the OIDC provider UI",
"verify": "Verify"
}

View File

@@ -1,3 +0,0 @@
{
"passcodeMismatchError": "Passcode did not match."
}

View File

@@ -1,4 +0,0 @@
{
"missingPermissionText": "This app uses the camera to scan the QR code of another device.",
"allowCameraButton": "Allow access to camera"
}

View File

@@ -323,7 +323,7 @@ export const MosipVCItemContent: React.FC<
function faceImageSource() {
return !verifiableCredential
? Theme.ProfileIcon
? Theme.cardFaceIcon
: {
uri: props.vcMetadata.isFromOpenId4VCI()
? verifiableCredential?.credentialSubject.face

View File

@@ -49,7 +49,7 @@ const getProfileImage = (
return {uri: props.vc?.credential.biometrics.face};
}
}
return Theme.ProfileIcon;
return Theme.cardFaceIcon;
};
export const MosipVCItemDetails: React.FC<

View File

@@ -1,22 +0,0 @@
{
"generatedOn": "Generated On",
"status": "Status",
"valid": "Valid",
"photo": "Photo",
"fullName": "Full Name",
"gender": "Gender",
"dateOfBirth": "Date of Birth",
"phoneNumber": "Phone Number",
"email": "Email",
"address": "Address",
"reasonForSharing": "Reason for sharing",
"idType": "ID Type",
"id": "Id",
"nationalCard": "National Card",
"uin": "UIN",
"vid": "VID",
"enableVerification": "Enable Verification",
"profileAuthenticated": "Profile is authenticated!",
"offlineAuthDisabledHeader": "Offline Authentication disabled!",
"offlineAuthDisabledMessage": "Click 'Enable Authentication' to enable this credentials to be used for offline authentication."
}

View File

@@ -26,7 +26,7 @@ export const Loader: React.FC<LoaderProps> = props => {
{props.subTitle && (
<Text
style={Theme.TextStyles.subHeader}
color={Theme.Colors.profileValue}
color={Theme.Colors.textLabel}
testID="loaderSubTitle">
{props.subTitle}
</Text>

View File

@@ -57,7 +57,7 @@ export const Modal: React.FC<ModalProps> = props => {
color={
props.headerLabelColor
? props.headerLabelColor
: Theme.Colors.profileLanguageValue
: Theme.Colors.textLabel
}>
{props.headerLabel}
</Text>

View File

@@ -1,6 +1,7 @@
/* eslint-disable sonarjs/no-duplicate-string */
import {Dimensions, Platform, StyleSheet, ViewStyle} from 'react-native';
import {Spacing} from '../styleUtils';
import {isIOS} from '../../../shared/constants';
const Colors = {
Black: '#000000',
@@ -61,11 +62,7 @@ export const DefaultTheme = {
borderBottomColor: Colors.Grey6,
whiteBackgroundColor: Colors.White,
lightGreyBackgroundColor: Colors.LightGrey,
profileLanguageValue: Colors.Grey,
aboutVersion: Colors.Gray40,
profileAuthFactorUnlock: Colors.Grey,
profileLabel: Colors.Black,
profileValue: Colors.Grey,
switchHead: Colors.Orange,
switchTrackTrue: Colors.LightOrange,
switchTrackFalse: Colors.Grey,
@@ -89,7 +86,6 @@ export const DefaultTheme = {
OnboardingCloseIcon: Colors.White,
WarningIcon: Colors.Warning,
DefaultToggle: Colors.LightOrange,
ProfileIconBg: Colors.LightOrange,
GrayText: Colors.GrayText,
errorGrayText: Colors.mediumDarkGrey,
gradientBtn: ['#F59B4B', '#E86E04'],
@@ -108,6 +104,8 @@ export const DefaultTheme = {
statusMessage: Colors.Gray40,
blackIcon: Colors.Black,
uncheckedIcon: Colors.uncheckedIcon,
settingsLabel: Colors.Black,
chevronRightColor: Colors.Grey,
},
Styles: StyleSheet.create({
title: {
@@ -499,9 +497,9 @@ export const DefaultTheme = {
width: Dimensions.get('window').width * 0.32,
borderBottomWidth: 1,
marginBottom: 2,
borderColor: Platform.OS === 'ios' ? 'transparent' : Colors.Grey,
bottom: Platform.OS === 'ios' ? 50 : 24,
height: Platform.OS === 'ios' ? 100 : 'auto',
borderColor: isIOS() ? 'transparent' : Colors.Grey,
bottom: isIOS() ? 50 : 24,
height: isIOS() ? 100 : 'auto',
},
idInputBottom: {
borderBottomColor: Colors.Orange,
@@ -1236,7 +1234,7 @@ export const DefaultTheme = {
CardBackground: require('../../../assets/card_bg.png'),
OpenCard: require('../../../assets/card_bg.png'),
activationPending: require('../../../assets/pending_activation.png'),
ProfileIcon: require('../../../assets/placeholder-photo.png'),
cardFaceIcon: require('../../../assets/placeholder-photo.png'),
MosipSplashLogo: require('../../../assets/icon.png'),
MosipLogo: require('../../../assets/mosip-logo.png'),
CameraFlipIcon: require('../../../assets/camera-flip-icon.png'),
@@ -1306,17 +1304,16 @@ export const DefaultTheme = {
};
function generateBoxShadowStyle() {
if (Platform.OS === 'ios') {
if (isIOS()) {
return {
shadowColor: '#000',
shadowOffset: {width: 1, height: 1.2},
shadowOpacity: 0.3,
shadowRadius: 2.5,
};
} else if (Platform.OS === 'android') {
return {
elevation: 4,
shadowColor: '#000',
};
}
return {
elevation: 4,
shadowColor: '#000',
};
}

View File

@@ -1,6 +1,7 @@
/* eslint-disable sonarjs/no-duplicate-string */
import {Dimensions, Platform, StyleSheet, ViewStyle} from 'react-native';
import {Spacing} from '../styleUtils';
import {isIOS} from '../../../shared/constants';
const Colors = {
Black: '#231F20',
@@ -64,11 +65,7 @@ export const PurpleTheme = {
whiteBackgroundColor: Colors.White,
lightGreyBackgroundColor: Colors.LightGrey,
errorGrayText: Colors.mediumDarkGrey,
profileLanguageValue: Colors.Grey,
aboutVersion: Colors.Gray40,
profileAuthFactorUnlock: Colors.Grey,
profileLabel: Colors.Black,
profileValue: Colors.Grey,
switchHead: Colors.Purple,
switchTrackTrue: Colors.LightPurple,
switchTrackFalse: Colors.Grey,
@@ -92,7 +89,6 @@ export const PurpleTheme = {
OnboardingCloseIcon: Colors.White,
WarningIcon: Colors.Warning,
DefaultToggle: Colors.LightPurple,
ProfileIconBg: Colors.LightPurple,
GrayText: Colors.GrayText,
gradientBtn: Colors.GradientColors,
dotColor: Colors.dorColor,
@@ -110,6 +106,8 @@ export const PurpleTheme = {
statusMessage: Colors.Gray40,
blackIcon: Colors.Black,
uncheckedIcon: Colors.uncheckedIcon,
settingsLabel: Colors.Black,
chevronRightColor: Colors.Grey,
},
Styles: StyleSheet.create({
title: {
@@ -501,9 +499,9 @@ export const PurpleTheme = {
width: Dimensions.get('window').width * 0.32,
borderBottomWidth: 1,
marginBottom: 2,
borderColor: Platform.OS === 'ios' ? 'transparent' : Colors.Grey,
bottom: Platform.OS === 'ios' ? 50 : 24,
height: Platform.OS === 'ios' ? 100 : 'auto',
borderColor: isIOS() ? 'transparent' : Colors.Grey,
bottom: isIOS() ? 50 : 24,
height: isIOS() ? 100 : 'auto',
},
idInputBottom: {
borderBottomColor: Colors.Orange,
@@ -1234,7 +1232,7 @@ export const PurpleTheme = {
CardBackground: require('../../../assets/card_bg.png'),
OpenCard: require('../../../assets/card_bg.png'),
activationPending: require('../../../assets/pending_activation.png'),
ProfileIcon: require('../../../purpleAssets/profile_icon.png'),
cardFaceIcon: require('../../../purpleAssets/profile_icon.png'),
MosipSplashLogo: require('../../../assets/icon.png'),
MosipLogo: require('../../../assets/mosip-logo.png'),
CameraFlipIcon: require('../../../assets/camera-flip-icon.png'),
@@ -1304,17 +1302,16 @@ export const PurpleTheme = {
};
function generateBoxShadowStyle() {
if (Platform.OS === 'ios') {
if (isIOS()) {
return {
shadowColor: '#000',
shadowOffset: {width: 1, height: 1.2},
shadowOpacity: 0.3,
shadowRadius: 2.5,
};
} else if (Platform.OS === 'android') {
return {
elevation: 4,
shadowColor: '#000',
};
}
return {
elevation: 4,
shadowColor: '#000',
};
}

View File

@@ -357,11 +357,6 @@
"confirmPasscode": "قم بتأكيد رمز المرور",
"enterPasscode": "أدخل رمز المرور الخاص"
},
"AppMetaData": {
"header": "حول إنجي",
"version": "الإصدار",
"useBle": "مدعوم من BLE"
},
"QrLogin": {
"title": "QR تسجيل الدخول",
"alignQr": "قم بمحاذاة رمز الاستجابة السريعة داخل الإطار للمسح الضوئي",

View File

@@ -364,11 +364,6 @@
"confirmPasscode": "Confirm passcode",
"enterPasscode": "Enter your passcode"
},
"AppMetaData": {
"header": "About Inji",
"version": "Version",
"useBle": "Powered by BLE"
},
"QrLogin": {
"title": "QR Login",
"alignQr": "Align the QR code within the frame to scan",

View File

@@ -356,11 +356,6 @@
"confirmPasscode": "Kumpirmahin ang passcode",
"enterPasscode": "Ilagay ang iyong passcode"
},
"AppMetaData": {
"header": "Tungkol kay Inji",
"version": "Bersyon",
"useBle": "Pinapatakbo ng BLE"
},
"QrLogin": {
"title": "QR Login",
"alignQr": "I-align ang QR code sa loob ng frame para i-scan",

View File

@@ -356,11 +356,6 @@
"confirmPasscode": "पासकोड की पुष्टि करें",
"enterPasscode": "अपना पासकोड प्रविष्ट करें"
},
"AppMetaData": {
"header": "इंजी के बारे में",
"version": "संस्करण",
"useBle": "BLE द्वारा संचालित"
},
"QrLogin": {
"title": "क्यूआर लॉगिन",
"alignQr": "स्कैन करने के लिए फ्रेम के भीतर क्यूआर कोड को संरेखित करें",

View File

@@ -353,11 +353,6 @@
"confirmPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ಅನ್ನು ದೃಢೀಕರಿಸಿ",
"enterPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ನಮೂದಿಸಿ"
},
"AppMetaData": {
"header": "ಇಂಜಿ ಬಗ್ಗೆ",
"version": "ಆವೃತ್ತಿ",
"useBle": "BLE ನಿಂದ ನಡೆಸಲ್ಪಡುತ್ತಿದೆ"
},
"QrLogin": {
"title": "QR ಲಾಗಿನ್",
"alignQr": "ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಚೌಕಟ್ಟಿನೊಳಗೆ QR ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ",

View File

@@ -254,11 +254,6 @@
"confirmPasscode": "Confirma tu código de acceso",
"enterPasscode": "Ingresa tu código de acceso"
},
"AppMetaData": {
"header": "Acerca de Inji",
"version": "Versión",
"useBle": "Impulsado por BLE"
},
"SettingScreen": {
"header": "Ajustes",
"injiAsVerifierApp": "Inji como aplicación verificadora",
@@ -734,11 +729,6 @@
"confirmPasscode": "Confirma tu código de acceso",
"enterPasscode": "Ingresa tu código de acceso"
},
"AppMetaData": {
"header": "Acerca de Inji",
"version": "Versión",
"useBle": "Impulsado por BLE"
},
"SettingScreen": {
"header": "Ajustes",
"injiAsVerifierApp": "Inji como aplicación verificadora",

View File

@@ -353,11 +353,6 @@
"confirmPasscode": "கடவுக்குறியீட்டை உறுதிப்படுத்தவும்",
"enterPasscode": "உங்கள் கடவுக்குறியீட்டை உள்ளிடவும்"
},
"AppMetaData": {
"header": "இன்ஜி பற்றி",
"version": "பதிப்பு",
"useBle": "BLE ஆல் இயக்கப்படுகிறது"
},
"QrLogin": {
"title": "QR உள்நுழைவு",
"alignQr": "ஸ்கேன் செய்ய ஃப்ரேமுக்குள் QR குறியீட்டை சீரமைக்கவும்",

View File

@@ -1,17 +1,13 @@
import NetInfo, {NetInfoStateType} from '@react-native-community/netinfo';
import {AppState, AppStateStatus, Platform} from 'react-native';
import {
getDeviceId,
getDeviceName,
getDeviceNameSync,
} from 'react-native-device-info';
import {EventFrom, spawn, StateFrom, send, assign, AnyState} from 'xstate';
import {getDeviceId, getDeviceName} from 'react-native-device-info';
import {assign, EventFrom, send, spawn, StateFrom} from 'xstate';
import {createModel} from 'xstate/lib/model';
import {authMachine, createAuthMachine} from './auth';
import {createSettingsMachine, settingsMachine} from './settings';
import {StoreEvents, storeMachine} from './store';
import {createVcMachine, vcMachine} from './vc';
import {createActivityLogMachine, activityLogMachine} from './activityLog';
import {activityLogMachine, createActivityLogMachine} from './activityLog';
import {
createRequestMachine,
requestMachine,
@@ -20,19 +16,19 @@ import {createScanMachine, scanMachine} from './bleShare/scan/scanMachine';
import {createRevokeMachine, revokeVidsMachine} from './revoke';
import {pure, respond} from 'xstate/lib/actions';
import {AppServices} from '../shared/GlobalContext';
import {request} from '../shared/request';
import {
changeCrendetialRegistry,
SETTINGS_STORE_KEY,
MIMOTO_BASE_URL,
ESIGNET_BASE_URL,
changeEsignetUrl,
ESIGNET_BASE_URL,
isAndroid,
MIMOTO_BASE_URL,
SETTINGS_STORE_KEY,
} from '../shared/constants';
import {logState} from '../shared/commonUtil';
const model = createModel(
{
info: {} as AppInfo,
backendInfo: {} as BackendInfo,
serviceRefs: {} as AppServices,
isReadError: false,
isDecryptError: false,
@@ -51,7 +47,6 @@ const model = createModel(
REQUEST_DEVICE_INFO: () => ({}),
READY: (data?: unknown) => ({data}),
APP_INFO_RECEIVED: (info: AppInfo) => ({info}),
BACKEND_INFO_RECEIVED: (info: BackendInfo) => ({info}),
STORE_RESPONSE: (response: unknown) => ({response}),
RESET_KEY_INVALIDATE_ERROR_DISMISS: () => ({}),
},
@@ -135,19 +130,8 @@ export const appMachine = model.createMachine(
},
on: {
APP_INFO_RECEIVED: {
target: 'devinfo',
actions: ['setAppInfo'],
},
},
},
devinfo: {
invoke: {
src: 'getBackendInfo',
},
on: {
BACKEND_INFO_RECEIVED: {
target: '#ready',
actions: ['setBackendInfo'],
actions: ['setAppInfo'],
},
},
},
@@ -286,7 +270,7 @@ export const appMachine = model.createMachine(
scanMachine.id,
);
if (Platform.OS === 'android') {
if (isAndroid()) {
serviceRefs.request = spawn(
createRequestMachine(serviceRefs),
requestMachine.id,
@@ -310,7 +294,7 @@ export const appMachine = model.createMachine(
context.serviceRefs.activityLog.subscribe(logState);
context.serviceRefs.scan.subscribe(logState);
if (Platform.OS === 'android') {
if (isAndroid()) {
context.serviceRefs.request.subscribe(logState);
}
@@ -322,10 +306,6 @@ export const appMachine = model.createMachine(
info: (_, event) => event.info,
}),
setBackendInfo: model.assign({
backendInfo: (_, event) => event.info,
}),
loadCredentialRegistryHostFromStorage: send(
StoreEvents.GET(SETTINGS_STORE_KEY),
{
@@ -363,23 +343,6 @@ export const appMachine = model.createMachine(
callback(model.events.APP_INFO_RECEIVED(appInfo));
},
getBackendInfo: () => async callback => {
let backendInfo = {
application: {
name: '',
version: '',
},
build: {},
config: {},
};
try {
backendInfo = await request('GET', '/residentmobileapp/info');
callback(model.events.BACKEND_INFO_RECEIVED(backendInfo));
} catch {
callback(model.events.BACKEND_INFO_RECEIVED(backendInfo));
}
},
checkFocusState: () => callback => {
const changeHandler = (newState: AppStateStatus) => {
switch (newState) {
@@ -398,8 +361,7 @@ export const appMachine = model.createMachine(
AppState.addEventListener('change', changeHandler);
// android only
if (Platform.OS === 'android') {
if (isAndroid()) {
AppState.addEventListener('blur', blurHandler);
AppState.addEventListener('focus', focusHandler);
}
@@ -407,7 +369,7 @@ export const appMachine = model.createMachine(
return () => {
AppState.removeEventListener('change', changeHandler);
if (Platform.OS === 'android') {
if (isAndroid()) {
AppState.removeEventListener('blur', blurHandler);
AppState.removeEventListener('focus', focusHandler);
}
@@ -432,25 +394,11 @@ interface AppInfo {
deviceName: string;
}
interface BackendInfo {
application: {
name: string;
version: string;
};
build: object;
config: object;
}
type State = StateFrom<typeof appMachine>;
export function selectAppInfo(state: State) {
return state.context.info;
}
export function selectBackendInfo(state: State) {
return state.context.backendInfo;
}
export function selectIsReady(state: State) {
return state.matches('ready');
}
@@ -467,28 +415,6 @@ export function selectIsFocused(state: State) {
return state.matches('ready.focus');
}
export function logState(state: AnyState) {
const data = JSON.stringify(
state.event,
(key, value) => {
if (key === 'type') return undefined;
if (typeof value === 'string' && value.length >= 100) {
return value.slice(0, 100) + '...';
}
return value;
},
2,
);
console.log(
`[${getDeviceNameSync()}] ${state.machine.id}: ${
state.event.type
} -> ${state.toStrings().pop()}\n${
data.length > 300 ? data.slice(0, 300) + '...' : data
}
`,
);
}
export function selectIsReadError(state: State) {
return state.context.isReadError;
}

View File

@@ -2,6 +2,7 @@ import {createModel} from 'xstate/lib/model';
import * as LocalAuthentication from 'expo-local-authentication';
import {EventFrom, MetaObject, StateFrom} from 'xstate';
import {Platform} from 'react-native';
import {isAndroid} from '../shared/constants';
// ----- CREATE MODEL ---------------------------------------------------------
const model = createModel(
@@ -99,7 +100,7 @@ export const biometricsMachine = model.createMachine(
authenticating: {
invoke: {
src: () => async () => {
if (Platform.OS === 'android') {
if (isAndroid()) {
await LocalAuthentication.cancelAuthenticate();
}
const res = await LocalAuthentication.authenticateAsync({

View File

@@ -14,7 +14,7 @@ import {getDeviceNameSync} from 'react-native-device-info';
import {StoreEvents} from '../../store';
import {VC} from '../../../types/VC/ExistingMosipVC/vc';
import {AppServices} from '../../../shared/GlobalContext';
import {RECEIVED_VCS_STORE_KEY} from '../../../shared/constants';
import {isAndroid, RECEIVED_VCS_STORE_KEY} from '../../../shared/constants';
import {ActivityLogEvents, ActivityLogType} from '../../activityLog';
import {VcEvents} from '../../vc';
import {subscribe} from '../../../shared/openIdBLE/verifierEventHandler';
@@ -736,7 +736,7 @@ export const requestMachine =
},
checkNearByDevicesPermission: () => callback => {
if (Platform.OS === 'android' && Platform.Version >= 31) {
if (isAndroid() && Platform.Version >= 31) {
const result = checkMultiple([
PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE,
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,

View File

@@ -17,7 +17,7 @@ import {getDeviceNameSync} from 'react-native-device-info';
import {VC, VerifiablePresentation} from '../../../types/VC/ExistingMosipVC/vc';
import {AppServices} from '../../../shared/GlobalContext';
import {ActivityLogEvents, ActivityLogType} from '../../activityLog';
import {MY_LOGIN_STORE_KEY} from '../../../shared/constants';
import {isAndroid, isIOS, MY_LOGIN_STORE_KEY} from '../../../shared/constants';
import {subscribe} from '../../../shared/openIdBLE/walletEventHandler';
import {
check,
@@ -38,7 +38,6 @@ import {StoreEvents} from '../../store';
import {WalletDataEvent} from 'react-native-tuvali/lib/typescript/types/events';
import {BLEError} from '../types';
import Storage from '../../../shared/storage';
import {logState} from '../../app';
import {VCMetadata} from '../../../shared/VCMetadata';
import {
getStartEventData,
@@ -46,6 +45,7 @@ import {
sendStartEvent,
sendEndEvent,
} from '../../../shared/telemetry/TelemetryUtils';
import {logState} from '../../../shared/commonUtil';
const {wallet, EventTypes, VerificationStatus} = tuvali;
@@ -721,7 +721,7 @@ export const scanMachine =
value: context.linkCode,
}),
openBluetoothSettings: () => {
Platform.OS === 'android'
isAndroid()
? BluetoothStateManager.openSettings().catch()
: Linking.openURL('App-Prefs:Bluetooth');
},
@@ -905,7 +905,7 @@ export const scanMachine =
// Passing Granted for android since permission status is always granted even if its denied.
let response: PermissionStatus = RESULTS.GRANTED;
if (Platform.OS === 'ios') {
if (isIOS()) {
response = await check(PERMISSIONS.IOS.BLUETOOTH_PERIPHERAL);
}
@@ -1107,9 +1107,9 @@ export const scanMachine =
}
},
uptoAndroid11: () => Platform.OS === 'android' && Platform.Version < 31,
uptoAndroid11: () => isAndroid() && Platform.Version < 31,
isIOS: () => Platform.OS === 'ios',
isIOS: () => isIOS(),
isMinimumStorageRequiredForAuditEntryReached: (_context, event) =>
Boolean(event.data),

View File

@@ -1,7 +1,11 @@
import {authorize, AuthorizeResult} from 'react-native-app-auth';
import {assign, EventFrom, send, sendParent, StateFrom} from 'xstate';
import {createModel} from 'xstate/lib/model';
import {MY_VCS_STORE_KEY} from '../shared/constants';
import {
MY_VCS_STORE_KEY,
NETWORK_REQUEST_FAILED,
REQUEST_TIMEOUT,
} from '../shared/constants';
import {StoreEvents} from './store';
import {AppServices} from '../shared/GlobalContext';
import NetInfo from '@react-native-community/netinfo';
@@ -23,8 +27,8 @@ import {
updateCredentialInformation,
constructAuthorizationConfiguration,
getVCMetadata,
Issuers_Key_Ref,
} from '../shared/openId4VCI/Utils';
import {NETWORK_REQUEST_FAILED, REQUEST_TIMEOUT} from '../shared/constants';
import {VCMetadata} from '../shared/VCMetadata';
import {
getEndEventData,
@@ -71,7 +75,6 @@ const model = createModel(
export const IssuerScreenTabEvents = model.events;
export const Issuer_Tab_Ref_Id = 'issuersMachine';
export const Issuers_Key_Ref = 'OpenId4VCI_KeyPair';
export const IssuersMachine = model.createMachine(
{
/** @xstate-layout N4IgpgJg5mDOIC5QEtawK5gE6wLIEMBjAC2QDswA6CVABwBt8BPASTUxwGIIB7Cy8gDceAayqoM2PEVL8asBszaScCIT0L4ALsj4BtAAwBdQ0cShaPWMh19zIAB6IALAEYAnJWfuAzM4BsAKwAHN7BwQDsfgA0IEyIAEw+Ea6UBgkRwT7uEekGrhHOAL5FsRIc0iTkVPKKrOxSnNhYPFiUiloAZq0AtgINOARVcnSM9SqwamTCmrZkpqb2ltZz9k4Izgme3n5Boe7hUc6x8QgJ3gZpgT6BgRH+yYWBJWUDlbJUza2cACoASgBNAD6AEEAOIglgAOUWSBAyxsujIaxcWy8vgCITCkRicUSIQSlGyCQMETu7n84QKLxA5SkQw+lC+WF+gNBEOhelcZjhCNWcPWrgSJ0QQppdMGMmqTKwLRZ-2B4MhMISPIsVkRdgFooMvjS-jc9wezl1ARFZwiCUClFcN3czmcKWuPnFbwZ0uZnD+AFEAMren5A71-P4AeT+sPVKyRKIQrgMwX8lASCWCgVcgW8lt15oyEU8CSCloz6WcN38rom7v4sDA9DAhB0ZCgyg4nAAIqGAOpQgAyoZB7aBLHbkfhGv5oHWPgMBmclEigQM-lTVpyc9z+R8yfzriyPhTS4zlYq1aotfrjfILYGnH9ve9AGEft6hyxfb6AKrBsd8mPahBAmFPEEB8VwhS8XVkgKA5dXcE96SlOQeAAdzIegeHwCBW2wR8+E6ZAoG4PhxGmURxDdJCalQ9DMOwgY8LIAioCmGZtCRBZjCWCd-ynUVgNOMVSlpSjhmotCMKwnCsEY5imllVp2kYLpen6KsqOoGjJPolRZMI1iNHY-RjF-HitT4jYUwXZwgMpFMfHCGcIlze15zuFdghyA5UweBDJTEygSAbEQWDILRsAoLRiP4dQxEC4hgtC8KsEi0zo3MxxRVuQlLUCdxdUzbIhX8c14w8Iky1ucI1zTYI-PeaUgsIEKwoisAot4GKyLipqWuS1LuW49LkQA4I0SFdxwOXO1-HSUrbUuLZSX8XwMn8Vwy3qs94sS1qUva+S5SU7RuiwPpeqStqtDSzURos4IIMpB5i1moCHPNSbgi8QIDXcPLcltDIto0i69simU5QSVlFQ5GEuN5My7syuNkiTfJJvyDwiyCUrZ2tPwbimoDMhuYGAtobBTp6EF0C0YhWmQAAvIyyGi0jhDiiUGv4CmsCpmm6YZ5m5gM2YOJM+Go1u2NbJtFbJoyN7U3cc0V2tbxXH8FdHSPe0ycZXn+dp+msCZlnDsUjoqbU08NMN3oBZNs2RfUMXjJMSXx2GmXNbl9wFbJJJlfNB6bUiLYbiW-KIgifXpXts7HaF83mWOlSzptxDycph3jeTl2yLd+YTMGhHvYA64k01-2hUDg9PNK5J52CAwZ3TQpwNj4Sue23qAGkwCYAAFfBkBZR8AAknz7oE++9YEh8hCNPb-DLBTnKuPD+h15cKc0qptDaMcibxnm70TGX7weR7HzhJ+n2f56BReWAjUupcnZH4x8Tf-czAJ-Z7xAskS4YFiQeXOJ5F0591IBRgBQLA2gwAD2HqPFknV2bkUzv5Rk8DsBIJQTfLAosWacTVF7aWAECjZEoPlTy6Z1o5HOOaPwqRqoOQyGNTMKY478DwYg8KhC0FswEN1CisDcFgAQQQ6+aCSFzAWO-Chn9BRRE8HQv6msPCWmOCBFMhI0xBH8DHMkOQyS8PErRLCj4sCQCkTofA9BYAiNiuI22AVeASTojYuxYVkCOMmK7UhEtyGryRusGyER9SWgpIVCkYFAi5j3EmG4CZW4OSbsUGB7jGSeKsRAHxEB7H+KcRbNoVtVI9w0nk7ShTikBPkeLD2oTEaxkidErYQQyzxIzLmThlBKSrQzJsKkFjNJeOsbYopfiAl3xBFCR83pew3RUS4R0HTYndIeL0kCe4ogVSyB4ByMcNpjMENgZAnQmDXjqTM+gLixHYO5lQc5psrk3KmfU+gjT3YrN4l-eMnguF3HOAkDMDlEl6ITFXYxDosjnCONA14EjpSvMudc5styHH3NThUjOVSApoveZiz5dyfnF2aUNShFkppAqtCCzY4K0x9IMNafMDCDgPBJAeMZyAID1jvqGXAQ8HwvlHCvVpVC1ZeG5VsVMUQ9l9JNAM5wY0W6pnjJEXl-KwBzIWUsv5a9RTSs2K3OVOJFV6NtKkG4eVUytx+jymkZAeBFPgHCAlHwqWrIQAAWh-uaX1ZIw6WnuJVKIK0EhjNqGMaS7qP7-PWJaXMP0okmhTPmGOFJ4wVmyVnRkzJvWJsQC3IFOQNqJkKPmG4uZMiXF1JSTYhZ0i7DGReBsTYbwqCLUauMu4iRUh+pmIUG0km2gGQURMqNNibTzTg6UNS6LST0lAHt4TEDGJcoWWhI6xreACGSXNyKcmNQSs1S6+0tBrtjGGgZU6XqsqSMEc0ZJtwFRNAUHeGYz7Hvzae3a-V2oQ1aAka9VCwVROhS3PKfhlwFA+mNZMjxcgORskkI9IkUU8xzonPOpthb-LCW0gSoofB+C8GNFaLd4zLhjmMq+qCx5gYsoehcMcbi7g2imVW5H0yqrGjcPwlo6pzueZQfhMjGNYGY1-PwhISQFGeoJlILCwJeHWhmBVFahK-vnchCZBTSXYvjco4tCAch9LU7Va48ZHSUjORc4lUAsUlJk+sQZyYqrrgNFrZ9VrKR3uMR5TWZGf5tq0AzZsbnSO+0NNkNwbhHKQsEv7bcar8pgW8FsUI2r6zRZRhmNIMdVy5Dyuqyz84AhPXsqqlI0aSL5ZgjawdXSR26NOCmX2WxHS6k-Xxs+JQgA */

View File

@@ -93,7 +93,6 @@ export const settingsMachine = model.createMachine(
},
},
idle: {
entry: ['injiTourGuide'],
on: {
TOGGLE_BIOMETRIC_UNLOCK: {
actions: ['toggleBiometricUnlock', 'storeContext'],
@@ -114,6 +113,9 @@ export const settingsMachine = model.createMachine(
CANCEL: {
actions: ['resetCredentialRegistry'],
},
INJI_TOUR_GUIDE: {
target: 'showInjiTourGuide',
},
ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS: {
actions: [
'updateUserShownWithHardwareKeystoreNotExists',
@@ -146,13 +148,6 @@ export const settingsMachine = model.createMachine(
},
},
},
injiTourGuide: {
on: {
INJI_TOUR_GUIDE: {
target: 'showInjiTourGuide',
},
},
},
showInjiTourGuide: {
on: {
BACK: {

View File

@@ -105,7 +105,7 @@ export const storeMachine =
},
on: {
KEY_RECEIVED: {
actions: ['setEncryptionKey', 'logKey'],
actions: ['setEncryptionKey'],
target: 'ready',
},
ERROR: {

View File

@@ -6,7 +6,6 @@
"android:mosip": "react-native run-android --variant=mosipDebug",
"ios": "react-native run-ios",
"build:android:mosip": "cd android && ./gradlew :app:assembleMosipRelease && cd ..",
"i18n:compile-strings": "node scripts/compile-strings.js",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"test": "jest",
"postinstall": "patch-package && npm run jetify && sh tools/talisman/talisman-precommit.sh"
@@ -128,8 +127,7 @@
"name": "mosip-resident-app",
"version": "1.0.0",
"lint-staged": {
"*.{ts,tsx,js,css,md}": "prettier --write",
"*.strings.json": "node scripts/compile-strings.js"
"*.{ts,tsx,js,css,md}": "prettier --write"
},
"overrides": {
"react": "18.2.0",

View File

@@ -1,11 +0,0 @@
{
"header": "Would you like to use biometrics to unlock the application?",
"useBiometrics": "Use biometrics",
"usePasscode": "I'd rather use a passcode",
"errors": {
"unavailable": "Device does not support Biometrics",
"unenrolled": "To use Biometrics, please enroll your biometrics in your device settings",
"failed": "Failed to authenticate with Biometrics",
"generic": "There seems to be an error in Biometrics authentication"
}
}

View File

@@ -1,3 +0,0 @@
{
"unlock": "Unlock with biometrics"
}

View File

@@ -29,6 +29,7 @@ import {
sendInteractEvent,
sendStartEvent,
} from '../shared/telemetry/TelemetryUtils';
import {isAndroid} from '../shared/constants';
export function useBiometricScreen(props: RootRouteProps) {
const {appService} = useContext(GlobalContext);
@@ -114,7 +115,7 @@ export function useBiometricScreen(props: RootRouteProps) {
]);
const checkBiometricsChange = () => {
if (Platform.OS === 'android') {
if (isAndroid()) {
RNFingerprintChange.hasFingerPrintChanged().then(
async (biometricsHasChanged: boolean) => {
//if new biometrics are added, re-enable Biometrics Authentication

View File

@@ -1,7 +0,0 @@
{
"noHistory": "No history available yet",
"downloaded": "downloaded",
"shared": "shared",
"received": "received",
"deleted": "deleted"
}

View File

@@ -1,5 +0,0 @@
{
"myVcsTab": "My\nCards",
"receivedVcsTab": "Received\nCards",
"historyTab": "History"
}

View File

@@ -64,19 +64,19 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
alignItems: 'flex-end',
}}>
{controller.isPasscodeSet() ? (
<Button
testID="skip"
type="plain"
title={t('skip')}
onPress={controller.NEXT}
/>
) : (
<Button
testID="back"
type="plain"
title={t('back')}
onPress={controller.BACK}
/>
) : (
<Button
testID="skip"
type="plain"
title={t('skip')}
onPress={controller.NEXT}
/>
)}
</Column>
</Row>
@@ -137,7 +137,7 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
align="center"
color="#FFFFFF"
margin="15 0 0 0">
{controller.isPasscodeSet() ? t('getStarted') : t('goBack')}
{controller.isPasscodeSet() ? t('goBack') : t('getStarted')}
</Text>
</LinearGradient>
</View>
@@ -160,7 +160,7 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
dotStyle={{backgroundColor: Theme.Colors.dotColor, marginBottom: 47}}
renderItem={renderItem}
onDone={() =>
controller.isPasscodeSet() ? controller.NEXT() : controller.BACK()
controller.isPasscodeSet() ? controller.BACK() : controller.NEXT()
}
/>
</Column>

View File

@@ -1,16 +0,0 @@
{
"requestingCredential": "Requesting credential...",
"errors": {
"input": {
"empty": "The input cannot be empty",
"invalidFormat": "The input format is incorrect"
},
"backend": {
"invalidOtp": "OTP is invalid",
"invalidUin": "UIN invalid",
"invalidVid": "VID invalid",
"missingUin": "UIN not available in database",
"missingVid": "VID not available in database"
}
}
}

View File

@@ -1,5 +0,0 @@
{
"header": "Downloading your Card",
"bodyText": "This may take some time, we will notify you when your Card has been downloaded and is available",
"backButton": "Back home"
}

View File

@@ -1,7 +0,0 @@
{
"header": "Enter your Application ID to get your UIN",
"getUIN": "Get UIN/VID",
"applicationId": "Application ID",
"requestingOTP": "Requesting OTP...",
"qstnMarkToolTip": "Application ID is available in the acknowledgement received after enrolment."
}

View File

@@ -1,21 +1,22 @@
import React from 'react';
import { Dimensions, I18nManager } from 'react-native';
import { Icon, Input } from 'react-native-elements';
import { Button, Centered, Column, Row, Text } from '../../../components/ui';
import { Modal } from '../../../components/ui/Modal';
import { Theme } from '../../../components/ui/styleUtils';
import {Dimensions, I18nManager} from 'react-native';
import {Icon, Input} from 'react-native-elements';
import {Button, Centered, Column, Row, Text} from '../../../components/ui';
import {Modal} from '../../../components/ui/Modal';
import {Theme} from '../../../components/ui/styleUtils';
import {
GetIdInputModalProps,
useGetIdInputModal,
} from './GetIdInputModalController';
import { KeyboardAvoidingView, Platform } from 'react-native';
import { useTranslation } from 'react-i18next';
import { MessageOverlay } from '../../../components/MessageOverlay';
import {KeyboardAvoidingView, Platform} from 'react-native';
import {useTranslation} from 'react-i18next';
import {MessageOverlay} from '../../../components/MessageOverlay';
import Tooltip from '../../../lib/react-native-elements/tooltip/Tooltip';
import { color } from 'react-native-elements/dist/helpers';
import {color} from 'react-native-elements/dist/helpers';
import {isIOS} from '../../../shared/constants';
export const GetIdInputModal: React.FC<GetIdInputModalProps> = (props) => {
const { t } = useTranslation('GetIdInputModal');
export const GetIdInputModal: React.FC<GetIdInputModalProps> = props => {
const {t} = useTranslation('GetIdInputModal');
const controller = useGetIdInputModal(props);
const inputLabel = t('enterApplicationId');
@@ -27,13 +28,13 @@ export const GetIdInputModal: React.FC<GetIdInputModalProps> = (props) => {
headerTitle={t('header')}
headerElevation={2}>
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
style={{flex: 1}}
behavior={isIOS() ? 'padding' : 'height'}>
<Column fill align="space-between" padding="32 24">
<Column>
<Text
margin="10"
style={{ color: Theme.Colors.GrayText }}
style={{color: Theme.Colors.GrayText}}
weight="regular">
{t('applicationIdLabel')}
</Text>
@@ -86,10 +87,10 @@ export const GetIdInputModal: React.FC<GetIdInputModalProps> = (props) => {
</Centered>
</Tooltip>
}
errorStyle={{ color: Theme.Colors.errorMessage }}
errorStyle={{color: Theme.Colors.errorMessage}}
errorMessage={controller.idError}
onChangeText={controller.INPUT_ID}
ref={(node) => !controller.idInputRef && controller.READY(node)}
ref={node => !controller.idInputRef && controller.READY(node)}
/>
</Row>
</Column>

View File

@@ -1,7 +0,0 @@
{
"header": "Enter your UIN/VID to download your Card",
"generateVc": "Generate My Card",
"enterId": "Enter your {{idType}}",
"noUIN/VID": "Don't have your UIN/VID? Get it here",
"requestingOTP": "Requesting OTP..."
}

View File

@@ -14,7 +14,7 @@ import {
TextInput,
} from 'react-native';
import {TouchableOpacity} from 'react-native';
import {individualId} from '../../../shared/constants';
import {individualId, isIOS} from '../../../shared/constants';
import {GET_INDIVIDUAL_ID} from '../../../shared/constants';
import {MessageOverlay} from '../../../components/MessageOverlay';
import testIDProps from '../../../shared/commonUtil';
@@ -47,7 +47,7 @@ export const IdInputModal: React.FC<IdInputModalProps> = props => {
headerElevation={2}>
<KeyboardAvoidingView
style={{flex: 1}}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
behavior={isIOS() ? 'padding' : 'height'}>
<Column fill align="space-between" pY={32} pX={24}>
<Column>
<Text

View File

@@ -1,6 +0,0 @@
{
"title": "OTP Verification",
"otpSentMessage": "We've sent the 6 digit code to your registered mobile number!",
"resendTheCode": "You can resend the code in ",
"resendCode": "Resend Code"
}

View File

@@ -30,15 +30,6 @@ export const WalletBinding: React.FC<WalletBindingProps> = props => {
return controller.emptyWalletBindingId ? (
<ListItem bottomDivider onPress={controller.ADD_WALLET_BINDING_ID}>
{props.Icon && (
<Icon
name={props.Icon}
type="font-awesome"
size={20}
style={Theme.Styles.profileIconBg}
color={Theme.Colors.Icon}
/>
)}
<ListItem.Content>
<ListItem.Title {...testIDProps('pendingActivationOrActivated')}>
<Text weight="bold" size="small">
@@ -103,7 +94,6 @@ interface WalletBindingProps {
testID?: string;
label: string;
content?: string;
Icon?: string;
service: ActorRefFrom<typeof ExistingMosipVCItemMachine>;
vcMetadata: VCMetadata;
}

View File

@@ -1,87 +0,0 @@
import {useSelector, useInterpret} from '@xstate/react';
import {useContext, useRef, useState} from 'react';
import {GlobalContext} from '../../../shared/GlobalContext';
import {selectMyVcsMetadata, VcEvents} from '../../../machines/vc';
import {
createExistingMosipVCItemMachine,
isShowingBindingWarning,
selectAcceptingBindingOtp,
ExistingMosipVCItemEvents,
selectIsAcceptingOtpInput,
selectOtpError,
selectShowWalletBindingError,
selectWalletBindingError,
} from '../../../machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine';
import {useTranslation} from 'react-i18next';
import {ActorRefFrom} from 'xstate';
export function useWalletBinding(props) {
const {t} = useTranslation('ProfileScreen');
const {appService} = useContext(GlobalContext);
const machine = useRef(
createExistingMosipVCItemMachine(
appService.getSnapshot().context.serviceRefs,
props.vcMetadata,
),
);
const bindingService = useInterpret(machine.current, {devTools: __DEV__});
const vcService = appService.children.get('vc');
const vcsMetadata = useSelector(vcService, selectMyVcsMetadata);
const otpError = useSelector(bindingService, selectOtpError);
const [isRevoking, setRevoking] = useState(false);
const [isAuthenticating, setAuthenticating] = useState(false);
const [isViewing, setIsViewing] = useState(false);
const [isBindingWarning, setisBindingWarning] = useState(false);
const [toastVisible, setToastVisible] = useState(false);
const [message, setMessage] = useState('');
const [selectedIndex, setSelectedIndex] = useState<number>(null);
const [selectedVidKeys, setSelectedVidKeys] = useState<string[]>([]);
const selectVcItem = (index: number, vcKey: string) => {
return () => {
setSelectedIndex(index);
};
};
const WalletBindingInProgress = useSelector(
bindingService,
isWalletBindingInProgress,
);
return {
isBindingWarning,
setisBindingWarning,
otpError,
message,
toastVisible,
WalletBindingInProgress,
isAcceptingOtpInput: useSelector(bindingService, selectIsAcceptingOtpInput),
isAcceptingBindingOtp: useSelector(
bindingService,
selectAcceptingBindingOtp,
),
isBindingError: useSelector(bindingService, selectShowWalletBindingError),
walletBindingError: useSelector(bindingService, selectWalletBindingError),
RESEND_OTP: () =>
bindingService.send(ExistingMosipVCItemEvents.RESEND_OTP()),
DISMISS: () => bindingService.send(ExistingMosipVCItemEvents.DISMISS()),
CONFIRM: () => bindingService.send(ExistingMosipVCItemEvents.CONFIRM()),
CANCEL: () => bindingService.send(ExistingMosipVCItemEvents.CANCEL()),
REFRESH: () => vcService.send(VcEvents.REFRESH_MY_VCS()),
setAuthenticating,
selectVcItem,
setIsViewing,
setRevoking,
};
}

View File

@@ -1,15 +0,0 @@
{
"addVcButton": "Add Card",
"generateVc": "Generate your Cards",
"generateVcDescription": "Tap on \"Add Card\" below to download your Card",
"errors": {
"savingFailed": {
"title": "Failed to save the Card",
"message": "Something went wrong while saving Card to the store."
},
"storageLimitReached": {
"title": "Insufficient Appdata",
"message": "You cannot add or receive cards since the Appdata is full"
}
}
}

View File

@@ -1,9 +0,0 @@
{
"stepOneTitle": "Welcome!",
"stepOneText": "Keep your digital credential with you at all times. To get started, add Cards to your profile.",
"stepTwoTitle": "Card management",
"stepTwoText": "Once generated, Cards are safely stored on your mobile and can be renamed or shared at any time.",
"stepThreeTitle": "Easy sharing",
"stepThreeText": "Share and receive Cards switfly using your phone camera to scan QR codes.",
"stepThreeButton": "Get started and add Card"
}

View File

@@ -1,4 +0,0 @@
{
"noReceivedVcsTitle": "No Cards available yet",
"noReceivedVcsText": "Tap on Request below to receive Card"
}

View File

@@ -1,16 +0,0 @@
{
"cancel": "Cancel",
"lock": "Lock",
"unlock": "Unlock",
"rename": "Rename",
"delete": "Delete",
"revoke": "Revoke",
"revoking": "Your wallet contains a credential with VID {{vid}}. Revoking this will automatically remove the same from the wallet. Are you sure you want to proceed?",
"requestingOtp": "Requesting OTP...",
"redirecting": "Redirecting...",
"success": {
"unlocked": "Card successfully unlocked",
"locked": "Card successfully locked",
"revoked": "VID {{vid}} has been revoked. Any credential containing the same will be removed automatically from the wallet"
}
}

View File

@@ -1,6 +0,0 @@
{
"home": "Home",
"scan": "Scan",
"request": "Request",
"settings": "Settings"
}

View File

@@ -1,5 +0,0 @@
{
"header": "Set a passcode to secure your application",
"confirmPasscode": "Confirm your passcode",
"enterPasscode": "Enter your passcode"
}

View File

@@ -1,190 +0,0 @@
import React from 'react';
import {Platform, View} from 'react-native';
import {getVersion} from 'react-native-device-info';
import {Icon, ListItem, Switch} from 'react-native-elements';
import {Column, Text} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils';
import {MainRouteProps} from '../../routes/main';
import {EditableListItem} from '../../components/EditableListItem';
import {MessageOverlay} from '../../components/MessageOverlay';
import {Revoke} from '../Settings/Revoke';
import {useProfileScreen} from './ProfileScreenController';
import {useTranslation} from 'react-i18next';
import {LanguageSelector} from '../../components/LanguageSelector';
import i18next, {SUPPORTED_LANGUAGES} from '../../i18n';
import {ScrollView} from 'react-native-gesture-handler';
import {AppMetaData} from '../Settings/AppMetaData';
import {CREDENTIAL_REGISTRY_EDIT} from 'react-native-dotenv';
const LanguageSetting: React.FC = () => {
const {t} = useTranslation('ProfileScreen');
return (
<LanguageSelector
triggerComponent={
<ListItem bottomDivider>
<Icon
name="language"
size={20}
color={Theme.Colors.Icon}
style={Theme.Styles.profileIconBg}
/>
<ListItem.Content>
<ListItem.Title>
<Text>{t('language')}</Text>
</ListItem.Title>
</ListItem.Content>
<Text margin="0 12 0 0" color={Theme.Colors.profileLanguageValue}>
{SUPPORTED_LANGUAGES[i18next.language]}
</Text>
</ListItem>
}
/>
);
};
export const ProfileScreen: React.FC<MainRouteProps> = props => {
const {t} = useTranslation('ProfileScreen');
const controller = useProfileScreen(props);
return (
<ScrollView>
<Column
fill
padding="24 0"
backgroundColor={Theme.Colors.lightGreyBackgroundColor}>
<MessageOverlay
isVisible={controller.alertMsg != ''}
onBackdropPress={controller.hideAlert}
title={controller.alertMsg}
/>
<EditableListItem
title={t('name')}
content={controller.name}
items={[
{
label: t('name'),
value: controller.name,
},
]}
onEdit={controller.UPDATE_NAME}
Icon=""
onCancel={() => {}}
/>
{/* Intentionally hidden using {display='none'} - Refer mosip/inji/issue#607 */}
<EditableListItem
title={t('vcLabel')}
content={controller.vcLabel.singular}
items={[
{
label: t('vcLabel'),
value: controller.vcLabel.singular,
},
]}
onEdit={controller.UPDATE_VC_LABEL}
Icon="star"
display="none"
onCancel={() => {}}
/>
<LanguageSetting />
<Revoke label={t('revokeLabel')} Icon="rotate-left" />
<ListItem bottomDivider disabled={!controller.canUseBiometrics}>
<Icon
name="fingerprint"
type="fontawesome"
size={25}
style={Theme.Styles.IconContainer}
color={Theme.Colors.Icon}
/>
<ListItem.Content>
<ListItem.Title>
<Text color={Theme.Colors.profileLabel}>{t('bioUnlock')}</Text>
</ListItem.Title>
</ListItem.Content>
<Switch
value={controller.isBiometricUnlockEnabled}
onValueChange={controller.useBiometrics}
trackColor={{
false: Theme.Colors.switchTrackFalse,
true:
Platform.OS == 'ios'
? Theme.Colors.switchHead
: Theme.Colors.switchTrackTrue,
}}
color={Theme.Colors.switchHead}
/>
</ListItem>
{/* Intentionally hidden using {display:'none'} - Refer mosip/inji/issue#607 */}
<ListItem bottomDivider disabled style={{display: 'none'}}>
<Icon
name="unlock"
size={20}
type="antdesign"
style={Theme.Styles.IconContainer}
color={Theme.Colors.Icon}
/>
<ListItem.Content>
<ListItem.Title>
<Text color={Theme.Colors.profileAuthFactorUnlock}>
{t('authFactorUnlock')}
</Text>
</ListItem.Title>
</ListItem.Content>
</ListItem>
<AppMetaData
label={t('AppMetaData')}
color={Theme.Colors.profileLabel}
/>
{CREDENTIAL_REGISTRY_EDIT === 'true' && (
<EditableListItem
title={t('credentialRegistry')}
content={controller.credentialRegistry}
items={[
{
label: t('credentialRegistry'),
value: controller.credentialRegistry,
},
]}
response={controller.credentialRegistryResponse}
onEdit={controller.UPDATE_CREDENTIAL_REGISTRY}
Icon="star"
onCancel={() => {}}
/>
)}
<ListItem bottomDivider onPress={controller.LOGOUT}>
<Icon
name="logout"
type="fontawesome"
size={20}
style={Theme.Styles.IconContainer}
color={Theme.Colors.Icon}
/>
<ListItem.Content>
<ListItem.Title>
<Text color={Theme.Colors.profileLabel}>{t('logout')}</Text>
</ListItem.Title>
</ListItem.Content>
</ListItem>
{controller.backendInfo.application.name !== '' ? (
<View>
<Text
weight="semibold"
align="center"
size="smaller"
color={Theme.Colors.profileValue}>
{controller.backendInfo.application.name}:{' '}
{controller.backendInfo.application.version}
</Text>
<Text
weight="semibold"
align="center"
size="smaller"
color={Theme.Colors.profileValue}>
MOSIP: {controller.backendInfo.config['mosip.host']}
</Text>
</View>
) : null}
</Column>
</ScrollView>
);
};

View File

@@ -1,137 +0,0 @@
import {useMachine, useSelector} from '@xstate/react';
import {useContext, useEffect, useState} from 'react';
import * as LocalAuthentication from 'expo-local-authentication';
import {selectBackendInfo} from '../../machines/app';
import {
AuthEvents,
selectBiometrics,
selectCanUseBiometrics,
} from '../../machines/auth';
import {
selectBiometricUnlockEnabled,
selectName,
selectCredentialRegistryResponse,
selectVcLabel,
selectCredentialRegistry,
SettingsEvents,
} from '../../machines/settings';
import {
biometricsMachine,
selectError,
selectIsSuccess,
selectUnenrolledNotice,
} from '../../machines/biometrics';
import {MainRouteProps} from '../../routes/main';
import {GlobalContext} from '../../shared/GlobalContext';
import {useTranslation} from 'react-i18next';
export function useProfileScreen({navigation}: MainRouteProps) {
const {appService} = useContext(GlobalContext);
const authService = appService.children.get('auth');
const settingsService = appService.children.get('settings');
const [alertMsg, setHasAlertMsg] = useState('');
const authBiometrics = useSelector(authService, selectBiometrics);
const [biometricState, biometricSend, bioService] =
useMachine(biometricsMachine);
const isSuccessBio: boolean = useSelector(bioService, selectIsSuccess);
const errorMsgBio: string = useSelector(bioService, selectError);
const unEnrolledNoticeBio: string = useSelector(
bioService,
selectUnenrolledNotice,
);
const {t} = useTranslation('AuthScreen');
useEffect(() => {
setTimeout(async () => {
const hasEnrolledBiometrics = await LocalAuthentication.isEnrolledAsync();
if (!hasEnrolledBiometrics) {
authService.send(AuthEvents.SETUP_BIOMETRICS(''));
settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(false));
}
}, 0);
// if biometic state is success then lets send auth service BIOMETRICS
if (isSuccessBio) {
authService.send(AuthEvents.SETUP_BIOMETRICS('true'));
settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(true));
// handle biometric failure unknown error
} else {
const error: string = errorMsgBio ?? unEnrolledNoticeBio ?? '';
if (error != '') {
setHasAlertMsg(t(error));
}
}
}, [isSuccessBio, errorMsgBio, unEnrolledNoticeBio]);
const useBiometrics = (value: boolean) => {
if (value) {
// But check if we already enrolled biometrics
if (authBiometrics) {
authService.send(AuthEvents.SETUP_BIOMETRICS('true'));
settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(true));
// but if device does not have any enrolled biometrics
} else if (biometricState.matches({failure: 'unenrolled'})) {
biometricSend({type: 'RETRY_AUTHENTICATE'});
// otherwise lets do a biometric auth
} else {
biometricSend({type: 'AUTHENTICATE'});
}
} else {
authService.send(AuthEvents.SETUP_BIOMETRICS(''));
settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(false));
}
};
const hideAlert = () => {
setHasAlertMsg('');
};
return {
alertMsg,
hideAlert,
backendInfo: useSelector(appService, selectBackendInfo),
name: useSelector(settingsService, selectName),
vcLabel: useSelector(settingsService, selectVcLabel),
credentialRegistry: useSelector(settingsService, selectCredentialRegistry),
credentialRegistryResponse: useSelector(
settingsService,
selectCredentialRegistryResponse,
),
isBiometricUnlockEnabled: useSelector(
settingsService,
selectBiometricUnlockEnabled,
),
canUseBiometrics: useSelector(authService, selectCanUseBiometrics),
useBiometrics,
UPDATE_NAME: names =>
settingsService.send(SettingsEvents.UPDATE_NAME(names[0].value)),
UPDATE_VC_LABEL: labels =>
settingsService.send(SettingsEvents.UPDATE_VC_LABEL(labels[0].value)),
UPDATE_CREDENTIAL_REGISTRY: items =>
settingsService.send(SettingsEvents.UPDATE_MIMOTO_HOST(items[0].value)),
UPDATE_CREDENTIAL_REGISTRY_RESPONSE: (credentialRegistryResponse: string) =>
settingsService.send(
SettingsEvents.UPDATE_CREDENTIAL_REGISTRY_RESPONSE(
credentialRegistryResponse,
),
),
TOGGLE_BIOMETRIC: (enable: boolean) =>
settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(enable)),
LOGOUT: () => {
authService.send(AuthEvents.LOGOUT());
navigation.navigate('Welcome');
},
};
}

View File

@@ -57,7 +57,7 @@ export const QrConsent: React.FC<QrConsentProps> = props => {
{controller.essentialClaims.map((claim, index) => (
<Row key={index} align={'space-between'} margin={'10 0 0 20'}>
<Text
color={Theme.Colors.profileLabel}
color={Theme.Colors.Details}
style={Theme.TextStyles.base}>
{t(claim[0].toUpperCase() + claim.slice(1))
.split('_')
@@ -91,7 +91,7 @@ export const QrConsent: React.FC<QrConsentProps> = props => {
containerStyle={Theme.claimsContainer.container}>
<ListItem.Content>
<ListItem.Title>
<Text color={Theme.Colors.profileLabel}>
<Text color={Theme.Colors.Details}>
{t(claim[0].toUpperCase() + claim.slice(1))
.split('_')
.join(' ')}

View File

@@ -1,14 +0,0 @@
{
"header": "Card details",
"save": "Save Card",
"verifyAndSave": "Verify and save",
"reject": "Reject",
"discard": "Discard",
"goToReceivedVCTab": "View Received Cards",
"errors": {
"savingFailed": {
"title": "Failed to save the Card",
"message": "Something went wrong while saving Card to the store."
}
}
}

View File

@@ -1,52 +0,0 @@
{
"bluetoothDenied": "Please enable Bluetooth to be able to request Card",
"bluetoothStateIos": "Bluetooth is turned OFF, please turn it ON from Control center",
"bluetoothStateAndroid": "Bluetooth is turned OFF, please turn it ON from Quick settings menu",
"nearbyDevicesPermissionDenied": "Please enable Nearby Devices Permission to be able to request card",
"showQrCode": "Display this QR code to request resident Card",
"incomingVc": "Incoming Card",
"request": "Request",
"errors": {
"nearbyDevicesPermissionDenied": {
"message": "Nearby Devices permission is required to be able to request Card",
"button": "Allow Permission"
},
"storageLimitReached": {
"title": "Insufficient Appdata",
"message": "You cannot add or receive cards since the Appdata is full"
}
},
"status": {
"accepted": {
"title": "Success!",
"message": "Card has been successfully received from Wallet"
},
"rejected": {
"title": "Notice",
"message": "You discarded Wallet's Card"
},
"disconnected": {
"title": "Disconnected",
"message": "The connection was interrupted. Please try again."
},
"waitingConnection": "Waiting for connection...",
"exchangingDeviceInfo": {
"message": "Exchanging device info...",
"timeoutHint": "It's taking too long to exchange device info..."
},
"connected": {
"message": "Connected to the device. Waiting for Card...",
"timeoutHint": "No data received yet. Is sending device still connected?"
},
"offline": {
"message": "Please connect to the internet to enable Online sharing mode"
},
"bleError": {
"title": "Failed to transfer",
"message": "Something went wrong while transferring Card. Please try again."
}
},
"online": "Online",
"offline": "Offline",
"gotoSettings": "Go to settings"
}

View File

@@ -17,6 +17,7 @@ import {
import {MainBottomTabParamList} from '../../routes/main';
import {BOTTOM_TAB_ROUTES} from '../../routes/routesConstants';
import {ProgressingModal} from '../../components/ProgressingModal';
import {isIOS} from '../../shared/constants';
type RequestStackParamList = {
RequestScreen: undefined;
@@ -106,9 +107,7 @@ const BluetoothPrompt: React.FC<RequestScreenProps> = ({t}) => {
return (
<Centered fill>
<Text color={Theme.Colors.errorMessage} align="center" margin="0 10">
{t(
Platform.OS === 'ios' ? 'bluetoothStateIos' : 'bluetoothStateAndroid',
)}
{t(isIOS() ? 'bluetoothStateIos' : 'bluetoothStateAndroid')}
</Text>
</Centered>
);

View File

@@ -1,48 +0,0 @@
{
"header": "Scan QR Code",
"noShareableVcs": "No shareable Cards are available.",
"sharingVc": "Sharing Card",
"BluetoothStateIos": "Bluetooth is turned OFF, please turn it ON from Control center",
"BluetoothStateAndroid": "Bluetooth is turned OFF, please turn it ON from Quick settings menu",
"errors": {
"locationDisabled": {
"message": "Location services must be enabled for the scanning functionality",
"button": "Enable location services"
},
"locationDenied": {
"message": "Location permission is required for the scanning functionality",
"button": "Allow access to location"
},
"storageLimitReached": {
"title": "Insufficient Appdata",
"message": "You cannot share cards since the Appdata is full. Clear Appdata to proceed."
}
},
"status": {
"connecting": "Connecting...",
"connectingTimeout": "It's taking a while to establish the connection. Is the other device open for connections?",
"exchangingDeviceInfo": "Exchanging device info...",
"exchangingDeviceInfoTimeout": "It's taking a while to exchange device info. You may have to reconnect.",
"invalid": "Invalid QR Code",
"offline": "Please connect to the internet to scan QR codes using Online sharing mode",
"sent": "{{ vcLabel }} has been sent...",
"sentHint": "Waiting for receiver to save or discard your {{ vcLabel }}",
"sharing": {
"title": "Sharing...",
"hint": "Please wait for the receiving device to accept or reject the share.",
"timeoutHint": "It's taking longer than expected to share. There could be a problem with the connection."
},
"accepted": {
"title": "Success!",
"message": "Your Card has been successfully shared with Verifier"
},
"rejected": {
"title": "Notice",
"message": "Your Card was discarded by Verifier"
},
"bleError": {
"title": "Failed to transfer",
"message": "Something went wrong while transferring Card. Please try again."
}
}
}

View File

@@ -14,6 +14,7 @@ import {Linking, Platform} from 'react-native';
import {useNavigation, NavigationProp} from '@react-navigation/native';
import {MainBottomTabParamList} from '../../routes/main';
import {BOTTOM_TAB_ROUTES} from '../../routes/routesConstants';
import {isIOS} from '../../shared/constants';
export const ScanScreen: React.FC = () => {
type ScanScreenNavigation = NavigationProp<MainBottomTabParamList>;
@@ -56,9 +57,7 @@ export const ScanScreen: React.FC = () => {
function bluetoothIsOffText() {
return (
<Text align="center" color={Theme.Colors.errorMessage} margin="0 10">
{t(
Platform.OS === 'ios' ? 'bluetoothStateIos' : 'bluetoothStateAndroid',
)}
{t(isIOS() ? 'bluetoothStateIos' : 'bluetoothStateAndroid')}
</Text>
);
}

View File

@@ -1,6 +0,0 @@
{
"header": "Share Card",
"chooseVc": "Choose the Card you'd like to share with",
"share": "Share",
"verifyAndShare": "Verify Identity & Share"
}

View File

@@ -1,7 +0,0 @@
{
"reasonForSharing": "Reason for sharing (optional)",
"acceptRequest": "Share",
"acceptRequestAndVerify": "Accept request and verify",
"reject": "Reject",
"consentToPhotoVerification": "I give consent to have my photo taken for authentication"
}

View File

@@ -40,7 +40,7 @@ export const AboutInji: React.FC<AboutInjiProps> = ({appId}) => {
/>
<ListItem.Content>
<ListItem.Title>
<Text weight="semibold" color={Theme.Colors.profileLabel}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('aboutInji')}
</Text>
</ListItem.Title>

View File

@@ -1,5 +0,0 @@
{
"header": "About Inji",
"version": "Version",
"useBle": "Powered by BLE"
}

View File

@@ -1,99 +0,0 @@
import React, {useState} from 'react';
import Markdown from 'react-native-simple-markdown';
import {useTranslation} from 'react-i18next';
import {I18nManager, SafeAreaView, View} from 'react-native';
import {Divider, Icon, ListItem, Overlay} from 'react-native-elements';
import {Button, Text, Row} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils';
import appMetaData from '../../AppMetaData.md';
import {__InjiVersion, __TuvaliVersion} from '../../shared/GlobalVariables';
export const AppMetaData: React.FC<AppMetaDataProps> = props => {
const {t} = useTranslation('AppMetaData');
const [isViewing, setIsViewing] = useState(false);
const markdownStyles = {
text: {
fontSize: 18,
},
view: {
flex: 1,
},
};
return (
<ListItem bottomDivider onPress={() => setIsViewing(true)}>
<Icon
name="filetext1"
type="antdesign"
size={20}
style={Theme.Styles.profileIconBg}
color={Theme.Colors.Icon}
/>
<ListItem.Content>
<ListItem.Title>
<Text color={props.color}>{props.label}</Text>
</ListItem.Title>
</ListItem.Content>
<Overlay
overlayStyle={{padding: 24}}
isVisible={isViewing}
onBackdropPress={() => setIsViewing(false)}>
<SafeAreaView>
<View style={Theme.AppMetaDataStyles.view}>
<Row align="center" crossAlign="center" margin="0 0 10 0">
<View style={Theme.AppMetaDataStyles.buttonContainer}>
<Button
type="clear"
icon={
<Icon
name={
I18nManager.isRTL ? 'chevron-right' : 'chevron-left'
}
color={Theme.Colors.Icon}
/>
}
title=""
onPress={() => setIsViewing(false)}
/>
</View>
<Text style={Theme.AppMetaDataStyles.header}>
{t('header').toUpperCase()}
</Text>
</Row>
<Divider />
<View style={Theme.AppMetaDataStyles.contentView}>
<Markdown styles={markdownStyles}>{appMetaData}</Markdown>
<View style={Theme.FooterStyles.bottom}>
<Text
weight="semibold"
margin="5 0 0 0"
align="center"
size="small"
color={Theme.Colors.version}>
{t('version')}: {__InjiVersion.getValue()}
</Text>
{__TuvaliVersion.getpackageVersion() != 'unknown' && (
<Text
weight="semibold"
margin="32 0 5 0"
align="center"
size="small"
color={Theme.Colors.version}>
{t('Tuvali-version')}: {__TuvaliVersion.getValue()}
</Text>
)}
</View>
</View>
</View>
</SafeAreaView>
</Overlay>
</ListItem>
);
};
interface AppMetaDataProps {
label: string;
color?: string;
}

View File

@@ -1,4 +0,0 @@
{
"header": "Credits and legal notices",
"back": "Back"
}

View File

@@ -1,101 +0,0 @@
import React, { useState } from 'react';
import Markdown from 'react-native-simple-markdown';
import { useTranslation } from 'react-i18next';
import { Image, SafeAreaView, View } from 'react-native';
import { Divider, Icon, ListItem, Overlay } from 'react-native-elements';
import { Button, Text, Row, Column } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import creditsContent from '../../Credits.md';
export const Credits: React.FC<CreditsProps> = (props) => {
const { t } = useTranslation('Credits');
const [isViewing, setIsViewing] = useState(false);
const images = {
'docs/images/newlogic_logo.png': require('../../docs/images/newlogic_logo.png'),
'docs/images/id_pass_logo.png': require('../../docs/images/id_pass_logo.png'),
};
const markdownStyles = {
heading1: {
fontSize: 24,
textAlign: 'left',
},
heading2: {
fontSize: 24,
textAlign: 'left',
},
image: {
maxWidth: 150,
margin: 0,
},
};
const rules = {
image: {
react: (node, output, state) => (
<View key={`image-${state.key}`}>
<Image
style={{ maxWidth: 150, height: 100 }}
source={images[node.target]}
resizeMode="contain"
/>
</View>
),
},
};
return (
<ListItem bottomDivider onPress={() => setIsViewing(true)}>
<Icon
name="filetext1"
type="antdesign"
size={22}
color={Theme.Colors.Icon}
/>
<ListItem.Content>
<ListItem.Title>
<Text weight="semibold" color={props.color}>
{props.label}
</Text>
</ListItem.Title>
</ListItem.Content>
<Icon
name="chevron-right"
size={21}
color={Theme.Colors.profileLanguageValue}
/>
<Overlay
overlayStyle={{ padding: 24 }}
isVisible={isViewing}
onBackdropPress={() => setIsViewing(false)}>
<SafeAreaView>
<View style={Theme.CreditsStyles.view}>
<Row align="center" crossAlign="center" margin="0 0 10 0">
<View style={Theme.CreditsStyles.buttonContainer}>
<Button
type="clear"
icon={<Icon name="chevron-left" color={Theme.Colors.Icon} />}
title=""
onPress={() => setIsViewing(false)}
/>
</View>
<Text size="small">{t('header')}</Text>
</Row>
<Divider />
<View style={Theme.CreditsStyles.markdownView}>
<Markdown rules={rules} styles={markdownStyles}>
{creditsContent}
</Markdown>
</View>
</View>
</SafeAreaView>
</Overlay>
</ListItem>
);
};
interface CreditsProps {
label: string;
color?: string;
}

View File

@@ -1,15 +0,0 @@
{
"name": "Name",
"vcLabel": "VC Label",
"language": "Language",
"bioUnlock": "Unlock with biometrics",
"authFactorUnlock": "Unlock auth factor",
"AppMetaData": "About Inji",
"logout": "Log-out",
"revokeLabel": "Revoke VID",
"revokeHeader": "REVOKE VID",
"revokingVids": "You are about to revoke ({{count}}) VIDs.",
"revokingVidsAfter": "This means you will no longer be able to use or view any of the IDs linked to those VID(s). \nAre you sure you want to proceed?",
"empty": "Empty",
"revokeSuccessful": "VID successfully revoked"
}

View File

@@ -33,13 +33,15 @@ const LanguageSetting: React.FC = () => {
/>
<ListItem.Content>
<ListItem.Title>
<Text weight="semibold">{t('language')}</Text>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('language')}
</Text>
</ListItem.Title>
</ListItem.Content>
<Icon
name="chevron-right"
size={21}
color={Theme.Colors.profileLanguageValue}
color={Theme.Colors.chevronRightColor}
style={{marginRight: 15}}
/>
</ListItem>
@@ -130,7 +132,7 @@ export const SettingScreen: React.FC<
/>
<ListItem.Content>
<ListItem.Title>
<Text weight="semibold" color={Theme.Colors.profileLabel}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('bioUnlock')}
</Text>
</ListItem.Title>
@@ -171,6 +173,7 @@ export const SettingScreen: React.FC<
Icon="star"
errorMessage={t('errorMessage')}
progress={controller.isResetInjiProps}
titleColor={Theme.Colors.settingsLabel}
/>
)}
@@ -188,7 +191,7 @@ export const SettingScreen: React.FC<
/>
<ListItem.Content>
<ListItem.Title>
<Text weight="semibold" color={Theme.Colors.profileLabel}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('injiTourGuide')}
</Text>
</ListItem.Title>
@@ -205,32 +208,12 @@ export const SettingScreen: React.FC<
/>
<ListItem.Content>
<ListItem.Title>
<Text weight="semibold" color={Theme.Colors.profileLabel}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('logout')}
</Text>
</ListItem.Title>
</ListItem.Content>
</ListItem>
{controller.backendInfo.application.name !== '' ? (
<View>
<Text
weight="semibold"
align="center"
size="smaller"
color={Theme.Colors.profileValue}>
{controller.backendInfo.application.name}:{' '}
{controller.backendInfo.application.version}
</Text>
<Text
weight="semibold"
align="center"
size="smaller"
color={Theme.Colors.profileValue}>
MOSIP: {controller.backendInfo.config['mosip.host']}
</Text>
</View>
) : null}
</Column>
</ScrollView>
</Modal>

View File

@@ -1,7 +1,6 @@
import {useMachine, useSelector} from '@xstate/react';
import {useContext, useEffect, useState} from 'react';
import * as LocalAuthentication from 'expo-local-authentication';
import {selectBackendInfo} from '../../machines/app';
import {
AuthEvents,
selectBiometrics,
@@ -30,6 +29,7 @@ import {useTranslation} from 'react-i18next';
import {Platform} from 'react-native';
import {RequestRouteProps, RootRouteProps} from '../../routes';
import {REQUEST_ROUTES} from '../../routes/routesConstants';
import {isIOS} from '../../shared/constants';
export function useSettingsScreen(props: RootRouteProps & RequestRouteProps) {
const {appService} = useContext(GlobalContext);
@@ -104,7 +104,6 @@ export function useSettingsScreen(props: RootRouteProps & RequestRouteProps) {
alertMsg,
hideAlert,
appId: useSelector(settingsService, selectAppId),
backendInfo: useSelector(appService, selectBackendInfo),
name: useSelector(settingsService, selectName),
vcLabel: useSelector(settingsService, selectVcLabel),
credentialRegistry: useSelector(settingsService, selectCredentialRegistry),
@@ -166,7 +165,7 @@ export function useSettingsScreen(props: RootRouteProps & RequestRouteProps) {
authService.send(AuthEvents.LOGOUT());
};
if (Platform.OS === 'ios') {
if (isIOS()) {
setTimeout(() => navigate(), 0);
} else {
navigate();

View File

@@ -1,12 +0,0 @@
{
"status": {
"verifyingIdentity": "Verifying identity..."
},
"errors": {
"invalidIdentity": {
"title": "Unable to verify identity",
"message": "Face not recognised. Please try again.",
"messageNoRetry": "Face not recognised."
}
}
}

View File

@@ -1,5 +0,0 @@
{
"title": "Open Source Identity Solution",
"getStarted": "Get started",
"unlockApp": "Unlock application"
}

View File

@@ -30,13 +30,7 @@ export function useWelcomeScreen(props: RootRouteProps) {
const isSettingUp = useSelector(authService, selectSettingUp);
const passcode = useSelector(authService, selectPasscode);
const isPasscodeSet = () => {
if (passcode) {
return false;
} else {
return true;
}
};
const isPasscodeSet = () => !!passcode;
const biometrics = useSelector(authService, selectBiometrics);
const isLanguagesetup = useSelector(authService, selectLanguagesetup);

View File

@@ -1,13 +0,0 @@
const fs = require('fs');
const glob = require('glob');
glob('**/*.strings.json', (_err, paths) => {
const strings = {};
paths.forEach((path) => {
const key = path.match(/(?<ns>[^/]+)\.strings\.json$/).groups.ns;
strings[key] = JSON.parse(fs.readFileSync(path));
});
fs.writeFileSync(`locales/en.json`, JSON.stringify(strings, null, 2));
});

View File

@@ -1,13 +0,0 @@
{
"cancel": "Cancel",
"save": "Save",
"dismiss": "Dismiss",
"editLabel": "Edit {{label}}",
"tryAgain": "Try again",
"camera": {
"errors": {
"missingPermission": "This app uses the camera to scan the QR code of another device."
},
"allowAccess": "Allow access to the camera"
}
}

View File

@@ -1,5 +1,8 @@
import {Platform} from 'react-native';
import argon2 from 'react-native-argon2';
import {AnyState} from 'xstate';
import {getDeviceNameSync} from 'react-native-device-info';
import {isAndroid} from './constants';
export const hashData = async (
data: string,
@@ -19,7 +22,7 @@ export interface Argon2iConfig {
}
export default function testIDProps(id) {
return Platform.OS === 'android'
return isAndroid()
? {accessible: true, accessibilityLabel: id}
: {testID: id};
}
@@ -27,3 +30,25 @@ export default function testIDProps(id) {
export const removeWhiteSpace = (str: string) => {
return str ? str.replace(/\s/g, '') : str;
};
export function logState(state: AnyState) {
const data = JSON.stringify(
state.event,
(key, value) => {
if (key === 'type') return undefined;
if (typeof value === 'string' && value.length >= 100) {
return value.slice(0, 100) + '...';
}
return value;
},
2,
);
console.log(
`[${getDeviceNameSync()}] ${state.machine.id}: ${
state.event.type
} -> ${state.toStrings().pop()}\n${
data.length > 300 ? data.slice(0, 300) + '...' : data
}
`,
);
}

View File

@@ -50,6 +50,10 @@ export function isIOS(): boolean {
return Platform.OS === 'ios';
}
export function isAndroid(): boolean {
return Platform.OS === 'android';
}
// Configuration for argon2i hashing algorithm
export const argon2iConfig: Argon2iConfig = {
iterations: 5,

View File

@@ -3,11 +3,7 @@ import jwtDecode from 'jwt-decode';
import jose from 'node-jose';
import {isIOS} from '../constants';
import pem2jwk from 'simple-pem2jwk';
import {
displayType,
Issuers_Key_Ref,
issuerType,
} from '../../machines/issuersMachine';
import {displayType, issuerType} from '../../machines/issuersMachine';
import getAllConfigurations from '../commonprops/commonProps';
import {CredentialWrapper} from '../../types/VC/EsignetMosipVC/vc';
import {VCMetadata} from '../VCMetadata';
@@ -18,6 +14,8 @@ export const Protocols = {
OTP: 'OTP',
};
export const Issuers_Key_Ref = 'OpenId4VCI_KeyPair';
export const getIdentifier = (context, credential) => {
const credId = credential.credential.id.split('/');
return (

View File

@@ -15,7 +15,7 @@ import {
} from './cryptoutil/cryptoUtil';
import {VCMetadata} from './VCMetadata';
import {ENOENT, getItem} from '../machines/store';
import {MY_VCS_STORE_KEY, RECEIVED_VCS_STORE_KEY} from './constants';
import {isAndroid, MY_VCS_STORE_KEY, RECEIVED_VCS_STORE_KEY} from './constants';
import FileStorage, {getFilePath, vcDirectoryPath} from './fileStorage';
export const MMKV = new MMKVLoader().initialize();
@@ -197,7 +197,7 @@ class Storage {
const minimumStorageLimitInBytes = configurations[limitInMB] * 1000 * 1000;
const freeDiskStorageInBytes =
Platform.OS === 'android' && Platform.Version < 29
isAndroid() && Platform.Version < 29
? getFreeDiskStorageOldSync()
: getFreeDiskStorageSync();