mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-09 13:38:01 -05:00
Merge remote-tracking branch 'upstream/develop' into inji-505-release
Co-authored-by: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com> Signed-off-by: Kiruthika Jeyashankar <81218987+KiruthikaJeyashankar@users.noreply .github.com>
This commit is contained in:
5
.env
5
.env
@@ -6,8 +6,6 @@ MIMOTO_HOST=https://api.qa-inji.mosip.net
|
||||
|
||||
ESIGNET_HOST=https://api.qa-inji.mosip.net
|
||||
|
||||
GOOGLE_NEARBY_MESSAGES_API_KEY=
|
||||
|
||||
OBSRV_HOST = https://dataset-api.obsrv.mosip.net
|
||||
|
||||
#Application Theme can be ( orange | purple )
|
||||
@@ -19,6 +17,3 @@ DEBUG_MODE=false
|
||||
|
||||
#supported languages( en, fil, ar, hi, kn, ta)
|
||||
APPLICATION_LANGUAGE=en
|
||||
|
||||
#Toggle for openID for VC
|
||||
ENABLE_OPENID_FOR_VC=true
|
||||
|
||||
7
.github/workflows/android-beta-build.yml
vendored
7
.github/workflows/android-beta-build.yml
vendored
@@ -104,13 +104,6 @@ jobs:
|
||||
gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
|
||||
gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
|
||||
|
||||
- name: Setup Firebase
|
||||
run: |
|
||||
cd android
|
||||
if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];then rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;fi
|
||||
env:
|
||||
FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
|
||||
|
||||
- name: Generate keystore
|
||||
run: |
|
||||
echo "$ANDROID_KEYSTORE_FILE" > release.keystore.b64
|
||||
|
||||
14
.github/workflows/android-build-verify.yml
vendored
14
.github/workflows/android-build-verify.yml
vendored
@@ -109,20 +109,6 @@ jobs:
|
||||
gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
|
||||
gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
|
||||
|
||||
- name: Setup Firebase
|
||||
run: |
|
||||
cd android
|
||||
|
||||
if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];
|
||||
then
|
||||
rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;
|
||||
else
|
||||
echo "Using Dummy Google Service JSON for firebase"
|
||||
echo "$DUMMY_GOOGLE_SERVICE_JSON" > app/google-services.json
|
||||
fi
|
||||
env:
|
||||
FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
|
||||
|
||||
- name: Generate keystore
|
||||
run: |
|
||||
keytool \
|
||||
|
||||
14
.github/workflows/android-internal-build.yml
vendored
14
.github/workflows/android-internal-build.yml
vendored
@@ -92,13 +92,6 @@ jobs:
|
||||
gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
|
||||
gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
|
||||
|
||||
- name: Setup Firebase
|
||||
run: |
|
||||
cd android
|
||||
if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];then rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;fi
|
||||
env:
|
||||
FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
|
||||
|
||||
- name: Generate keystore
|
||||
run: |
|
||||
echo "$ANDROID_KEYSTORE_FILE" > release.keystore.b64
|
||||
@@ -182,13 +175,6 @@ jobs:
|
||||
gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
|
||||
gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
|
||||
|
||||
- name: Setup Firebase
|
||||
run: |
|
||||
cd android
|
||||
if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];then rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;fi
|
||||
env:
|
||||
FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
|
||||
|
||||
- name: Generate keystore
|
||||
run: |
|
||||
echo "$ANDROID_KEYSTORE_FILE" > release.keystore.b64
|
||||
|
||||
3
.github/workflows/ios-build.yml
vendored
3
.github/workflows/ios-build.yml
vendored
@@ -88,6 +88,9 @@ jobs:
|
||||
SLACK_URL: '${{ secrets.SLACK_WEBHOOK_DEVOPS }}'
|
||||
MATCH_PASSWORD: '${{ secrets.INJI_IOS_MATCH_PASSWORD }}'
|
||||
APPLICATION_THEME: ${{ github.event.inputs.theme }}
|
||||
CREDENTIAL_REGISTRY_EDIT: ${{ github.event.inputs.registry_edit }}
|
||||
MIMOTO_HOST: ${{ github.event.inputs.mimotoBackendServiceUrl }}
|
||||
ESIGNET_HOST: ${{ github.event.inputs.esignetBackendServiceUrl }}
|
||||
TESTFLIGHT_INTERNAL_TESTERS_GROUP: ${{ github.event.inputs.internal-testers }}
|
||||
TESTFLIGHT_BETA_APP_DESCRIPTION: ${{ github.event.inputs.buildDescription }}
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
.git/hooks/bin/talisman ${DEBUG_OPTS} --githook pre-commit
|
||||
59
.talismanrc
Normal file
59
.talismanrc
Normal file
@@ -0,0 +1,59 @@
|
||||
fileignoreconfig:
|
||||
- filename: package.json
|
||||
checksum: e0b34f1a1efbdf07b40a3e9e9ecd8884dd7d6835f45c57850e30988d2c6371a2
|
||||
- filename: package-lock.json
|
||||
checksum: fc26d97edecbacd0b7507032c6fc1acfcea9f01f5dbe66a2a0341506e2f0daca
|
||||
- filename: components/PasscodeVerify.tsx
|
||||
checksum: 14654c0f038979fcd0d260170a45894a072f81e0767ca9a0e66935d33b5cc703
|
||||
- filename: i18n.ts
|
||||
checksum: 75dd5536038ba198aa7b12eb6d2c2e7042c9ce292e5a0d5c90883ae5b2312b1e
|
||||
- filename: screens/BiometricScreenController.ts
|
||||
checksum: b3d0184fb894f4a9ffa1a4d277d2975495dbc47771593895bf1999deabafeb94
|
||||
- filename: screens/Home/MyVcs/IdInputModal.tsx
|
||||
checksum: ec48ebeaf46b8fbc756f19ef8ffe8901ce0528aef164f3c7ffdeec36fb53ffc6
|
||||
- filename: components/Passcode.tsx
|
||||
checksum: db4a18001be8c63bf7ffb389359861401fa1d22261b10ad729a76fd431c019a7
|
||||
- filename: screens/PasscodeScreen.tsx
|
||||
checksum: 0cc5b91350e491a058ee8a1878a496c16b65f14969e989bdb1c354f6e9b8c03c
|
||||
- filename: locales/spa.json
|
||||
checksum: 981103ff872d6f54610468c7ead65873d9294a11092649b105c552f770f0214b
|
||||
- filename: screens/AuthScreen.tsx
|
||||
checksum: 2c1183b2ad8ec27adf8f389a2511805493f229fdda674064e2579d2032119d1c
|
||||
- filename: screens/BiometricScreen.tsx
|
||||
checksum: 7a730731aaa7540eec9d05d73de277a665dc06425666280842e0f9ba6e5b8514
|
||||
- filename: screens/AuthScreenController.ts
|
||||
checksum: 18af825821bc95e1056050623b804a5a8e7435b9e3383916a5d63024eeba9553
|
||||
- filename: screens/WelcomeScreenController.ts
|
||||
checksum: 71917c8c543a4a5b7ab61df259b785d233a80718123b0c8edf6ec81e1b3a81e0
|
||||
- filename: shared/telemetry/TelemetryUtils.js
|
||||
checksum: 9a61cd59a3718adf1f14faf3024fec66a3295ef373878a878a28e5cb1287afaa
|
||||
- filename: ios/Podfile.lock
|
||||
checksum: cc123c3e1f04d41b394ceb16843b15c08bac3ba619ae853ff322717739761a85
|
||||
- filename: ios/Podfile.lock
|
||||
checksum: cc123c3e1f04d41b394ceb16843b15c08bac3ba619ae853ff322717739761a85
|
||||
- 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
|
||||
- filename: machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine.ts
|
||||
checksum: 237a2640b7db70770d65da67c79f2929581e32f1162517e50b8d37e409f3387d
|
||||
- filename: shared/cryptoutil/cryptoUtil.ts
|
||||
checksum: b785ff3f01ab9530119072c4d38195048bfeee6155c54ea7dd031559acb722f3
|
||||
- filename: package.json
|
||||
checksum: 1a9d02d94424c1266503d58038cae2318ab71261ab50cf930c5f98e07c0f3ccd
|
||||
- filename: machines/store.typegen.ts
|
||||
checksum: 6d22bc5c77398316b943c512c208ce0846a9fff674c1ccac79e07f21962acd5f
|
||||
- filename: machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine.typegen.ts
|
||||
checksum: 10889302ca05646a283386be1bbe7a5fb510c02bb62a308ee45f3c2a872ae64e
|
||||
16
App.tsx
16
App.tsx
@@ -15,15 +15,10 @@ import {
|
||||
import {DualMessageOverlay} from './components/DualMessageOverlay';
|
||||
import {useApp} from './screens/AppController';
|
||||
import {Alert} from 'react-native';
|
||||
import {
|
||||
getAppInfoData,
|
||||
getTelemetryConfigData,
|
||||
initializeTelemetry,
|
||||
sendAppInfoEvent,
|
||||
} from './shared/telemetry/TelemetryUtils';
|
||||
import {configureTelemetry} from './shared/telemetry/TelemetryUtils';
|
||||
import {MessageOverlay} from './components/MessageOverlay';
|
||||
import SecureKeystore from 'react-native-secure-keystore';
|
||||
import {isCustomSecureKeystore} from './shared/cryptoutil/cryptoUtil';
|
||||
import {isHardwareKeystoreExists} from './shared/cryptoutil/cryptoUtil';
|
||||
import i18n from './i18n';
|
||||
import './shared/flipperConfig';
|
||||
|
||||
@@ -42,11 +37,6 @@ const DecryptErrorAlert = (controller, t) => {
|
||||
},
|
||||
]);
|
||||
};
|
||||
function configureTelemetry() {
|
||||
const config = getTelemetryConfigData();
|
||||
initializeTelemetry(config);
|
||||
sendAppInfoEvent(getAppInfoData());
|
||||
}
|
||||
|
||||
const AppLayoutWrapper: React.FC = () => {
|
||||
const {appService} = useContext(GlobalContext);
|
||||
@@ -101,7 +91,7 @@ const AppInitialization: React.FC = () => {
|
||||
const {t} = useTranslation('common');
|
||||
|
||||
useEffect(() => {
|
||||
if (isCustomSecureKeystore()) {
|
||||
if (isHardwareKeystoreExists) {
|
||||
SecureKeystore.updatePopup(
|
||||
t('biometricPopup.title'),
|
||||
t('biometricPopup.description'),
|
||||
|
||||
@@ -52,15 +52,10 @@ Create a `.env.local` file using `.env` as your template:
|
||||
|
||||
```
|
||||
MIMOTO_HOST=
|
||||
GOOGLE_NEARBY_MESSAGES_API_KEY=
|
||||
```
|
||||
|
||||
And `android/local.properties`:
|
||||
|
||||
```
|
||||
GOOGLE_NEARBY_MESSAGES_API_KEY=
|
||||
```
|
||||
|
||||
More info here: [Setup Google Nearby Messages in React](https://github.com/mrousavy/react-native-google-nearby-messages#usage)
|
||||
|
||||
### Android
|
||||
|
||||
@@ -3,8 +3,6 @@ plugins {
|
||||
}
|
||||
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
apply plugin: "com.facebook.react"
|
||||
|
||||
import com.android.build.OutputFile
|
||||
@@ -121,7 +119,6 @@ android {
|
||||
|
||||
manifestPlaceholders = [
|
||||
APP_NAME: APP_NAME_RELEASE,
|
||||
GOOGLE_NEARBY_MESSAGES_API_KEY: "${properties.getProperty('GOOGLE_NEARBY_MESSAGES_API_KEY')}",
|
||||
appAuthRedirectScheme: 'io.mosip.residentapp.inji'
|
||||
]
|
||||
}
|
||||
@@ -219,6 +216,7 @@ dependencies {
|
||||
if (isGifEnabled || isWebpEnabled) {
|
||||
implementation 'com.facebook.fresco:fresco:2.0.0'
|
||||
implementation 'com.facebook.fresco:imagepipeline-okhttp3:2.0.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.4.1'
|
||||
}
|
||||
|
||||
if (isGifEnabled) {
|
||||
@@ -250,20 +248,8 @@ dependencies {
|
||||
} else {
|
||||
implementation jscFlavor
|
||||
}
|
||||
// Firebase
|
||||
implementation 'com.google.firebase:firebase-crashlytics:17.3.1'
|
||||
implementation 'com.google.firebase:firebase-analytics:18.0.2'
|
||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||
}
|
||||
|
||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||
apply from: "./eas-build.gradle"
|
||||
|
||||
try {
|
||||
def servicesJSON = file('google-services.json')
|
||||
if (servicesJSON.text) {
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.warn("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
|
||||
}
|
||||
apply from: "./eas-build.gradle"
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "259470317171",
|
||||
"project_id": "mosip-resident-app",
|
||||
"storage_bucket": "mosip-resident-app.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "",
|
||||
"android_client_info": {
|
||||
"package_name": "io.mosip.residentapp"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": ""
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -21,8 +21,6 @@ import com.facebook.soloader.SoLoader;
|
||||
import timber.log.Timber;
|
||||
|
||||
import com.facebook.react.bridge.JSIModulePackage;
|
||||
import com.google.firebase.analytics.FirebaseAnalytics;
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
@@ -77,36 +75,9 @@ public class MainApplication extends Application implements ReactApplication {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(new Timber.DebugTree());
|
||||
}
|
||||
// Setup Firebase
|
||||
FirebaseAnalytics.getInstance(this);
|
||||
Timber.plant(new CrashReportingTree());
|
||||
ApplicationLifecycleDispatcher.onApplicationCreate(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A tree which logs important information for crash reporting.
|
||||
*/
|
||||
private static class CrashReportingTree extends Timber.Tree {
|
||||
FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
|
||||
@Override
|
||||
protected void log(int priority, String tag, @NonNull String message, Throwable t) {
|
||||
if (priority == Log.VERBOSE || priority == Log.DEBUG) {
|
||||
return;
|
||||
}
|
||||
|
||||
crashlytics.setCustomKey("priority", priority);
|
||||
crashlytics.setCustomKey("tag", tag);
|
||||
crashlytics.log(message);
|
||||
|
||||
if (t != null) {
|
||||
if (priority == Log.ERROR) {
|
||||
crashlytics.recordException(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
@@ -17,8 +17,6 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:7.3.1")
|
||||
classpath 'com.google.gms:google-services:4.3.5'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
|
||||
classpath("com.facebook.react:react-native-gradle-plugin")
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 214 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -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"
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Pressable } from 'react-native';
|
||||
import { Theme } from './ui/styleUtils';
|
||||
import React, {useState} from 'react';
|
||||
import {Pressable} from 'react-native';
|
||||
import {Theme} from './ui/styleUtils';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import { Text } from './ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {Icon} from 'react-native-elements';
|
||||
import {Text} from './ui';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
|
||||
export const CopyButton: React.FC<CopyButtonProps> = ({ content }) => {
|
||||
const { t } = useTranslation('common');
|
||||
export const CopyButton: React.FC<CopyButtonProps> = ({content}) => {
|
||||
const {t} = useTranslation('common');
|
||||
const [buttonText, setButtonText] = useState(t('clipboard.copy'));
|
||||
|
||||
return (
|
||||
@@ -22,10 +22,12 @@ export const CopyButton: React.FC<CopyButtonProps> = ({ content }) => {
|
||||
type={'material'}
|
||||
name={'file-copy'}
|
||||
color={Theme.Colors.Icon}
|
||||
style={{ marginRight: 2 }}
|
||||
style={{marginRight: 2}}
|
||||
size={19}
|
||||
/>
|
||||
<Text style={Theme.TextStyles.semibold}>{buttonText}</Text>
|
||||
<Text style={{...Theme.TextStyles.semibold, paddingTop: 3}}>
|
||||
{buttonText}
|
||||
</Text>
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"requestedBy": "Requested by",
|
||||
"sentBy": "Sent by",
|
||||
"deviceRefNumber": "Device reference number",
|
||||
"name": "Name"
|
||||
}
|
||||
@@ -37,17 +37,17 @@ export const EditableListItem: React.FC<EditableListItemProps> = props => {
|
||||
color={Theme.Colors.Icon}
|
||||
/>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<Text weight="semibold" color={Theme.Colors.profileLabel}>
|
||||
<ListItem.Title style={{paddingTop: 3}}>
|
||||
<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 {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -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');
|
||||
@@ -129,12 +130,6 @@ export const FaceScanner: React.FC<FaceScannerProps> = props => {
|
||||
</Centered>
|
||||
</Row>
|
||||
)}
|
||||
{/* TODO: remove warning when iOS SDK is ready */}
|
||||
{Platform.OS === 'ios' && (
|
||||
<Text size="smaller" color={Theme.Colors.textLabel} align="center">
|
||||
(face-matching in iOS is mocked)
|
||||
</Text>
|
||||
)}
|
||||
</Centered>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -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__});
|
||||
|
||||
@@ -6,7 +6,6 @@ import Storage from '../shared/storage';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import i18next from 'i18next';
|
||||
import RNRestart from 'react-native-restart';
|
||||
import {__SelectedLanguage} from '../shared/GlobalVariables';
|
||||
|
||||
export const LanguageSelector: React.FC<LanguageSelectorProps> = props => {
|
||||
const {i18n} = useTranslation();
|
||||
@@ -17,7 +16,6 @@ export const LanguageSelector: React.FC<LanguageSelectorProps> = props => {
|
||||
const changeLanguage = async (language: string) => {
|
||||
if (language !== i18n.language) {
|
||||
await i18n.changeLanguage(language).then(async () => {
|
||||
__SelectedLanguage.setValue(language);
|
||||
await Storage.setItem('language', i18n.language);
|
||||
const isRTL = i18next.dir(language) === 'rtl' ? true : false;
|
||||
if (isRTL !== I18nManager.isRTL) {
|
||||
|
||||
@@ -29,6 +29,7 @@ export const MessageOverlay: React.FC<MessageOverlayProps> = props => {
|
||||
<Column padding="21" crossAlign="center">
|
||||
{props.title && (
|
||||
<Text
|
||||
style={{paddingTop: 3}}
|
||||
align="center"
|
||||
weight="bold"
|
||||
margin="0 0 10 0"
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"title": "OIDC Authentication",
|
||||
"text": "To be replaced with the OIDC provider UI",
|
||||
"verify": "Verify"
|
||||
}
|
||||
@@ -1,11 +1,19 @@
|
||||
import React from 'react';
|
||||
import { Modal as RNModal } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import { PasscodeVerify } from '../components/PasscodeVerify';
|
||||
import { Column, Text } from '../components/ui';
|
||||
import { Theme } from '../components/ui/styleUtils';
|
||||
import React, {useEffect} from 'react';
|
||||
import {Modal as RNModal} from 'react-native';
|
||||
import {Icon} from 'react-native-elements';
|
||||
import {PasscodeVerify} from '../components/PasscodeVerify';
|
||||
import {Column, Text} from '../components/ui';
|
||||
import {Theme} from '../components/ui/styleUtils';
|
||||
import {
|
||||
getImpressionEventData,
|
||||
sendImpressionEvent,
|
||||
} from '../shared/telemetry/TelemetryUtils';
|
||||
|
||||
export const Passcode: React.FC<PasscodeProps> = props => {
|
||||
useEffect(() => {
|
||||
sendImpressionEvent(getImpressionEventData('App Login', 'Passcode'));
|
||||
}, []);
|
||||
|
||||
export const Passcode: React.FC<PasscodeProps> = (props) => {
|
||||
return (
|
||||
<RNModal
|
||||
animationType="slide"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"passcodeMismatchError": "Passcode did not match."
|
||||
}
|
||||
@@ -13,6 +13,7 @@ export const PasscodeVerify: React.FC<PasscodeVerifyProps> = props => {
|
||||
useEffect(() => {
|
||||
if (isVerified) {
|
||||
props.onSuccess();
|
||||
setIsVerified(false);
|
||||
}
|
||||
}, [isVerified]);
|
||||
|
||||
@@ -21,11 +22,17 @@ export const PasscodeVerify: React.FC<PasscodeVerifyProps> = props => {
|
||||
);
|
||||
|
||||
async function verify(value: string) {
|
||||
const hashedPasscode = await hashData(value, props.salt, argon2iConfig);
|
||||
if (props.passcode === hashedPasscode) {
|
||||
setIsVerified(true);
|
||||
} else {
|
||||
props.onError(t('passcodeMismatchError'));
|
||||
try {
|
||||
const hashedPasscode = await hashData(value, props.salt, argon2iConfig);
|
||||
if (props.passcode === hashedPasscode) {
|
||||
setIsVerified(true);
|
||||
} else {
|
||||
if (props.onError) {
|
||||
props.onError(t('passcodeMismatchError'));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"missingPermissionText": "This app uses the camera to scan the QR code of another device.",
|
||||
"allowCameraButton": "Allow access to camera"
|
||||
}
|
||||
@@ -1,55 +1,40 @@
|
||||
import React, {useContext, useEffect, useMemo, useRef} from 'react';
|
||||
import {useInterpret, useSelector} from '@xstate/react';
|
||||
import {View, Pressable} from 'react-native';
|
||||
import React, {useEffect} from 'react';
|
||||
import {Pressable, View} from 'react-native';
|
||||
import {ActorRefFrom} from 'xstate';
|
||||
import {
|
||||
createExistingMosipVCItemMachine,
|
||||
selectVerifiableCredential,
|
||||
selectGeneratedOn,
|
||||
ExistingMosipVCItemEvents,
|
||||
ExistingMosipVCItemMachine,
|
||||
selectContext,
|
||||
selectEmptyWalletBindingId,
|
||||
selectIsSavingFailedInIdle,
|
||||
selectKebabPopUp,
|
||||
} from '../../../machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine';
|
||||
import {ExistingMosipVCItemEvents} from '../../../machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine';
|
||||
import {ErrorMessageOverlay} from '../../MessageOverlay';
|
||||
import {Theme} from '../../ui/styleUtils';
|
||||
import {GlobalContext} from '../../../shared/GlobalContext';
|
||||
import {MosipVCItemContent} from './MosipVCItemContent';
|
||||
import {MosipVCItemActivationStatus} from './MosipVCItemActivationStatus';
|
||||
import {Row} from '../../ui';
|
||||
import {KebabPopUp} from '../../KebabPopUp';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {format} from 'date-fns';
|
||||
import {
|
||||
createEsignetMosipVCItemMachine,
|
||||
EsignetMosipVCItemEvents,
|
||||
EsignetMosipVCItemMachine,
|
||||
selectContext as esignetSelectContext,
|
||||
selectEmptyWalletBindingId as esignetSelectEmptyWalletBindingId,
|
||||
selectGeneratedOn as esignetSelectGeneratedOn,
|
||||
selectKebabPopUp as esignetSelectKebabPopUp,
|
||||
selectVerifiableCredentials as esignetSelectVerifiableCredentials,
|
||||
} from '../../../machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine';
|
||||
import {EsignetMosipVCItemMachine} from '../../../machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine';
|
||||
import {useVcItemController} from './VcItemController';
|
||||
|
||||
export const MosipVCItem: React.FC<
|
||||
ExistingMosipVCItemProps | EsignetMosipVCItemProps
|
||||
> = props => {
|
||||
const {appService} = useContext(GlobalContext);
|
||||
const machine = useRef(
|
||||
!props.vcMetadata.isFromOpenId4VCI()
|
||||
? createExistingMosipVCItemMachine(
|
||||
appService.getSnapshot().context.serviceRefs,
|
||||
props.vcMetadata,
|
||||
)
|
||||
: createEsignetMosipVCItemMachine(
|
||||
appService.getSnapshot().context.serviceRefs,
|
||||
props.vcMetadata,
|
||||
),
|
||||
);
|
||||
let {
|
||||
service,
|
||||
context,
|
||||
verifiableCredential,
|
||||
emptyWalletBindingId,
|
||||
isKebabPopUp,
|
||||
isSavingFailedInIdle,
|
||||
storeErrorTranslationPath,
|
||||
generatedOn,
|
||||
|
||||
const service = useInterpret(machine.current, {devTools: __DEV__});
|
||||
DISMISS,
|
||||
KEBAB_POPUP,
|
||||
} = useVcItemController(props);
|
||||
|
||||
let formattedDate =
|
||||
generatedOn && format(new Date(generatedOn), 'MM/dd/yyyy');
|
||||
|
||||
useEffect(() => {
|
||||
service.send(
|
||||
@@ -57,32 +42,6 @@ export const MosipVCItem: React.FC<
|
||||
);
|
||||
}, [props.vcMetadata]);
|
||||
|
||||
let context = useSelector(service, selectContext);
|
||||
let verifiableCredential = useSelector(service, selectVerifiableCredential);
|
||||
let emptyWalletBindingId = useSelector(service, selectEmptyWalletBindingId);
|
||||
let isKebabPopUp = useSelector(service, selectKebabPopUp);
|
||||
let DISMISS = () => service.send(ExistingMosipVCItemEvents.DISMISS());
|
||||
let KEBAB_POPUP = () => service.send(ExistingMosipVCItemEvents.KEBAB_POPUP());
|
||||
const isSavingFailedInIdle = useSelector(service, selectIsSavingFailedInIdle);
|
||||
const storeErrorTranslationPath = 'errors.savingFailed';
|
||||
let generatedOn = useSelector(service, selectGeneratedOn);
|
||||
if (props.vcMetadata.isFromOpenId4VCI()) {
|
||||
context = useSelector(service, esignetSelectContext);
|
||||
isKebabPopUp = useSelector(service, esignetSelectKebabPopUp);
|
||||
generatedOn = useSelector(service, esignetSelectGeneratedOn);
|
||||
emptyWalletBindingId = useSelector(
|
||||
service,
|
||||
esignetSelectEmptyWalletBindingId,
|
||||
);
|
||||
DISMISS = () => service.send(EsignetMosipVCItemEvents.DISMISS());
|
||||
KEBAB_POPUP = () => service.send(EsignetMosipVCItemEvents.KEBAB_POPUP());
|
||||
verifiableCredential = useSelector(
|
||||
service,
|
||||
esignetSelectVerifiableCredentials,
|
||||
);
|
||||
}
|
||||
let formattedDate =
|
||||
generatedOn && format(new Date(generatedOn), 'MM/dd/yyyy');
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Pressable
|
||||
@@ -105,20 +64,17 @@ export const MosipVCItem: React.FC<
|
||||
iconName={props.iconName}
|
||||
iconType={props.iconType}
|
||||
onPress={() => props.onPress(service)}
|
||||
isDownloading={props.isDownloading}
|
||||
/>
|
||||
<View style={Theme.Styles.horizontalLine} />
|
||||
{props.isSharingVc ? null : (
|
||||
<Row style={Theme.Styles.activationTab}>
|
||||
{props.activeTab !== 'receivedVcsTab' &&
|
||||
props.activeTab != 'sharingVcScreen' && (
|
||||
<MosipVCItemActivationStatus
|
||||
vcMetadata={props.vcMetadata}
|
||||
verifiableCredential={verifiableCredential}
|
||||
emptyWalletBindingId={emptyWalletBindingId}
|
||||
onPress={() => props.onPress(service)}
|
||||
showOnlyBindedVc={props.showOnlyBindedVc}
|
||||
/>
|
||||
)}
|
||||
<MosipVCItemActivationStatus
|
||||
vcMetadata={props.vcMetadata}
|
||||
verifiableCredential={verifiableCredential}
|
||||
emptyWalletBindingId={emptyWalletBindingId}
|
||||
showOnlyBindedVc={props.showOnlyBindedVc}
|
||||
/>
|
||||
<View style={Theme.Styles.verticalLine} />
|
||||
<Row style={Theme.Styles.kebabIcon}>
|
||||
<Pressable onPress={KEBAB_POPUP} accessible={false}>
|
||||
@@ -153,10 +109,10 @@ export interface ExistingMosipVCItemProps {
|
||||
showOnlyBindedVc?: boolean;
|
||||
onPress?: (vcRef?: ActorRefFrom<typeof ExistingMosipVCItemMachine>) => void;
|
||||
onShow?: (vcRef?: ActorRefFrom<typeof ExistingMosipVCItemMachine>) => void;
|
||||
activeTab?: string;
|
||||
iconName?: string;
|
||||
iconType?: string;
|
||||
isSharingVc?: boolean;
|
||||
isDownloading?: boolean;
|
||||
}
|
||||
|
||||
export interface EsignetMosipVCItemProps {
|
||||
@@ -167,8 +123,8 @@ export interface EsignetMosipVCItemProps {
|
||||
showOnlyBindedVc?: boolean;
|
||||
onPress?: (vcRef?: ActorRefFrom<typeof EsignetMosipVCItemMachine>) => void;
|
||||
onShow?: (vcRef?: ActorRefFrom<typeof EsignetMosipVCItemMachine>) => void;
|
||||
activeTab?: string;
|
||||
iconName?: string;
|
||||
iconType?: string;
|
||||
isSharingVc?: boolean;
|
||||
isDownloading?: boolean;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ import React from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {Dimensions} from 'react-native';
|
||||
import {Icon} from 'react-native-elements';
|
||||
import {ActorRefFrom} from 'xstate';
|
||||
import {ExistingMosipVCItemMachine} from '../../../machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine';
|
||||
import {VerifiableCredential} from '../../../types/VC/ExistingMosipVC/vc';
|
||||
import {Row, Text} from '../../ui';
|
||||
import {Theme} from '../../ui/styleUtils';
|
||||
@@ -16,9 +14,10 @@ const WalletUnverifiedIcon: React.FC = () => {
|
||||
size={Theme.ICON_MID_SIZE}
|
||||
type="material-community"
|
||||
containerStyle={{
|
||||
marginStart: 10,
|
||||
marginStart: 1,
|
||||
marginEnd: 1,
|
||||
bottom: 1,
|
||||
marginLeft: 10,
|
||||
marginRight: -2,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -48,13 +47,14 @@ const WalletUnverifiedActivationDetails: React.FC<
|
||||
crossAlign="center"
|
||||
style={{
|
||||
flex: 1,
|
||||
maxWidth: 255,
|
||||
}}>
|
||||
{props.verifiableCredential && <WalletUnverifiedIcon />}
|
||||
<Text
|
||||
color={Theme.Colors.Details}
|
||||
testID="activationPending"
|
||||
weight="regular"
|
||||
margin="8 10 10 5"
|
||||
margin="8"
|
||||
style={
|
||||
!props.verifiableCredential
|
||||
? Theme.Styles.loadingTitle
|
||||
@@ -106,13 +106,11 @@ export const MosipVCItemActivationStatus: React.FC<
|
||||
{props.emptyWalletBindingId ? (
|
||||
<WalletUnverifiedActivationDetails
|
||||
verifiableCredential={props.verifiableCredential}
|
||||
onPress={props.onPress}
|
||||
/>
|
||||
) : (
|
||||
<WalletVerifiedActivationDetails
|
||||
verifiableCredential={props.verifiableCredential}
|
||||
showOnlyBindedVc={props.showOnlyBindedVc}
|
||||
onPress={props.onPress}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
@@ -121,18 +119,15 @@ export const MosipVCItemActivationStatus: React.FC<
|
||||
|
||||
interface ExistingMosipVCItemActivationStatusProps {
|
||||
showOnlyBindedVc: boolean;
|
||||
onPress: (vcRef?: ActorRefFrom<typeof ExistingMosipVCItemMachine>) => void;
|
||||
verifiableCredential: VerifiableCredential;
|
||||
emptyWalletBindingId: boolean;
|
||||
}
|
||||
|
||||
interface WalletVerifiedDetailsProps {
|
||||
showOnlyBindedVc: boolean;
|
||||
onPress: (vcRef?: ActorRefFrom<typeof ExistingMosipVCItemMachine>) => void;
|
||||
verifiableCredential: VerifiableCredential;
|
||||
}
|
||||
|
||||
interface WalletUnVerifiedDetailsProps {
|
||||
onPress: (vcRef?: ActorRefFrom<typeof ExistingMosipVCItemMachine>) => void;
|
||||
verifiableCredential: VerifiableCredential;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {Image, ImageBackground, View} from 'react-native';
|
||||
import {Image, ImageBackground} from 'react-native';
|
||||
import {getLocalizedField} from '../../../i18n';
|
||||
import {VerifiableCredential} from '../../../types/VC/ExistingMosipVC/vc';
|
||||
import VerifiedIcon from '../../VerifiedIcon';
|
||||
import {Column, Row, Text} from '../../ui';
|
||||
import {Theme} from '../../ui/styleUtils';
|
||||
import {CheckBox, Icon} from 'react-native-elements';
|
||||
import testIDProps from '../../../shared/commonUtil';
|
||||
import testIDProps, {getMaskedText} from '../../../shared/commonUtil';
|
||||
import {logoType} from '../../../machines/issuersMachine';
|
||||
|
||||
const getDetails = (arg1, arg2, verifiableCredential) => {
|
||||
if (arg1 === 'Status') {
|
||||
@@ -83,15 +84,12 @@ const getDetails = (arg1, arg2, verifiableCredential) => {
|
||||
}
|
||||
};
|
||||
|
||||
function getIdNumber(id: string) {
|
||||
return '*'.repeat(id.length - 4) + id.slice(-4);
|
||||
}
|
||||
|
||||
const getIssuerLogo = (isOpenId4VCI: boolean, issuerLogo: string) => {
|
||||
const getIssuerLogo = (isOpenId4VCI: boolean, issuerLogo: logoType) => {
|
||||
if (isOpenId4VCI) {
|
||||
return (
|
||||
<Image
|
||||
src={issuerLogo}
|
||||
src={issuerLogo?.url}
|
||||
alt={issuerLogo?.alt_text}
|
||||
style={Theme.Styles.issuerLogo}
|
||||
resizeMethod="scale"
|
||||
resizeMode="contain"
|
||||
@@ -111,7 +109,9 @@ const getIssuerLogo = (isOpenId4VCI: boolean, issuerLogo: string) => {
|
||||
export const MosipVCItemContent: React.FC<
|
||||
ExistingMosipVCItemContentProps | EsignetMosipVCItemContentProps
|
||||
> = props => {
|
||||
const verifiableCredential = props.vcMetadata.isFromOpenId4VCI()
|
||||
const verifiableCredential = props.isDownloading
|
||||
? null
|
||||
: props.vcMetadata.isFromOpenId4VCI()
|
||||
? props.verifiableCredential?.credential
|
||||
: props.verifiableCredential;
|
||||
|
||||
@@ -165,7 +165,7 @@ export const MosipVCItemContent: React.FC<
|
||||
</ImageBackground>
|
||||
|
||||
<Column margin="0 0 10 20" height={96} align="space-between">
|
||||
<Column>
|
||||
<Column style={{maxWidth: 230}}>
|
||||
<Text
|
||||
testID="fullNameTitle"
|
||||
weight="regular"
|
||||
@@ -239,7 +239,7 @@ export const MosipVCItemContent: React.FC<
|
||||
weight="semibold"
|
||||
size="extraSmall"
|
||||
color={Theme.Colors.statusLabel}>
|
||||
{getIdNumber(uin)}
|
||||
{getMaskedText(uin)}
|
||||
</Text>
|
||||
</Column>
|
||||
) : null}
|
||||
@@ -258,7 +258,7 @@ export const MosipVCItemContent: React.FC<
|
||||
weight="semibold"
|
||||
size="extraSmall"
|
||||
color={Theme.Colors.Details}>
|
||||
{getIdNumber(vid)}
|
||||
{getMaskedText(vid)}
|
||||
</Text>
|
||||
</Column>
|
||||
) : null}
|
||||
@@ -319,7 +319,7 @@ export const MosipVCItemContent: React.FC<
|
||||
|
||||
function faceImageSource() {
|
||||
return !verifiableCredential
|
||||
? Theme.ProfileIcon
|
||||
? Theme.cardFaceIcon
|
||||
: {
|
||||
uri: props.vcMetadata.isFromOpenId4VCI()
|
||||
? verifiableCredential?.credentialSubject.face
|
||||
@@ -338,6 +338,7 @@ interface ExistingMosipVCItemContentProps {
|
||||
iconType?: string;
|
||||
service: any;
|
||||
onPress?: () => void;
|
||||
isDownloading?: boolean;
|
||||
}
|
||||
|
||||
export interface EsignetMosipVCItemContentProps {
|
||||
@@ -350,4 +351,5 @@ export interface EsignetMosipVCItemContentProps {
|
||||
iconType?: string;
|
||||
service: any;
|
||||
onPress?: () => void;
|
||||
isDownloading?: boolean;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import {format, formatDistanceToNow, parse} from 'date-fns';
|
||||
import React from 'react';
|
||||
import * as DateFnsLocale from 'date-fns/locale';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {Image, ImageBackground, View} from 'react-native';
|
||||
import {Dimensions, Image, ImageBackground, View} from 'react-native';
|
||||
import {Icon} from 'react-native-elements';
|
||||
import {VC, CredentialSubject} from '../../../types/VC/ExistingMosipVC/vc';
|
||||
import {CredentialSubject, VC} from '../../../types/VC/ExistingMosipVC/vc';
|
||||
import {Button, Column, Row, Text} from '../../ui';
|
||||
import {Theme} from '../../ui/styleUtils';
|
||||
import {TextItem} from '../../ui/TextItem';
|
||||
@@ -20,10 +20,17 @@ import {
|
||||
VerifiablePresentation,
|
||||
} from '../../../types/VC/EsignetMosipVC/vc';
|
||||
import {WalletBindingResponse} from '../../../shared/cryptoutil/cryptoUtil';
|
||||
import {logoType} from '../../../machines/issuersMachine';
|
||||
|
||||
const getIssuerLogo = (isOpenId4VCI: boolean, issuerLogo: string) => {
|
||||
const getIssuerLogo = (isOpenId4VCI: boolean, issuerLogo: logoType) => {
|
||||
if (isOpenId4VCI) {
|
||||
return <Image src={issuerLogo} style={Theme.Styles.issuerLogo} />;
|
||||
return (
|
||||
<Image
|
||||
src={issuerLogo?.url}
|
||||
alt={issuerLogo?.alt_text}
|
||||
style={Theme.Styles.issuerLogo}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <Image source={Theme.MosipLogo} style={Theme.Styles.vcDetailsLogo} />;
|
||||
};
|
||||
@@ -42,7 +49,7 @@ const getProfileImage = (
|
||||
return {uri: props.vc?.credential.biometrics.face};
|
||||
}
|
||||
}
|
||||
return Theme.ProfileIcon;
|
||||
return Theme.cardFaceIcon;
|
||||
};
|
||||
|
||||
export const MosipVCItemDetails: React.FC<
|
||||
@@ -68,14 +75,14 @@ export const MosipVCItemDetails: React.FC<
|
||||
}
|
||||
|
||||
return (
|
||||
<Column margin="10">
|
||||
<Column margin="10 4 10 4">
|
||||
<ImageBackground
|
||||
imageStyle={{width: '100%'}}
|
||||
resizeMethod="scale"
|
||||
resizeMode="stretch"
|
||||
style={Theme.Styles.openCardBgContainer}
|
||||
source={Theme.OpenCard}>
|
||||
<Row align="space-between" padding="10" margin="0 10 0 10">
|
||||
<Row align="space-between" padding="10" margin="0 10 0 8">
|
||||
<Column align="space-evenly" crossAlign="center">
|
||||
<Image
|
||||
source={getProfileImage(
|
||||
@@ -101,6 +108,7 @@ export const MosipVCItemDetails: React.FC<
|
||||
<Text
|
||||
testID="fullNameValue"
|
||||
weight="semibold"
|
||||
style={{maxWidth: 190}}
|
||||
size="smaller"
|
||||
color={Theme.Colors.Details}>
|
||||
{getLocalizedField(
|
||||
@@ -139,6 +147,7 @@ export const MosipVCItemDetails: React.FC<
|
||||
<Text
|
||||
testID="nationalCard"
|
||||
weight="bold"
|
||||
style={{minWidth: 65}}
|
||||
size="smaller"
|
||||
color={Theme.Colors.Details}>
|
||||
{t('nationalCard')}
|
||||
@@ -198,10 +207,11 @@ export const MosipVCItemDetails: React.FC<
|
||||
</Text>
|
||||
</Column>
|
||||
</Column>
|
||||
<Column margin="0 0 0 40">
|
||||
<Column margin="0 0 0 38">
|
||||
<Column margin="20 0 0 0">
|
||||
<Text
|
||||
testID="dateOfBirth"
|
||||
style={{maxWidth: 121}}
|
||||
weight="regular"
|
||||
size="smaller"
|
||||
color={Theme.Colors.DetailsLabel}>
|
||||
@@ -215,7 +225,8 @@ export const MosipVCItemDetails: React.FC<
|
||||
{formattedDateOfBirth()}
|
||||
</Text>
|
||||
</Column>
|
||||
<Column margin="25 0 0 0">
|
||||
<Column
|
||||
style={{marginTop: Dimensions.get('window').height * 0.04}}>
|
||||
<Text
|
||||
testID="status"
|
||||
weight="regular"
|
||||
@@ -231,6 +242,7 @@ export const MosipVCItemDetails: React.FC<
|
||||
{props.vc?.isVerified && <VerifiedIcon />}
|
||||
<Text
|
||||
testID="valid"
|
||||
style={{maxWidth: 63}}
|
||||
weight="semibold"
|
||||
size="smaller"
|
||||
color={Theme.Colors.Details}>
|
||||
@@ -238,9 +250,11 @@ export const MosipVCItemDetails: React.FC<
|
||||
</Text>
|
||||
</Row>
|
||||
</Column>
|
||||
<Column margin="92 0 0 0">
|
||||
<Column
|
||||
style={{marginTop: Dimensions.get('window').height * 0.1}}>
|
||||
<Text
|
||||
testID="phoneNumber"
|
||||
style={{maxWidth: 80}}
|
||||
weight="regular"
|
||||
size="smaller"
|
||||
color={Theme.Colors.DetailsLabel}>
|
||||
|
||||
79
components/VC/MosipVCItem/VcItemController.tsx
Normal file
79
components/VC/MosipVCItem/VcItemController.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import {useContext, useRef} from 'react';
|
||||
import {GlobalContext} from '../../../shared/GlobalContext';
|
||||
import {
|
||||
createExistingMosipVCItemMachine,
|
||||
ExistingMosipVCItemEvents,
|
||||
selectContext,
|
||||
selectEmptyWalletBindingId,
|
||||
selectGeneratedOn,
|
||||
selectIsSavingFailedInIdle,
|
||||
selectKebabPopUp,
|
||||
selectVerifiableCredential,
|
||||
} from '../../../machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine';
|
||||
import {
|
||||
createEsignetMosipVCItemMachine,
|
||||
EsignetMosipVCItemEvents,
|
||||
selectContext as esignetSelectContext,
|
||||
selectEmptyWalletBindingId as esignetSelectEmptyWalletBindingId,
|
||||
selectGeneratedOn as esignetSelectGeneratedOn,
|
||||
selectKebabPopUp as esignetSelectKebabPopUp,
|
||||
selectVerifiableCredentials as esignetSelectVerifiableCredentials,
|
||||
} from '../../../machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine';
|
||||
import {useInterpret, useSelector} from '@xstate/react';
|
||||
import {EsignetMosipVCItemProps, ExistingMosipVCItemProps} from './MosipVCItem';
|
||||
|
||||
export function useVcItemController(
|
||||
props: ExistingMosipVCItemProps | EsignetMosipVCItemProps,
|
||||
) {
|
||||
const {appService} = useContext(GlobalContext);
|
||||
const machine = useRef(
|
||||
!props.vcMetadata.isFromOpenId4VCI()
|
||||
? createExistingMosipVCItemMachine(
|
||||
appService.getSnapshot().context.serviceRefs,
|
||||
props.vcMetadata,
|
||||
)
|
||||
: createEsignetMosipVCItemMachine(
|
||||
appService.getSnapshot().context.serviceRefs,
|
||||
props.vcMetadata,
|
||||
),
|
||||
);
|
||||
|
||||
const service = useInterpret(machine.current, {devTools: __DEV__});
|
||||
|
||||
let context = useSelector(service, selectContext);
|
||||
let verifiableCredential = useSelector(service, selectVerifiableCredential);
|
||||
let emptyWalletBindingId = useSelector(service, selectEmptyWalletBindingId);
|
||||
let isKebabPopUp = useSelector(service, selectKebabPopUp);
|
||||
let DISMISS = () => service.send(ExistingMosipVCItemEvents.DISMISS());
|
||||
let KEBAB_POPUP = () => service.send(ExistingMosipVCItemEvents.KEBAB_POPUP());
|
||||
const isSavingFailedInIdle = useSelector(service, selectIsSavingFailedInIdle);
|
||||
const storeErrorTranslationPath = 'errors.savingFailed';
|
||||
let generatedOn = useSelector(service, selectGeneratedOn);
|
||||
if (props.vcMetadata.isFromOpenId4VCI()) {
|
||||
context = useSelector(service, esignetSelectContext);
|
||||
isKebabPopUp = useSelector(service, esignetSelectKebabPopUp);
|
||||
generatedOn = useSelector(service, esignetSelectGeneratedOn);
|
||||
emptyWalletBindingId = useSelector(
|
||||
service,
|
||||
esignetSelectEmptyWalletBindingId,
|
||||
);
|
||||
DISMISS = () => service.send(EsignetMosipVCItemEvents.DISMISS());
|
||||
KEBAB_POPUP = () => service.send(EsignetMosipVCItemEvents.KEBAB_POPUP());
|
||||
verifiableCredential = useSelector(
|
||||
service,
|
||||
esignetSelectVerifiableCredentials,
|
||||
);
|
||||
}
|
||||
return {
|
||||
service,
|
||||
context,
|
||||
verifiableCredential,
|
||||
emptyWalletBindingId,
|
||||
isKebabPopUp,
|
||||
DISMISS,
|
||||
KEBAB_POPUP,
|
||||
isSavingFailedInIdle,
|
||||
storeErrorTranslationPath,
|
||||
generatedOn,
|
||||
};
|
||||
}
|
||||
@@ -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."
|
||||
}
|
||||
@@ -9,8 +9,7 @@ export const Issuer: React.FC<IssuerProps> = (props: IssuerProps) => {
|
||||
const {t} = useTranslation('IssuersScreen');
|
||||
|
||||
function getIssuerLogo() {
|
||||
if (props.logoUrl) return {uri: props.logoUrl};
|
||||
return Theme.DigitIcon;
|
||||
return {uri: props.logoUrl};
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -45,6 +45,7 @@ export const Button: React.FC<ButtonProps> = props => {
|
||||
raised={props.raised}
|
||||
title={
|
||||
<Text
|
||||
style={{paddingTop: 3}}
|
||||
weight="semibold"
|
||||
align="center"
|
||||
color={
|
||||
@@ -77,7 +78,7 @@ export const Button: React.FC<ButtonProps> = props => {
|
||||
raised={props.raised}
|
||||
title={
|
||||
<Text
|
||||
style={Theme.TextStyles.bold}
|
||||
style={{...Theme.TextStyles.bold, paddingTop: 3}}
|
||||
color={
|
||||
type === 'solid' || type === 'gradient' || type === 'radius'
|
||||
? Theme.Colors.whiteText
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
import React, {Fragment} from 'react';
|
||||
import React, {Fragment, useEffect} from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {Image, SafeAreaView, View} from 'react-native';
|
||||
import {BackHandler, Image, SafeAreaView, View} from 'react-native';
|
||||
import Spinner from 'react-native-spinkit';
|
||||
import {Button, Centered, Column, Row, Text} from '../../components/ui';
|
||||
import {Theme} from '../../components/ui/styleUtils';
|
||||
import {Theme} from './styleUtils';
|
||||
import testIDProps from '../../shared/commonUtil';
|
||||
|
||||
export const Loader: React.FC<LoaderProps> = props => {
|
||||
const {t} = useTranslation('ScanScreen');
|
||||
|
||||
useEffect(() => {
|
||||
const backHandler = BackHandler.addEventListener(
|
||||
'hardwareBackPress',
|
||||
() => true,
|
||||
);
|
||||
return () => backHandler.remove();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Row style={{backgroundColor: Theme.Colors.whiteBackgroundColor}}>
|
||||
@@ -17,7 +25,7 @@ export const Loader: React.FC<LoaderProps> = props => {
|
||||
fill
|
||||
align={'flex-start'}
|
||||
style={Theme.LoaderStyles.titleContainer}>
|
||||
<View style={Theme.issuersScreenStyles.loaderHeadingText}>
|
||||
<View style={Theme.LoaderStyles.heading}>
|
||||
<Text
|
||||
style={Theme.TextStyles.semiBoldHeader}
|
||||
testID="loaderTitle">
|
||||
@@ -26,7 +34,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>
|
||||
@@ -81,7 +89,7 @@ export const Loader: React.FC<LoaderProps> = props => {
|
||||
|
||||
export interface LoaderProps {
|
||||
isVisible: boolean;
|
||||
title?: string;
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
label?: string;
|
||||
hint?: string;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -40,7 +40,7 @@ export const SetupPicker: Picker = (props: PickerProps<unknown>) => {
|
||||
onPress={() => selectItem(index)}
|
||||
key={index}>
|
||||
<ListItem.Content>
|
||||
<ListItem.Title>
|
||||
<ListItem.Title style={{paddingTop: 3}}>
|
||||
<Text
|
||||
color={selectedIndex === index ? Theme.Colors.Icon : null}
|
||||
weight={selectedIndex === index ? 'semibold' : 'regular'}>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable sonarjs/no-duplicate-string */
|
||||
import {Dimensions, Platform, StyleSheet, ViewStyle} from 'react-native';
|
||||
import {Dimensions, 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,
|
||||
@@ -82,7 +79,6 @@ export const DefaultTheme = {
|
||||
VerifiedIcon: Colors.Green,
|
||||
whiteText: Colors.White,
|
||||
flipCameraIcon: Colors.Black,
|
||||
IdInputModalBorder: Colors.Grey,
|
||||
RetrieveIdLabel: Colors.ShadeOfGrey,
|
||||
inputSelection: Colors.Orange,
|
||||
checkCircleIcon: Colors.White,
|
||||
@@ -90,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'],
|
||||
@@ -109,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: {
|
||||
@@ -177,8 +174,8 @@ export const DefaultTheme = {
|
||||
cardDetailsContainer: {},
|
||||
bottomTabIconStyle: {
|
||||
padding: 4,
|
||||
width: 36,
|
||||
height: 36,
|
||||
width: Dimensions.get('window').width * 0.12,
|
||||
height: Dimensions.get('window').height * 0.045,
|
||||
borderRadius: 6,
|
||||
backgroundColor: Colors.LightOrange,
|
||||
},
|
||||
@@ -226,8 +223,8 @@ export const DefaultTheme = {
|
||||
height: 30,
|
||||
backgroundColor: Colors.Grey,
|
||||
marginVertical: 8,
|
||||
marginLeft: -45,
|
||||
marginRight: 22,
|
||||
marginLeft: -25,
|
||||
marginRight: 12,
|
||||
},
|
||||
closeCardBgContainer: {
|
||||
borderRadius: 10,
|
||||
@@ -492,6 +489,22 @@ export const DefaultTheme = {
|
||||
fontSize: 15,
|
||||
fontFamily: 'Inter_700Bold',
|
||||
},
|
||||
idInputContainer: {
|
||||
marginTop: 20,
|
||||
marginRight: Dimensions.get('window').width * 0.26,
|
||||
},
|
||||
idInputPicker: {
|
||||
width: Dimensions.get('window').width * 0.32,
|
||||
borderBottomWidth: 1,
|
||||
marginBottom: 2,
|
||||
borderColor: isIOS() ? 'transparent' : Colors.Grey,
|
||||
bottom: isIOS() ? 50 : 24,
|
||||
height: isIOS() ? 100 : 'auto',
|
||||
},
|
||||
idInputBottom: {
|
||||
borderBottomColor: Colors.Orange,
|
||||
borderBottomWidth: 1,
|
||||
},
|
||||
getId: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
@@ -511,12 +524,11 @@ export const DefaultTheme = {
|
||||
borderBottomColor: Colors.platinumGrey,
|
||||
borderBottomWidth: 1.3,
|
||||
},
|
||||
downloadFabIcon: {
|
||||
downloadFabIconContainer: {
|
||||
height: 70,
|
||||
width: 70,
|
||||
borderRadius: 200,
|
||||
padding: 10,
|
||||
backgroundColor: Colors.Orange,
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.4,
|
||||
elevation: 5,
|
||||
@@ -524,6 +536,21 @@ export const DefaultTheme = {
|
||||
bottom: Dimensions.get('window').width * 0.1,
|
||||
right: Dimensions.get('window').width * 0.1,
|
||||
},
|
||||
downloadFabIconNormal: {
|
||||
borderRadius: 200,
|
||||
height: 70,
|
||||
width: 70,
|
||||
justifyContent: 'center',
|
||||
position: 'absolute',
|
||||
},
|
||||
downloadFabIconPressed: {
|
||||
borderRadius: 200,
|
||||
height: 70,
|
||||
width: 70,
|
||||
backgroundColor: Colors.Orange,
|
||||
justifyContent: 'center',
|
||||
position: 'absolute',
|
||||
},
|
||||
boxShadow: generateBoxShadowStyle(),
|
||||
}),
|
||||
QrCodeStyles: StyleSheet.create({
|
||||
@@ -598,14 +625,14 @@ export const DefaultTheme = {
|
||||
fontFamily: 'Inter_700Bold',
|
||||
fontSize: 18,
|
||||
lineHeight: 19,
|
||||
paddingTop: 4,
|
||||
paddingTop: 5,
|
||||
},
|
||||
subHeader: {
|
||||
color: Colors.mediumLightGrayText,
|
||||
fontFamily: 'Inter_600SemiBold',
|
||||
lineHeight: 19,
|
||||
fontSize: 13,
|
||||
paddingTop: 3,
|
||||
paddingTop: 4,
|
||||
},
|
||||
semiBoldHeader: {
|
||||
color: Colors.Black,
|
||||
@@ -717,6 +744,10 @@ export const DefaultTheme = {
|
||||
marginBottom: 17,
|
||||
marginTop: 22,
|
||||
},
|
||||
heading: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
}),
|
||||
ButtonStyles: StyleSheet.create({
|
||||
fill: {
|
||||
@@ -1162,6 +1193,7 @@ export const DefaultTheme = {
|
||||
lineHeight: 17,
|
||||
paddingHorizontal: 3,
|
||||
paddingBottom: 4,
|
||||
paddingTop: 1.7,
|
||||
},
|
||||
issuerDescription: {
|
||||
fontSize: 11,
|
||||
@@ -1169,6 +1201,7 @@ export const DefaultTheme = {
|
||||
color: Colors.ShadeOfGrey,
|
||||
paddingVertical: 5,
|
||||
paddingHorizontal: 3,
|
||||
paddingTop: 1.4,
|
||||
},
|
||||
issuerIcon: {
|
||||
resizeMode: 'contain',
|
||||
@@ -1178,10 +1211,6 @@ export const DefaultTheme = {
|
||||
marginTop: 8,
|
||||
marginLeft: 2.5,
|
||||
},
|
||||
loaderHeadingText: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
}),
|
||||
ErrorStyles: StyleSheet.create({
|
||||
image: {marginTop: -60, paddingBottom: 26},
|
||||
@@ -1204,6 +1233,15 @@ export const DefaultTheme = {
|
||||
color: Colors.mediumDarkGrey,
|
||||
},
|
||||
}),
|
||||
SetupLanguageScreenStyle: StyleSheet.create({
|
||||
columnStyle: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-around',
|
||||
backgroundColor: Colors.White,
|
||||
maxHeight: Dimensions.get('window').height,
|
||||
},
|
||||
}),
|
||||
|
||||
ICON_SMALL_SIZE: 16,
|
||||
ICON_MID_SIZE: 22,
|
||||
@@ -1212,7 +1250,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'),
|
||||
@@ -1230,14 +1268,13 @@ export const DefaultTheme = {
|
||||
InjiHomeLogo: require('../../../assets/inji-home-logo.png'),
|
||||
MagnifierZoom: require('../../../assets/magnifier-zoom.png'),
|
||||
HelpIcon: require('../../../assets/help-icon.png'),
|
||||
sharingIntro: require('../../../assets/Secure-Sharing.png'),
|
||||
sharingIntro: require('../../../assets/intro-secure-sharing.png'),
|
||||
walletIntro: require('../../../assets/intro-wallet-binding.png'),
|
||||
IntroScanner: require('../../../assets/intro-scanner.png'),
|
||||
injiSmallLogo: require('../../../assets/inji_small_logo.png'),
|
||||
protectPrivacy: require('../../../assets/phone_mockup_1.png'),
|
||||
protectPrivacy: require('../../../assets/intro-unlock-method.png'),
|
||||
NoInternetConnection: require('../../../assets/no-internet-connection.png'),
|
||||
SomethingWentWrong: require('../../../assets/something-went-wrong.png'),
|
||||
DigitIcon: require('../../../assets/digit-icon.png'),
|
||||
|
||||
elevation(level: ElevationLevel): ViewStyle {
|
||||
// https://ethercreative.github.io/react-native-shadow-generator/
|
||||
@@ -1283,17 +1320,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',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable sonarjs/no-duplicate-string */
|
||||
import {Dimensions, Platform, StyleSheet, ViewStyle} from 'react-native';
|
||||
import {Dimensions, 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,
|
||||
@@ -85,7 +82,6 @@ export const PurpleTheme = {
|
||||
VerifiedIcon: Colors.Green,
|
||||
whiteText: Colors.White,
|
||||
flipCameraIcon: Colors.Black,
|
||||
IdInputModalBorder: Colors.Grey,
|
||||
RetrieveIdLabel: Colors.ShadeOfGrey,
|
||||
inputSelection: Colors.Purple,
|
||||
checkCircleIcon: Colors.White,
|
||||
@@ -93,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,
|
||||
@@ -111,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: {
|
||||
@@ -179,8 +176,8 @@ export const PurpleTheme = {
|
||||
cardDetailsContainer: {},
|
||||
bottomTabIconStyle: {
|
||||
padding: 4,
|
||||
width: 36,
|
||||
height: 36,
|
||||
width: Dimensions.get('window').width * 0.12,
|
||||
height: Dimensions.get('window').height * 0.045,
|
||||
borderRadius: 6,
|
||||
backgroundColor: Colors.LightPurple,
|
||||
},
|
||||
@@ -228,8 +225,8 @@ export const PurpleTheme = {
|
||||
height: 30,
|
||||
backgroundColor: Colors.Grey,
|
||||
marginVertical: 8,
|
||||
marginLeft: -45,
|
||||
marginRight: 22,
|
||||
marginLeft: -25,
|
||||
marginRight: 12,
|
||||
},
|
||||
closeCardBgContainer: {
|
||||
borderRadius: 10,
|
||||
@@ -494,6 +491,22 @@ export const PurpleTheme = {
|
||||
fontSize: 15,
|
||||
fontFamily: 'Inter_700Bold',
|
||||
},
|
||||
idInputContainer: {
|
||||
marginTop: 20,
|
||||
marginRight: Dimensions.get('window').width * 0.26,
|
||||
},
|
||||
idInputPicker: {
|
||||
width: Dimensions.get('window').width * 0.32,
|
||||
borderBottomWidth: 1,
|
||||
marginBottom: 2,
|
||||
borderColor: isIOS() ? 'transparent' : Colors.Grey,
|
||||
bottom: isIOS() ? 50 : 24,
|
||||
height: isIOS() ? 100 : 'auto',
|
||||
},
|
||||
idInputBottom: {
|
||||
borderBottomColor: Colors.Orange,
|
||||
borderBottomWidth: 1,
|
||||
},
|
||||
getId: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
@@ -513,12 +526,11 @@ export const PurpleTheme = {
|
||||
borderBottomColor: Colors.platinumGrey,
|
||||
borderBottomWidth: 1.3,
|
||||
},
|
||||
downloadFabIcon: {
|
||||
downloadFabIconContainer: {
|
||||
height: 70,
|
||||
width: 70,
|
||||
borderRadius: 200,
|
||||
padding: 10,
|
||||
backgroundColor: Colors.Purple,
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.4,
|
||||
elevation: 5,
|
||||
@@ -526,6 +538,21 @@ export const PurpleTheme = {
|
||||
bottom: Dimensions.get('window').width * 0.1,
|
||||
right: Dimensions.get('window').width * 0.1,
|
||||
},
|
||||
downloadFabIconNormal: {
|
||||
borderRadius: 200,
|
||||
height: 70,
|
||||
width: 70,
|
||||
justifyContent: 'center',
|
||||
position: 'absolute',
|
||||
},
|
||||
downloadFabIconPressed: {
|
||||
borderRadius: 200,
|
||||
height: 70,
|
||||
width: 70,
|
||||
backgroundColor: Colors.Purple,
|
||||
justifyContent: 'center',
|
||||
position: 'absolute',
|
||||
},
|
||||
boxShadow: generateBoxShadowStyle(),
|
||||
}),
|
||||
QrCodeStyles: StyleSheet.create({
|
||||
@@ -600,14 +627,14 @@ export const PurpleTheme = {
|
||||
fontFamily: 'Inter_700Bold',
|
||||
fontSize: 18,
|
||||
lineHeight: 19,
|
||||
paddingTop: 4,
|
||||
paddingTop: 5,
|
||||
},
|
||||
subHeader: {
|
||||
color: Colors.mediumLightGrayText,
|
||||
fontFamily: 'Inter_600SemiBold',
|
||||
lineHeight: 19,
|
||||
fontSize: 13,
|
||||
paddingTop: 3,
|
||||
paddingTop: 4,
|
||||
},
|
||||
semiBoldHeader: {
|
||||
color: Colors.Black,
|
||||
@@ -719,6 +746,10 @@ export const PurpleTheme = {
|
||||
marginBottom: 17,
|
||||
marginTop: 22,
|
||||
},
|
||||
heading: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
}),
|
||||
ButtonStyles: StyleSheet.create({
|
||||
fill: {
|
||||
@@ -1162,11 +1193,13 @@ export const PurpleTheme = {
|
||||
fontFamily: 'Inter_600SemiBold',
|
||||
fontSize: 14,
|
||||
lineHeight: 17,
|
||||
paddingTop: 1.7,
|
||||
},
|
||||
issuerDescription: {
|
||||
fontSize: 11,
|
||||
lineHeight: 14,
|
||||
color: Colors.ShadeOfGrey,
|
||||
paddingTop: 1.4,
|
||||
},
|
||||
issuerIcon: {
|
||||
resizeMode: 'contain',
|
||||
@@ -1176,10 +1209,6 @@ export const PurpleTheme = {
|
||||
marginTop: 8,
|
||||
marginLeft: 2.5,
|
||||
},
|
||||
loaderHeadingText: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
}),
|
||||
ErrorStyles: StyleSheet.create({
|
||||
image: {marginTop: -60, paddingBottom: 26},
|
||||
@@ -1202,6 +1231,16 @@ export const PurpleTheme = {
|
||||
color: Colors.mediumDarkGrey,
|
||||
},
|
||||
}),
|
||||
SetupLanguageScreenStyle: StyleSheet.create({
|
||||
columnStyle: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-around',
|
||||
backgroundColor: Colors.White,
|
||||
maxHeight: Dimensions.get('window').height,
|
||||
},
|
||||
}),
|
||||
|
||||
ICON_SMALL_SIZE: 16,
|
||||
ICON_MID_SIZE: 22,
|
||||
PinIcon: require('../../../assets/pin_icon.png'),
|
||||
@@ -1209,7 +1248,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'),
|
||||
@@ -1227,14 +1266,13 @@ export const PurpleTheme = {
|
||||
InjiHomeLogo: require('../../../assets/inji-home-logo.png'),
|
||||
MagnifierZoom: require('../../../assets/magnifier-zoom.png'),
|
||||
HelpIcon: require('../../../assets/help-icon.png'),
|
||||
sharingIntro: require('../../../assets/Secure-Sharing.png'),
|
||||
sharingIntro: require('../../../assets/intro-secure-sharing.png'),
|
||||
walletIntro: require('../../../assets/intro-wallet-binding.png'),
|
||||
IntroScanner: require('../../../assets/intro-scanner.png'),
|
||||
injiSmallLogo: require('../../../assets/inji_small_logo.png'),
|
||||
protectPrivacy: require('../../../assets/phone_mockup_1.png'),
|
||||
protectPrivacy: require('../../../assets/intro-unlock-method.png'),
|
||||
NoInternetConnection: require('../../../assets/no-internet-connection.png'),
|
||||
SomethingWentWrong: require('../../../assets/something-went-wrong.png'),
|
||||
DigitIcon: require('../../../assets/digit-icon.png'),
|
||||
|
||||
elevation(level: ElevationLevel): ViewStyle {
|
||||
// https://ethercreative.github.io/react-native-shadow-generator/
|
||||
@@ -1280,17 +1318,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',
|
||||
};
|
||||
}
|
||||
|
||||
57
i18n.ts
57
i18n.ts
@@ -13,11 +13,9 @@ import Storage from './shared/storage';
|
||||
import {iso6393To1} from 'iso-639-3';
|
||||
import {LocalizedField} from './types/VC/ExistingMosipVC/vc';
|
||||
|
||||
import {APPLICATION_LANGUAGE} from 'react-native-dotenv';
|
||||
|
||||
const resources = {en, fil, ar, hi, kn, ta};
|
||||
const locale = Localization.locale;
|
||||
const languageCodeMap = {};
|
||||
const languageCodeMap = {} as {[key: string]: string};
|
||||
|
||||
export const SUPPORTED_LANGUAGES = {
|
||||
en: 'English',
|
||||
@@ -56,19 +54,32 @@ export function getLanguageCode(code: string) {
|
||||
return language;
|
||||
}
|
||||
|
||||
export function getVCDetailsForCurrentLanguage(locales) {
|
||||
export function getValueForCurrentLanguage(
|
||||
localizedData: LocalizedField[] | Object,
|
||||
defaultLanguage = '@none',
|
||||
) {
|
||||
const currentLanguage = i18next.language;
|
||||
const vcDetailsForCurrentLanguage = locales.filter(
|
||||
obj => obj.language === languageCodeMap[currentLanguage],
|
||||
);
|
||||
return vcDetailsForCurrentLanguage[0]?.value
|
||||
? vcDetailsForCurrentLanguage[0].value
|
||||
: locales[0]?.value;
|
||||
const currentLanguageCode = languageCodeMap[currentLanguage];
|
||||
if (Array.isArray(localizedData)) {
|
||||
const valueForCurrentLanguage = localizedData.filter(
|
||||
obj => obj.language === currentLanguageCode,
|
||||
);
|
||||
|
||||
return valueForCurrentLanguage[0]?.value
|
||||
? valueForCurrentLanguage[0].value
|
||||
: localizedData[0]?.value;
|
||||
} else {
|
||||
const localizedDataObject = localizedData as {[key: string]: string};
|
||||
|
||||
return localizedDataObject.hasOwnProperty(currentLanguageCode)
|
||||
? localizedDataObject[currentLanguageCode]
|
||||
: localizedDataObject[defaultLanguage];
|
||||
}
|
||||
}
|
||||
|
||||
// This method gets the value from iso-639-3 package, which contains key value pairs of three letter language codes[key] and two letter langugae code[value]. These values are according to iso standards.
|
||||
// The response received from the server is three letter language code and the value in the inji code base is two letter language code. Hence the conversion is done.
|
||||
function getThreeLetterLanguageCode(twoLetterLanguageCode) {
|
||||
function getThreeLetterLanguageCode(twoLetterLanguageCode: string) {
|
||||
return Object.keys(iso6393To1).find(
|
||||
key => iso6393To1[key] === twoLetterLanguageCode,
|
||||
);
|
||||
@@ -86,19 +97,33 @@ function populateLanguageCodeMap() {
|
||||
});
|
||||
}
|
||||
|
||||
export function getLocalizedField(rawField: string | LocalizedField[]) {
|
||||
export function getLocalizedField(
|
||||
rawField: string | LocalizedField[] | Object,
|
||||
) {
|
||||
if (typeof rawField === 'string') {
|
||||
return rawField;
|
||||
}
|
||||
|
||||
if (Array.isArray(rawField)) {
|
||||
try {
|
||||
if (rawField.length == 1) return rawField[0]?.value;
|
||||
return getValueForCurrentLanguage(rawField);
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const locales: LocalizedField[] = JSON.parse(JSON.stringify(rawField));
|
||||
if (locales.length == 1) return locales[0]?.value;
|
||||
return getVCDetailsForCurrentLanguage(locales);
|
||||
if (Object.keys(rawField).length === 1) {
|
||||
return Object.values(rawField)[0];
|
||||
}
|
||||
|
||||
return getValueForCurrentLanguage(rawField);
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function isTwoLetterLanguageCode(languageCode) {
|
||||
function isTwoLetterLanguageCode(languageCode: string) {
|
||||
return languageCode.length == 2;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ PODS:
|
||||
- AppAuth/ExternalUserAgent (1.6.2):
|
||||
- AppAuth/Core
|
||||
- ASN1Decoder (1.8.0)
|
||||
- BiometricSdk (0.5.4):
|
||||
- TensorFlowLiteObjC (= 2.12.0)
|
||||
- boost (1.76.0)
|
||||
- BVLinearGradient (2.8.2):
|
||||
- React-Core
|
||||
@@ -78,7 +80,8 @@ PODS:
|
||||
- MMKV (1.2.13):
|
||||
- MMKVCore (~> 1.2.13)
|
||||
- MMKVCore (1.2.16)
|
||||
- mosip-inji-face-sdk (0.1.12):
|
||||
- mosip-mobileid-sdk (0.1.0):
|
||||
- BiometricSdk (= 0.5.4)
|
||||
- React-Core
|
||||
- Permission-BluetoothPeripheral (3.8.4):
|
||||
- RNPermissions
|
||||
@@ -481,6 +484,13 @@ PODS:
|
||||
- React
|
||||
- RNSVG (13.4.0):
|
||||
- React-Core
|
||||
- TensorFlowLiteC (2.12.0):
|
||||
- TensorFlowLiteC/Core (= 2.12.0)
|
||||
- TensorFlowLiteC/Core (2.12.0)
|
||||
- TensorFlowLiteObjC (2.12.0):
|
||||
- TensorFlowLiteObjC/Core (= 2.12.0)
|
||||
- TensorFlowLiteObjC/Core (2.12.0):
|
||||
- TensorFlowLiteC (= 2.12.0)
|
||||
- Yoga (1.14.0)
|
||||
- ZXingObjC/Core (3.6.5)
|
||||
- ZXingObjC/OneD (3.6.5):
|
||||
@@ -516,7 +526,7 @@ DEPENDENCIES:
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
||||
- libevent (~> 2.1.12)
|
||||
- mosip-inji-face-sdk (from `../node_modules/mosip-inji-face-sdk`)
|
||||
- mosip-mobileid-sdk (from `../node_modules/mosip-mobileid-sdk`)
|
||||
- Permission-BluetoothPeripheral (from `../node_modules/react-native-permissions/ios/BluetoothPeripheral`)
|
||||
- Permission-Camera (from `../node_modules/react-native-permissions/ios/Camera`)
|
||||
- Permission-LocationAccuracy (from `../node_modules/react-native-permissions/ios/LocationAccuracy`)
|
||||
@@ -579,6 +589,7 @@ SPEC REPOS:
|
||||
trunk:
|
||||
- AppAuth
|
||||
- ASN1Decoder
|
||||
- BiometricSdk
|
||||
- CatCrypto
|
||||
- CrcSwift
|
||||
- fmt
|
||||
@@ -586,6 +597,8 @@ SPEC REPOS:
|
||||
- libevent
|
||||
- MMKV
|
||||
- MMKVCore
|
||||
- TensorFlowLiteC
|
||||
- TensorFlowLiteObjC
|
||||
- ZXingObjC
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
@@ -641,8 +654,8 @@ EXTERNAL SOURCES:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||
hermes-engine:
|
||||
:podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
|
||||
mosip-inji-face-sdk:
|
||||
:path: "../node_modules/mosip-inji-face-sdk"
|
||||
mosip-mobileid-sdk:
|
||||
:path: "../node_modules/mosip-mobileid-sdk"
|
||||
Permission-BluetoothPeripheral:
|
||||
:path: "../node_modules/react-native-permissions/ios/BluetoothPeripheral"
|
||||
Permission-Camera:
|
||||
@@ -759,6 +772,7 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
|
||||
ASN1Decoder: 6110fdeacfdb41559b1481457a1645be716610aa
|
||||
BiometricSdk: 1d16c395413164d92a280b78006abba4307063e6
|
||||
boost: 57d2868c099736d80fcd648bf211b4431e51a558
|
||||
BVLinearGradient: 916632041121a658c704df89d99f04acb038de0f
|
||||
CatCrypto: a477899b6be4954e75be4897e732da098cc0a5a8
|
||||
@@ -792,7 +806,7 @@ SPEC CHECKSUMS:
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
MMKV: aac95d817a100479445633f2b3ed8961b4ac5043
|
||||
MMKVCore: 9cfef4c48c6c46f66226fc2e4634d78490206a48
|
||||
mosip-inji-face-sdk: d5bc0fb66721c25450f92d3297efcb2cf0117271
|
||||
mosip-mobileid-sdk: 6b8182276896194fdcacdde148b02d5d2d16b02a
|
||||
Permission-BluetoothPeripheral: 2b88a131074edafd8a46a5cda4ba610ec986d2fb
|
||||
Permission-Camera: 7ec9ee99704766ff9b90198183387a7f5d82b0c1
|
||||
Permission-LocationAccuracy: a38ddb5c5d0b8e656f3c86e4a500f9bb88bc099d
|
||||
@@ -848,6 +862,8 @@ SPEC CHECKSUMS:
|
||||
RNScreens: 218801c16a2782546d30bd2026bb625c0302d70f
|
||||
RNSecureRandom: 07efbdf2cd99efe13497433668e54acd7df49fef
|
||||
RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2
|
||||
TensorFlowLiteC: 20785a69299185a379ba9852b6625f00afd7984a
|
||||
TensorFlowLiteObjC: 9a46a29a76661c513172cfffd3bf712b11ef25c3
|
||||
Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556
|
||||
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
export default async function faceAuth(capturedImage: string, vcImage: string) {
|
||||
// TODO: iOS implementation
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import { faceAuth } from 'mosip-inji-face-sdk';
|
||||
|
||||
export default faceAuth;
|
||||
@@ -11,7 +11,7 @@
|
||||
"VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "الواردة. فشل التحقق من التواجد",
|
||||
"PRESENCE_VERIFIED_AND_VC_SHARED": "التحقق منها ومشاركتها",
|
||||
"PRESENCE_VERIFICATION_FAILED": "فشل التحقق",
|
||||
"QRLOGIN_SUCCESFULL": "QRL تم تسجيل الدخول بنجاح",
|
||||
"QRLOGIN_SUCCESFULL": "QR تم تسجيل الدخول بنجاح",
|
||||
"WALLET_BINDING_SUCCESSFULL": "تفعيل ناجحة",
|
||||
"WALLET_BINDING_FAILURE": "فشل التفعيل",
|
||||
"VC_REMOVED": "تمت إزالته من المحفظة",
|
||||
@@ -159,13 +159,15 @@
|
||||
},
|
||||
"IssuersScreen": {
|
||||
"title": "أضف بطاقة جديدة",
|
||||
"header": "يرجى تحديد الطريقة المفضلة من الأسفل لإضافة بطاقة جديدة",
|
||||
"header": "يرجى اختيار جهة الإصدار المفضلة لديك من الخيارات أدناه لإضافة بطاقة جديدة.",
|
||||
"itemHeading": "التنزيل عبر {{issuer}}",
|
||||
"itemSubHeading": "أدخل رقم الهوية الوطنية الخاص بك لتنزيل بطاقتك.",
|
||||
"loaders": {
|
||||
"loading": "جار التحميل...",
|
||||
"subTitle": {
|
||||
"displayIssuers": "Fetching Issuers",
|
||||
"settingUp": "Setting up",
|
||||
"downloadingCredentials": "Downloading Credentials",
|
||||
"displayIssuers": "جلب جهات الإصدار",
|
||||
"settingUp": "اعداد",
|
||||
"downloadingCredentials": "تنزيل بيانات الاعتماد"
|
||||
}
|
||||
},
|
||||
"errors":{
|
||||
@@ -202,6 +204,12 @@
|
||||
},
|
||||
"AddVcModal": {
|
||||
"requestingCredential": "جارٍ طلب بيانات الاعتماد...",
|
||||
"confirmationDialog": {
|
||||
"title": "هل تريد إلغاء التنزيل؟",
|
||||
"message": "بمجرد الإلغاء، لن يتم تنزيل بطاقتك وستحتاج إلى إعادة بدء التنزيل.",
|
||||
"wait": "لا، سأنتظر",
|
||||
"cancel": "نعم، إلغاء"
|
||||
},
|
||||
"errors": {
|
||||
"input": {
|
||||
"empty": "فارغًا",
|
||||
@@ -297,6 +305,10 @@
|
||||
"title": "لا يوجد اتصال بالإنترنت",
|
||||
"message": "الرجاء التحقق من اتصالك وإعادة المحاولة"
|
||||
},
|
||||
"downloadLimitExpires":{
|
||||
"title": "الخطأ تحميل",
|
||||
"message": "حدثت مشكلة أثناء تنزيل البطاقات التالية. حاول مرة اخرى"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OnboardingOverlay": {
|
||||
@@ -353,12 +365,7 @@
|
||||
"confirmPasscode": "قم بتأكيد رمز المرور",
|
||||
"enterPasscode": "أدخل رمز المرور الخاص"
|
||||
},
|
||||
"AppMetaData": {
|
||||
"header": "حول إنجي",
|
||||
"version": "الإصدار",
|
||||
"useBle": "مدعوم من BLE"
|
||||
},
|
||||
"QrScreen": {
|
||||
"QrLogin": {
|
||||
"title": "QR تسجيل الدخول",
|
||||
"alignQr": "قم بمحاذاة رمز الاستجابة السريعة داخل الإطار للمسح الضوئي",
|
||||
"confirmation": "تأكيد",
|
||||
@@ -375,8 +382,8 @@
|
||||
"domainWarning": "يرجى تأكيد مجال موقع الويب الذي تقوم بمسح رمز الاستجابة السريعة منه على النحو التالي",
|
||||
"access": " يطلب الوصول إلى",
|
||||
"status": "حالة",
|
||||
"successMessage": "لقد قمت بتسجيل الدخول بنجاح ",
|
||||
"okay": "تمام",
|
||||
"successMessage": "لقد تم تسجيل دخولك بنجاح ",
|
||||
"ok": "نعم",
|
||||
"allow": "يسمح",
|
||||
"cancel": "يلغي",
|
||||
"essentialClaims": "الادعاءات الأساسية",
|
||||
@@ -457,7 +464,7 @@
|
||||
},
|
||||
"ScanScreen": {
|
||||
"header": "مسح رمز الاستجابة السريعة",
|
||||
"noShareableVcs": "لا تتوفر بطاقات قابلة للمشاركة.",
|
||||
"noShareableVcs": "لا تتوفر بطاقات قابلة للمشاركة",
|
||||
"bluetoothStateAndroid": "يرجى تشغيل البلوتوث من الإعدادات السريعة لدعم المشاركة المحلية",
|
||||
"bluetoothStateIos": "يرجى تشغيل البلوتوث من مركز التحكم لدعم المشاركة المحلية",
|
||||
"enableBluetoothMessage": "يرجى تمكين أذونات البلوتوث لدعم المشاركة المحلية",
|
||||
@@ -560,8 +567,7 @@
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "حل هوية مفتوحة المصدر",
|
||||
"getStarted": "البدء",
|
||||
"unlockApp": "فتح التطبيق",
|
||||
"unlockApplication": "فتح التطبيق",
|
||||
"failedToReadKeys": "فشلت قراءة المفاتيح",
|
||||
"retryRead": "هل تريد إعادة المحاولة؟",
|
||||
"errors": {
|
||||
|
||||
@@ -160,13 +160,9 @@
|
||||
},
|
||||
"IssuersScreen": {
|
||||
"title": "Add new card",
|
||||
"header": "Please select a preferred method from below to add a new card",
|
||||
"header": "Please choose your preferred issuer from the options below to add a new card.",
|
||||
"itemHeading": "Download via {{issuer}}",
|
||||
"itemSubHeading": "Enter the mentioned ID and get your card",
|
||||
"modal": {
|
||||
"title": "In Progress",
|
||||
"hint": "downloading your credential from issuer"
|
||||
},
|
||||
"itemSubHeading": "Enter your national ID to download your card.",
|
||||
"loaders": {
|
||||
"loading": "Loading...",
|
||||
"subTitle": {
|
||||
@@ -209,6 +205,12 @@
|
||||
},
|
||||
"AddVcModal": {
|
||||
"requestingCredential": "Requesting credential...",
|
||||
"confirmationDialog": {
|
||||
"title": "Do you want to cancel downloading?",
|
||||
"message": "Once cancelled, your card will not be downloaded and you need to reinitiate the download.",
|
||||
"wait": "No, I’ll wait",
|
||||
"cancel": "Yes, Cancel"
|
||||
},
|
||||
"errors": {
|
||||
"input": {
|
||||
"empty": "The input cannot be empty",
|
||||
@@ -303,6 +305,10 @@
|
||||
"noInternetConnection": {
|
||||
"title": "No internet connection",
|
||||
"message": "Please check your connection and retry"
|
||||
},
|
||||
"downloadLimitExpires":{
|
||||
"title": "Download Error",
|
||||
"message": "There was an issue downloading following cards. Please try again"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -360,12 +366,7 @@
|
||||
"confirmPasscode": "Confirm passcode",
|
||||
"enterPasscode": "Enter your passcode"
|
||||
},
|
||||
"AppMetaData": {
|
||||
"header": "About Inji",
|
||||
"version": "Version",
|
||||
"useBle": "Powered by BLE"
|
||||
},
|
||||
"QrScreen": {
|
||||
"QrLogin": {
|
||||
"title": "QR Login",
|
||||
"alignQr": "Align the QR code within the frame to scan",
|
||||
"confirmation": "Confirmation",
|
||||
@@ -382,8 +383,8 @@
|
||||
"domainWarning": "Please confirm the domain of the website you are scanning the QR code from below",
|
||||
"access": " is requesting access to",
|
||||
"status": "Status",
|
||||
"successMessage": "You are successfully logged in ",
|
||||
"okay": "All right",
|
||||
"successMessage": "You are successfully logged in to ",
|
||||
"ok": "OK",
|
||||
"allow": "Allow",
|
||||
"cancel": "Cancel",
|
||||
"essentialClaims": "Important Claims",
|
||||
@@ -464,7 +465,7 @@
|
||||
},
|
||||
"ScanScreen": {
|
||||
"header": "Scan QR Code",
|
||||
"noShareableVcs": "No shareable card are available.",
|
||||
"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",
|
||||
@@ -567,18 +568,17 @@
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "Open Source Identity Solution",
|
||||
"getStarted": "Get started",
|
||||
"unlockApp": "Unlock application",
|
||||
"unlockApplication": "Unlock Application",
|
||||
"failedToReadKeys": "Failed to read keys",
|
||||
"retryRead": "Want to retry?",
|
||||
"ignore": "Ignore",
|
||||
"errors": {
|
||||
"decryptionFailed": "Failed to decrypt data",
|
||||
"invalidateKeyError": {
|
||||
"title": "App was Reset",
|
||||
"message": "Due to the fingerprint / facial recognition update, app security was impacted, and downloaded cards were removed. Please download again."
|
||||
}
|
||||
}
|
||||
},
|
||||
"ignore": "Ignore"
|
||||
},
|
||||
"SetupLanguage": {
|
||||
"header": "Choose Language",
|
||||
|
||||
@@ -158,13 +158,15 @@
|
||||
},
|
||||
"IssuersScreen": {
|
||||
"title": "Magdagdag ng bagong card",
|
||||
"header": "Mangyaring pumili ng gustong paraan mula sa ibaba upang magdagdag ng bagong card",
|
||||
"header": "Mangyaring piliin ang iyong gustong tagabigay mula sa mga opsyon sa ibaba upang magdagdag ng bagong card.",
|
||||
"itemHeading": "I-download sa pamamagitan ng {{issuer}}",
|
||||
"itemSubHeading": "Ilagay ang iyong national ID para i-download ang iyong card.",
|
||||
"loaders": {
|
||||
"loading": "Naglo-load...",
|
||||
"subTitle": {
|
||||
"displayIssuers": "Fetching Issuers",
|
||||
"settingUp": "Setting up",
|
||||
"downloadingCredentials": "Downloading Credentials",
|
||||
"displayIssuers": "Kinukuha ang mga Isyu",
|
||||
"settingUp": "Inaayos",
|
||||
"downloadingCredentials": "Nagda-download ng Mga Kredensyal"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
@@ -201,6 +203,12 @@
|
||||
},
|
||||
"AddVcModal": {
|
||||
"requestingCredential": "Humihiling ng kredensyal...",
|
||||
"confirmationDialog": {
|
||||
"title": "Gusto mo bang kanselahin ang pag-download?",
|
||||
"message": "Kapag nakansela, hindi na mada-download ang iyong card at kailangan mong simulan muli ang pag-download.",
|
||||
"wait": "Hindi, maghihintay ako",
|
||||
"cancel": "Oo, Kanselahin"
|
||||
},
|
||||
"errors": {
|
||||
"input": {
|
||||
"empty": "Hindi maaaring walang laman ang input",
|
||||
@@ -295,6 +303,10 @@
|
||||
"noInternetConnection": {
|
||||
"title": "Pakisuri ang iyong koneksyon at subukang muli",
|
||||
"message": "Mangyaring kumonekta sa internet at subukang muli."
|
||||
},
|
||||
"downloadLimitExpires":{
|
||||
"title": "Error sa Pag-download",
|
||||
"message": "Nagkaroon ng isyu sa pag-download ng mga sumusunod na card. Pakisubukang muli"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -352,12 +364,7 @@
|
||||
"confirmPasscode": "Kumpirmahin ang passcode",
|
||||
"enterPasscode": "Ilagay ang iyong passcode"
|
||||
},
|
||||
"AppMetaData": {
|
||||
"header": "Tungkol kay Inji",
|
||||
"version": "Bersyon",
|
||||
"useBle": "Pinapatakbo ng BLE"
|
||||
},
|
||||
"QrScreen": {
|
||||
"QrLogin": {
|
||||
"title": "QR Login",
|
||||
"alignQr": "I-align ang QR code sa loob ng frame para i-scan",
|
||||
"confirmation": "Kumpirmasyon",
|
||||
@@ -374,8 +381,8 @@
|
||||
"domainWarning": "Pakikumpirma ang domain ng website kung saan mo ini-scan ang QR code mula sa ibaba",
|
||||
"access": " ay humihiling ng access sa",
|
||||
"status": "Katayuan",
|
||||
"successMessage": "Ikaw ay Matagumpay na Naka-log In ",
|
||||
"okay": "Sige",
|
||||
"successMessage": "Matagumpay kang naka-log in sa ",
|
||||
"ok": "OK",
|
||||
"allow": "Payagan",
|
||||
"cancel": "Kanselahin",
|
||||
"essentialClaims": "Mahahalagang Claim",
|
||||
@@ -460,7 +467,7 @@
|
||||
},
|
||||
"ScanScreen": {
|
||||
"header": "I-scan ang QR Code",
|
||||
"noShareableVcs": "Walang magagamit na maibabahaging card..",
|
||||
"noShareableVcs": "Walang magagamit na mga card na maibabahagi.",
|
||||
"sharingVc": "Pagbabahagi ng card",
|
||||
"bluetoothStateIos": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",
|
||||
"bluetoothStateAndroid": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",
|
||||
@@ -563,8 +570,7 @@
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "Open Source Identity Solution",
|
||||
"getStarted": "Magsimula",
|
||||
"unlockApp": "Buksan ang aplikasyon",
|
||||
"unlockApplication": "I-unlock ang Application",
|
||||
"failedToReadKeys": "Nabigong basahin ang mga susi",
|
||||
"retryRead": "Gustong subukang muli?",
|
||||
"errors": {
|
||||
|
||||
@@ -156,8 +156,9 @@
|
||||
},
|
||||
"IssuersScreen": {
|
||||
"title": "नया कार्ड जोड़ें",
|
||||
"header": "नया कार्ड जोड़ने के लिए कृपया नीचे से कोई पसंदीदा विधि चुनें",
|
||||
|
||||
"header": "नया कार्ड जोड़ने के लिए कृपया नीचे दिए गए विकल्पों में से अपना पसंदीदा जारीकर्ता चुनें।",
|
||||
"itemHeading": "{{issuer}} के माध्यम से डाउनलोड करें",
|
||||
"itemSubHeading": "अपना कार्ड डाउनलोड करने के लिए अपनी राष्ट्रीय आईडी दर्ज करें।",
|
||||
"loaders": {
|
||||
"loading": "लोड हो रहा है...",
|
||||
"subTitle": {
|
||||
@@ -200,6 +201,12 @@
|
||||
},
|
||||
"AddVcModal": {
|
||||
"requestingCredential": "क्रेडेंशियल का अनुरोध कर रहा है...",
|
||||
"confirmationDialog": {
|
||||
"title": "क्या आप डाउनलोडिंग रद्द करना चाहते हैं?",
|
||||
"message": "एक बार रद्द होने पर, आपका कार्ड डाउनलोड नहीं किया जाएगा और आपको डाउनलोड फिर से शुरू करना होगा।",
|
||||
"wait": "नहीं, मैं इंतजार करूंगा",
|
||||
"cancel": "हाँ, रद्द करें"
|
||||
},
|
||||
"errors": {
|
||||
"input": {
|
||||
"empty": "इनपुट खाली नहीं हो सकता",
|
||||
@@ -296,6 +303,10 @@
|
||||
"title": "कोई इंटरनेट कनेक्शन नहीं",
|
||||
"message": "कृपया अपना कनेक्शन जांचें और पुनः प्रयास करें"
|
||||
},
|
||||
"downloadLimitExpires":{
|
||||
"title": "डाउनलोड त्रुटि",
|
||||
"message": "निम्नलिखित कार्ड डाउनलोड करने में एक समस्या थी। कृपया पुन: प्रयास करें"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OnboardingOverlay": {
|
||||
@@ -307,7 +318,7 @@
|
||||
"stepThreeText": "परेशानी मुक्त तरीके से अपने कार्ड सुरक्षित रूप से साझा करें और विभिन्न सेवाओं का लाभ उठाएं।",
|
||||
"stepFourTitle": "परेशानी मुक्त प्रमाणीकरण",
|
||||
"stepFourText": "संग्रहीत डिजिटल क्रेडेंशियल का उपयोग करके आसानी से स्वयं को प्रमाणित करें।",
|
||||
"getStarted": "शुरू करें",
|
||||
"getStarted": "शुरू हो जाओ",
|
||||
"goBack": "वापस जाओ",
|
||||
"back": "पीछे",
|
||||
"skip": "छोडना",
|
||||
@@ -352,12 +363,7 @@
|
||||
"confirmPasscode": "पासकोड की पुष्टि करें",
|
||||
"enterPasscode": "अपना पासकोड प्रविष्ट करें"
|
||||
},
|
||||
"AppMetaData": {
|
||||
"header": "इंजी के बारे में",
|
||||
"version": "संस्करण",
|
||||
"useBle": "BLE द्वारा संचालित"
|
||||
},
|
||||
"QrScreen": {
|
||||
"QrLogin": {
|
||||
"title": "क्यूआर लॉगिन",
|
||||
"alignQr": "स्कैन करने के लिए फ्रेम के भीतर क्यूआर कोड को संरेखित करें",
|
||||
"confirmation": "पुष्टीकरण",
|
||||
@@ -374,8 +380,8 @@
|
||||
"domainWarning": "कृपया उस वेबसाइट के डोमेन की पुष्टि करें जिसे आप नीचे दिए गए क्यूआर कोड से स्कैन कर रहे हैं",
|
||||
"access": " तक पहुंच का अनुरोध कर रहा है",
|
||||
"status": "दर्जा",
|
||||
"successMessage": "आपने सफलतापूर्वक लॉग इन कर लिया है ",
|
||||
"okay": "ठीक",
|
||||
"successMessage": "आप सफलतापूर्वक लॉग इन हो गए हैं ",
|
||||
"ok": "ठीक है",
|
||||
"allow": "अनुमति देना",
|
||||
"cancel": "रद्द करना",
|
||||
"essentialClaims": "आवश्यक दावे",
|
||||
@@ -458,7 +464,7 @@
|
||||
},
|
||||
"ScanScreen": {
|
||||
"header": "स्कैन क्यू आर कोड",
|
||||
"noShareableVcs": "कोई साझा करने योग्य कार्ड उपलब्ध नहीं है।",
|
||||
"noShareableVcs": "कोई साझा करने योग्य कार्ड उपलब्ध नहीं हैं।",
|
||||
"sharingVc": "कार्ड साझा करना",
|
||||
"bluetoothStateIos": "ब्लूटूथ बंद है, कृपया इसे नियंत्रण केंद्र से चालू करें",
|
||||
"bluetoothStateAndroid": "ब्लूटूथ बंद है, कृपया इसे त्वरित सेटिंग मेनू से चालू करें",
|
||||
@@ -561,8 +567,7 @@
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "ओपन सोर्स आइडेंटिटी सॉल्यूशन",
|
||||
"getStarted": "आरंभ करें",
|
||||
"unlockApp": "एप्लिकेशन अनलॉक करें",
|
||||
"unlockApplication": "एप्लिकेशन अनलॉक करें",
|
||||
"failedToReadKeys": "कुंजियाँ पढ़ने में विफल",
|
||||
"retryRead": "पुनः प्रयास करना चाहते हैं?",
|
||||
"errors": {
|
||||
|
||||
@@ -155,13 +155,15 @@
|
||||
},
|
||||
"IssuersScreen": {
|
||||
"title": "ಹೊಸ ಕಾರ್ಡ್ ಸೇರಿಸಿ",
|
||||
"header": "ದಯವಿಟ್ಟು ಹೊಸ ಕಾರ್ಡ್ ಸೇರಿಸಲು ಕೆಳಗಿನಿಂದ ಆದ್ಯತೆಯ ವಿಧಾನವನ್ನು ಆಯ್ಕೆಮಾಡಿ",
|
||||
"header": "ದಯವಿಟ್ಟು ಹೊಸ ಕಾರ್ಡ್ ಸೇರಿಸಲು ಕೆಳಗಿನ ಆಯ್ಕೆಗಳಿಂದ ನಿಮ್ಮ ಆದ್ಯತೆ ನೀಡುವವರನ್ನು ಆಯ್ಕೆಮಾಡಿ.",
|
||||
"itemHeading": "{{issuer}} ಮೂಲಕ ಡೌನ್ಲೋಡ್ ಮಾಡಿ",
|
||||
"itemSubHeading": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲು ನಿಮ್ಮ ರಾಷ್ಟ್ರೀಯ ID ಅನ್ನು ನಮೂದಿಸಿ.",
|
||||
"loaders": {
|
||||
"loading": "ಲೋಡ್ ಆಗುತ್ತಿದೆ...",
|
||||
"subTitle": {
|
||||
"displayIssuers": "Fetching Issuers",
|
||||
"settingUp": "Setting up",
|
||||
"downloadingCredentials": "Downloading Credentials"
|
||||
"displayIssuers": "ವಿತರಕರನ್ನು ಪಡೆಯಲಾಗುತ್ತಿದೆ",
|
||||
"settingUp": "ಸ್ಥಾಪನೆಗೆ",
|
||||
"downloadingCredentials": "ರುಜುವಾತುಗಳನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
@@ -198,6 +200,12 @@
|
||||
},
|
||||
"AddVcModal": {
|
||||
"requestingCredential": "ರುಜುವಾತುಗಳನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ...",
|
||||
"confirmationDialog": {
|
||||
"title": "ನೀವು ಡೌನ್ಲೋಡ್ ಮಾಡುವುದನ್ನು ರದ್ದುಗೊಳಿಸಲು ಬಯಸುವಿರಾ?",
|
||||
"message": "ಒಮ್ಮೆ ರದ್ದುಗೊಳಿಸಿದರೆ, ನಿಮ್ಮ ಕಾರ್ಡ್ ಡೌನ್ಲೋಡ್ ಆಗುವುದಿಲ್ಲ ಮತ್ತು ನೀವು ಡೌನ್ಲೋಡ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬೇಕಾಗುತ್ತದೆ.",
|
||||
"wait": "ಇಲ್ಲ, ನಾನು ಕಾಯುತ್ತೇನೆ",
|
||||
"cancel": "ಹೌದು, ರದ್ದುಮಾಡಿ"
|
||||
},
|
||||
"errors": {
|
||||
"input": {
|
||||
"empty": "ಇನ್ಪುಟ್ ಖಾಲಿ ಇರುವಂತಿಲ್ಲ",
|
||||
@@ -293,6 +301,10 @@
|
||||
"title": "ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವಿಲ್ಲ",
|
||||
"message": "ದಯವಿಟ್ಟು ನಿಮ್ಮ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಮರುಪ್ರಯತ್ನಿಸಿ"
|
||||
},
|
||||
"downloadLimitExpires":{
|
||||
"title": "ಡೌನ್ಲೋಡ್ ದೋಷ",
|
||||
"message": "ಕೆಳಗಿನ ಕಾರ್ಡ್ಗಳನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ಸಮಸ್ಯೆ ಕಂಡುಬಂದಿದೆ. ದಯವಿಟ್ಟು ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OnboardingOverlay": {
|
||||
@@ -336,8 +348,8 @@
|
||||
}
|
||||
},
|
||||
"MainLayout": {
|
||||
"home": "ಲೇಔಟ್",
|
||||
"scan": "ಮನೆ",
|
||||
"home": "ಮನೆ",
|
||||
"scan": "ಸ್ಕ್ಯಾನ್",
|
||||
"history": "ಇತಿಹಾಸ",
|
||||
"request": "ವಿನಂತಿ",
|
||||
"settings": "ಸೆಟ್ಟಿಂಗ್ಗಳು"
|
||||
@@ -349,12 +361,7 @@
|
||||
"confirmPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ಅನ್ನು ದೃಢೀಕರಿಸಿ",
|
||||
"enterPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ನಮೂದಿಸಿ"
|
||||
},
|
||||
"AppMetaData": {
|
||||
"header": "ಇಂಜಿ ಬಗ್ಗೆ",
|
||||
"version": "ಆವೃತ್ತಿ",
|
||||
"useBle": "BLE ನಿಂದ ನಡೆಸಲ್ಪಡುತ್ತಿದೆ"
|
||||
},
|
||||
"QrScreen": {
|
||||
"QrLogin": {
|
||||
"title": "QR ಲಾಗಿನ್",
|
||||
"alignQr": "ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಚೌಕಟ್ಟಿನೊಳಗೆ QR ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ",
|
||||
"confirmation": "ದೃಢೀಕರಣ",
|
||||
@@ -372,7 +379,7 @@
|
||||
"access": " ಗೆ ಪ್ರವೇಶವನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ",
|
||||
"status": "ಸ್ಥಿತಿ",
|
||||
"successMessage": "ನೀವು ಯಶಸ್ವಿಯಾಗಿ ಲಾಗ್ ಇನ್ ಆಗಿರುವಿರಿ ",
|
||||
"okay": "ಸರಿ",
|
||||
"ok": "ಸರಿ",
|
||||
"allow": "ಅನುಮತಿಸಿ",
|
||||
"cancel": "ರದ್ದುಮಾಡು",
|
||||
"essentialClaims": "ಅಗತ್ಯ ಹಕ್ಕುಗಳು",
|
||||
@@ -455,7 +462,7 @@
|
||||
},
|
||||
"ScanScreen": {
|
||||
"header": "QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ",
|
||||
"noShareableVcs": "ಯಾವುದೇ ಹಂಚಿಕೊಳ್ಳಬಹುದಾದ ಕಾರ್ಡ್ ಲಭ್ಯವಿಲ್ಲ.",
|
||||
"noShareableVcs": "ಹಂಚಿಕೊಳ್ಳಬಹುದಾದ ಯಾವುದೇ ಕಾರ್ಡ್ಗಳು ಲಭ್ಯವಿಲ್ಲ.",
|
||||
"sharingVc": "ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ",
|
||||
"bluetoothStateIos": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ಅದನ್ನು ನಿಯಂತ್ರಣ ಕೇಂದ್ರದಿಂದ ಆನ್ ಮಾಡಿ",
|
||||
"bluetoothStateAndroid": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳ ಮೆನುವಿನಿಂದ ಅದನ್ನು ಆನ್ ಮಾಡಿ",
|
||||
@@ -558,8 +565,7 @@
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "ಓಪನ್ ಸೋರ್ಸ್ ಐಡೆಂಟಿಟಿ ಸೊಲ್ಯೂಷನ್",
|
||||
"getStarted": "ಪ್ರಾರಂಭಿಸಿ",
|
||||
"unlockApp": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಿ",
|
||||
"unlockApplication": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಿ",
|
||||
"failedToReadKeys": "ಕೀಗಳನ್ನು ಓದಲು ವಿಫಲವಾಗಿದೆ",
|
||||
"retryRead": "ಮರುಪ್ರಯತ್ನಿಸಲು ಬಯಸುವಿರಾ?",
|
||||
"errors": {
|
||||
|
||||
@@ -117,6 +117,12 @@
|
||||
},
|
||||
"AddVcModal": {
|
||||
"requestingCredential": "Solicitando credencial...",
|
||||
"confirmationDialog": {
|
||||
"title": "Quieres cancelar la descarga?",
|
||||
"message": "OUna vez cancelada, su tarjeta no se descargará y deberá reiniciar la descarga.",
|
||||
"wait": "No, esperaré",
|
||||
"cancel": "Sí, cancelar"
|
||||
},
|
||||
"errors": {
|
||||
"input": {
|
||||
"empty": "El campo no puede estar vacío",
|
||||
@@ -206,6 +212,10 @@
|
||||
"title": "Sin conexión a Internet",
|
||||
"message": "Por favor verifique su conexión y vuelva a intentarlo"
|
||||
},
|
||||
"downloadLimitExpires":{
|
||||
"title": "Error de descarga",
|
||||
"message": "Hubo un problema al descargar las siguientes tarjetas. Inténtalo de nuevo"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OnboardingOverlay": {
|
||||
@@ -250,11 +260,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",
|
||||
@@ -267,7 +272,31 @@
|
||||
"logout": "Cerrar sesión",
|
||||
"resetInjiProps": "Restableciendo accesorios Inji..."
|
||||
},
|
||||
"QrScreen": {
|
||||
"IssuersScreen": {
|
||||
"title": "Agregar nueva tarjeta",
|
||||
"header": "Elija su emisor preferido entre las opciones siguientes para agregar una nueva tarjeta.",
|
||||
"itemHeading": "Descargar vía {{issuer}}",
|
||||
"itemSubHeading": "Introduce tu DNI para descargar tu tarjeta.",
|
||||
"loaders": {
|
||||
"loading": "Cargando...",
|
||||
"subTitle": {
|
||||
"displayIssuers": "Obteniendo emisores",
|
||||
"settingUp": "Configurando",
|
||||
"downloadingCredentials": "Descarga de credenciales"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"noInternetConnection": {
|
||||
"title": "Sin conexión a Internet",
|
||||
"message": "Por favor verifique su conexión y vuelva a intentarlo"
|
||||
},
|
||||
"generic": {
|
||||
"title": "¡Algo salió mal!",
|
||||
"message": "Estamos teniendo algunos problemas con su solicitud. Inténtalo de nuevo."
|
||||
}
|
||||
}
|
||||
},
|
||||
"QrLogin": {
|
||||
"title": "Inicio de sesión con código QR",
|
||||
"alignQr": "Alinea el código QR dentro del marco para escanearlo",
|
||||
"confirmation": "Confirmación",
|
||||
@@ -285,7 +314,7 @@
|
||||
"access": "está solicitando acceso a",
|
||||
"status": "Estado",
|
||||
"successMessage": "Has iniciado sesión correctamente en",
|
||||
"okay": "Aceptar",
|
||||
"ok": "Aceptar",
|
||||
"allow": "Permitir",
|
||||
"cancel": "Cancelar",
|
||||
"essentialClaims": "Reclamos Esenciales",
|
||||
@@ -453,14 +482,16 @@
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "Solución de identidad de código abierto",
|
||||
"getStarted": "Empezar",
|
||||
"unlockApp": "Desbloquear aplicación",
|
||||
"unlockApplication": "Desbloquear aplicación",
|
||||
"failedToReadKeys": "No se pudieron leer las claves",
|
||||
"retryRead": "¿Quieres volver a intentarlo?",
|
||||
"errors": {
|
||||
"invalidateKeyError": {
|
||||
"title": "La aplicación se restableció",
|
||||
"message": "Debido a la actualización de reconocimiento facial/huella digital, la seguridad de la aplicación se vio afectada y se eliminaron las tarjetas descargadas. Por favor descargue nuevamente."
|
||||
}
|
||||
}
|
||||
},
|
||||
"ignore": "Ignorar"
|
||||
},
|
||||
"common": {
|
||||
"cancel": "Cancelar",
|
||||
@@ -728,11 +759,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",
|
||||
@@ -757,7 +783,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"QrScreen": {
|
||||
"QrLogin": {
|
||||
"title": "Inicio de sesión con código QR",
|
||||
"alignQr": "Alinea el código QR dentro del marco para escanearlo",
|
||||
"confirmation": "Confirmación",
|
||||
@@ -774,8 +800,8 @@
|
||||
"domainWarning": "Por favor, confirma que el dominio del sitio web desde el cual estás escaneando el código QR es el siguiente",
|
||||
"access": "está solicitando acceso a",
|
||||
"status": "Estado",
|
||||
"successMessage": "Has iniciado sesión correctamente en",
|
||||
"okay": "Aceptar",
|
||||
"successMessage": "Has iniciado sesión correctamente en ",
|
||||
"okay": "De acuerdo",
|
||||
"allow": "Permitir",
|
||||
"cancel": "Cancelar",
|
||||
"essentialClaims": "Reclamos Esenciales",
|
||||
@@ -936,17 +962,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "Solución de identidad de código abierto",
|
||||
"getStarted": "Empezar",
|
||||
"unlockApp": "Desbloquear aplicación",
|
||||
"errors": {
|
||||
"invalidateKeyError": {
|
||||
"title": "Algunas pruebas de identidad se eliminan debido a problemas de seguridad.",
|
||||
"message": "Vuelva a descargar."
|
||||
}
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"cancel": "Cancelar",
|
||||
"save": "Guardar",
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"idType": "ஐடி வகை",
|
||||
"id": "ஐடி",
|
||||
"qrCodeHeader": "க்யு ஆர் குறியீடு",
|
||||
"nationalCard": "தேசிய அட்டை್",
|
||||
"nationalCard": "தேசிய அட்டை",
|
||||
"uin": "UIN",
|
||||
"vid": "VID",
|
||||
"enableVerification": "செயல்படுத்த",
|
||||
@@ -155,13 +155,15 @@
|
||||
},
|
||||
"IssuersScreen": {
|
||||
"title": "புதிய அட்டையைச் சேர்க்கவும்",
|
||||
"header": "புதிய கார்டைச் சேர்க்க கீழே இருந்து விருப்பமான முறையைத் தேர்ந்தெடுக்கவும்",
|
||||
"header": "புதிய கார்டைச் சேர்க்க, கீழே உள்ள விருப்பங்களிலிருந்து உங்களுக்கு விருப்பமான வழங்குபவரைத் தேர்ந்தெடுக்கவும்.",
|
||||
"itemHeading": "{{issuer}} மூலம் பதிவிறக்கவும்",
|
||||
"itemSubHeading": "உங்கள் கார்டைப் பதிவிறக்க உங்கள் தேசிய ஐடியை உள்ளிடவும்.",
|
||||
"loaders": {
|
||||
"loading": "ஏற்றுகிறது...",
|
||||
"subTitle": {
|
||||
"displayIssuers": "Fetching Issuers",
|
||||
"settingUp": "Setting up",
|
||||
"downloadingCredentials": "Downloading Credentials",
|
||||
"displayIssuers": "வழங்குபவர்களைப் பெறுதல்",
|
||||
"settingUp": "அமைக்கிறது",
|
||||
"downloadingCredentials": "நற்சான்றிதழ்களைப் பதிவிறக்குகிறது"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
@@ -198,6 +200,12 @@
|
||||
},
|
||||
"AddVcModal": {
|
||||
"requestingCredential": "நற்சான்றிதழைக் கோருகிறது...",
|
||||
"confirmationDialog": {
|
||||
"title": "பதிவிறக்குவதை ரத்துசெய்ய விரும்புகிறீர்களா?",
|
||||
"message": "ரத்துசெய்யப்பட்டதும், உங்கள் கார்டு பதிவிறக்கம் செய்யப்படாது மேலும் நீங்கள் பதிவிறக்கத்தை மீண்டும் தொடங்க வேண்டும்.",
|
||||
"wait": "இல்லை, நான் காத்திருப்பேன்",
|
||||
"cancel": "ஆம், ரத்துசெய்"
|
||||
},
|
||||
"errors": {
|
||||
"input": {
|
||||
"empty": "உள்ளீடு காலியாக இருக்க முடியாது",
|
||||
@@ -292,6 +300,10 @@
|
||||
"noInternetConnection": {
|
||||
"title": "இணைய இணைப்பு இல்லை",
|
||||
"message": "உங்கள் இணைப்பைச் சரிபார்த்து மீண்டும் முயற்சிக்கவும்"
|
||||
},
|
||||
"downloadLimitExpires":{
|
||||
"title": "பதிவிறக்கப் பிழை",
|
||||
"message": "பின்வரும் கார்டுகளைப் பதிவிறக்குவதில் சிக்கல் ஏற்பட்டது. தயவு செய்து மீண்டும் முயற்சிக்கவும்"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -304,7 +316,7 @@
|
||||
"stepThreeText": "தொந்தரவு இல்லாத வகையில் உங்கள் கார்டுகளைப் பாதுகாப்பாகப் பகிர்ந்து, பல்வேறு சேவைகளைப் பெறுங்கள்.",
|
||||
"stepFourTitle": "தொந்தரவு இல்லாத அங்கீகாரம்",
|
||||
"stepFourText": "சேமிக்கப்பட்ட டிஜிட்டல் நற்சான்றிதழைப் பயன்படுத்தி உங்களை எளிதாக அங்கீகரிக்கவும்.",
|
||||
"getStarted": "தொடங்குங்கள்",
|
||||
"getStarted": "தொடங்கு",
|
||||
"goBack": "திரும்பி போ",
|
||||
"back": "மீண்டும்",
|
||||
"skip": "தவிர்க்கவும்",
|
||||
@@ -349,12 +361,7 @@
|
||||
"confirmPasscode": "கடவுக்குறியீட்டை உறுதிப்படுத்தவும்",
|
||||
"enterPasscode": "உங்கள் கடவுக்குறியீட்டை உள்ளிடவும்"
|
||||
},
|
||||
"AppMetaData": {
|
||||
"header": "இன்ஜி பற்றி",
|
||||
"version": "பதிப்பு",
|
||||
"useBle": "BLE ஆல் இயக்கப்படுகிறது"
|
||||
},
|
||||
"QrScreen": {
|
||||
"QrLogin": {
|
||||
"title": "QR உள்நுழைவு",
|
||||
"alignQr": "ஸ்கேன் செய்ய ஃப்ரேமுக்குள் QR குறியீட்டை சீரமைக்கவும்",
|
||||
"confirmation": "உறுதிப்படுத்தல்",
|
||||
@@ -372,7 +379,7 @@
|
||||
"access": " அணுகலைக் கோருகிறது",
|
||||
"status": "நிலை",
|
||||
"successMessage": "நீங்கள் வெற்றிகரமாக உள்நுழைந்துள்ளீர்கள் ",
|
||||
"okay": "சரி",
|
||||
"ok": "சரி",
|
||||
"allow": "அனுமதி",
|
||||
"cancel": "ரத்து செய்",
|
||||
"essentialClaims": "அத்தியாவசிய உரிமைகோரல்கள்",
|
||||
@@ -455,7 +462,7 @@
|
||||
},
|
||||
"ScanScreen": {
|
||||
"header": "QR குறியீட்டை ஸ்கேன் செய்யவும்",
|
||||
"noShareableVcs": "பகிரக்கூடிய அட்டை எதுவும் இல்லை.",
|
||||
"noShareableVcs": "பகிரக்கூடிய அட்டைகள் எதுவும் இல்லை.",
|
||||
"sharingVc": "பகிர்கிறது அட்டை",
|
||||
"bluetoothStateIos": "புளூடூத் முடக்கப்பட்டுள்ளது, கட்டுப்பாட்டு மையத்திலிருந்து அதை இயக்கவும்",
|
||||
"bluetoothStateAndroid": "புளூடூத் முடக்கப்பட்டுள்ளது, விரைவு அமைப்புகள் மெனுவிலிருந்து அதை இயக்கவும்",
|
||||
@@ -558,8 +565,7 @@
|
||||
},
|
||||
"WelcomeScreen": {
|
||||
"title": "திறந்த மூல அடையாள தீர்வு",
|
||||
"getStarted": "தொடங்கு",
|
||||
"unlockApp": "பயன்பாட்டைத் திற",
|
||||
"unlockApplication": "பயன்பாட்டைத் திறக்கவும்",
|
||||
"failedToReadKeys": "விசைகளைப் படிக்க முடியவில்லை",
|
||||
"retryRead": "மீண்டும் முயற்சிக்க வேண்டுமா?",
|
||||
"errors": {
|
||||
|
||||
@@ -12,14 +12,20 @@ import {MY_VCS_STORE_KEY, ESIGNET_BASE_URL} from '../shared/constants';
|
||||
import {StoreEvents} from './store';
|
||||
import {linkTransactionResponse, VC} from '../types/VC/ExistingMosipVC/vc';
|
||||
import {request} from '../shared/request';
|
||||
import {getJwt, isCustomSecureKeystore} from '../shared/cryptoutil/cryptoUtil';
|
||||
import {
|
||||
getJwt,
|
||||
isHardwareKeystoreExists,
|
||||
} from '../shared/cryptoutil/cryptoUtil';
|
||||
import {
|
||||
getBindingCertificateConstant,
|
||||
getPrivateKey,
|
||||
} from '../shared/keystore/SecureKeystore';
|
||||
import i18n from '../i18n';
|
||||
import {parseMetadatas, VCMetadata} from '../shared/VCMetadata';
|
||||
import {getEndData, sendEndEvent} from '../shared/telemetry/TelemetryUtils';
|
||||
import {
|
||||
getEndEventData,
|
||||
sendEndEvent,
|
||||
} from '../shared/telemetry/TelemetryUtils';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -31,7 +37,7 @@ const model = createModel(
|
||||
linkTransactionResponse: {} as linkTransactionResponse,
|
||||
authFactors: [],
|
||||
authorizeScopes: null,
|
||||
clientName: '',
|
||||
clientName: {},
|
||||
configs: {},
|
||||
essentialClaims: [],
|
||||
linkTransactionId: '',
|
||||
@@ -224,7 +230,7 @@ export const qrLoginMachine =
|
||||
},
|
||||
},
|
||||
success: {
|
||||
entry: [() => sendEndEvent(getEndData('QR login'))],
|
||||
entry: [() => sendEndEvent(getEndEventData('QR login', 'SUCCESS'))],
|
||||
on: {
|
||||
CONFIRM: {
|
||||
target: 'done',
|
||||
@@ -345,7 +351,7 @@ export const qrLoginMachine =
|
||||
linkTransaction: async context => {
|
||||
const response = await request(
|
||||
'POST',
|
||||
'/v1/esignet/linked-authorization/link-transaction',
|
||||
'/v1/esignet/linked-authorization/v2/link-transaction',
|
||||
{
|
||||
requestTime: String(new Date().toISOString()),
|
||||
request: {
|
||||
@@ -360,7 +366,7 @@ export const qrLoginMachine =
|
||||
sendAuthenticate: async context => {
|
||||
let privateKey;
|
||||
const individualId = context.selectedVc.vcMetadata.id;
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
privateKey = await getPrivateKey(
|
||||
context.selectedVc.walletBindingResponse?.walletBindingId,
|
||||
);
|
||||
@@ -394,7 +400,7 @@ export const qrLoginMachine =
|
||||
sendConsent: async context => {
|
||||
let privateKey;
|
||||
const individualId = context.selectedVc.vcMetadata.id;
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
privateKey = await getPrivateKey(
|
||||
context.selectedVc.walletBindingResponse?.walletBindingId,
|
||||
);
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'done.invoke.QrLogin.linkTransaction:invocation[0]': {
|
||||
type: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.QrLogin.sendingAuthenticate:invocation[0]': {
|
||||
type: 'done.invoke.QrLogin.sendingAuthenticate:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'error.platform.QrLogin.linkTransaction:invocation[0]': {
|
||||
type: 'error.platform.QrLogin.linkTransaction:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.QrLogin.sendingAuthenticate:invocation[0]': {
|
||||
type: 'error.platform.QrLogin.sendingAuthenticate:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.QrLogin.sendingConsent:invocation[0]': {
|
||||
type: 'error.platform.QrLogin.sendingConsent:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
linkTransaction: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
||||
sendAuthenticate: 'done.invoke.QrLogin.sendingAuthenticate:invocation[0]';
|
||||
sendConsent: 'done.invoke.QrLogin.sendingConsent:invocation[0]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
SetErrorMessage:
|
||||
| 'error.platform.QrLogin.linkTransaction:invocation[0]'
|
||||
| 'error.platform.QrLogin.sendingAuthenticate:invocation[0]'
|
||||
| 'error.platform.QrLogin.sendingConsent:invocation[0]';
|
||||
expandLinkTransResp: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
||||
forwardToParent: 'DISMISS';
|
||||
loadMyVcs: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
||||
loadThumbprint: 'CONFIRM';
|
||||
resetLinkTransactionId: 'GET';
|
||||
resetSelectedVoluntaryClaims: 'GET';
|
||||
setClaims: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
||||
setConsentClaims: 'TOGGLE_CONSENT_CLAIM';
|
||||
setLinkedTransactionId: 'done.invoke.QrLogin.sendingAuthenticate:invocation[0]';
|
||||
setMyVcs: 'STORE_RESPONSE';
|
||||
setScanData: 'GET';
|
||||
setSelectedVc: 'SELECT_VC';
|
||||
setThumbprint: 'STORE_RESPONSE';
|
||||
setlinkTransactionResponse: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {};
|
||||
eventsCausingServices: {
|
||||
linkTransaction: 'GET';
|
||||
sendAuthenticate: never;
|
||||
sendConsent: 'STORE_RESPONSE';
|
||||
};
|
||||
matchesStates:
|
||||
| 'ShowError'
|
||||
| 'done'
|
||||
| 'faceAuth'
|
||||
| 'invalidIdentity'
|
||||
| 'linkTransaction'
|
||||
| 'loadMyVcs'
|
||||
| 'loadingThumbprint'
|
||||
| 'requestConsent'
|
||||
| 'sendingAuthenticate'
|
||||
| 'sendingConsent'
|
||||
| 'showvcList'
|
||||
| 'success'
|
||||
| 'waitingForData';
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {VC} from '../../../types/VC/ExistingMosipVC/vc';
|
||||
import {
|
||||
generateKeys,
|
||||
isCustomSecureKeystore,
|
||||
isHardwareKeystoreExists,
|
||||
WalletBindingResponse,
|
||||
} from '../../../shared/cryptoutil/cryptoUtil';
|
||||
import {log} from 'xstate/lib/actions';
|
||||
import {OpenId4VCIProtocol} from '../../../shared/openId4VCI/Utils';
|
||||
import {Protocols} from '../../../shared/openId4VCI/Utils';
|
||||
import {StoreEvents} from '../../../machines/store';
|
||||
import {MIMOTO_BASE_URL, MY_VCS_STORE_KEY} from '../../../shared/constants';
|
||||
import {VcEvents} from '../../../machines/vc';
|
||||
@@ -23,6 +23,7 @@ import {ActivityLogEvents} from '../../../machines/activityLog';
|
||||
import {request} from '../../../shared/request';
|
||||
import SecureKeystore from 'react-native-secure-keystore';
|
||||
import {VerifiableCredential} from './vc';
|
||||
import {API_URLS} from '../../../shared/api';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -500,7 +501,7 @@ export const EsignetMosipVCItemMachine = model.createMachine(
|
||||
context => ({
|
||||
type: 'GET_VC_ITEM',
|
||||
vcMetadata: context.vcMetadata,
|
||||
protocol: OpenId4VCIProtocol,
|
||||
protocol: Protocols.OpenId4VCI,
|
||||
}),
|
||||
{
|
||||
to: context => context.serviceRefs.vc,
|
||||
@@ -632,7 +633,7 @@ export const EsignetMosipVCItemMachine = model.createMachine(
|
||||
),
|
||||
setPublicKey: assign({
|
||||
publicKey: (context, event) => {
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
return (event.data as KeyPair).public;
|
||||
}
|
||||
return event.data as string;
|
||||
@@ -751,8 +752,8 @@ export const EsignetMosipVCItemMachine = model.createMachine(
|
||||
},
|
||||
addWalletBindnigId: async context => {
|
||||
const response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/wallet-binding',
|
||||
API_URLS.walletBinding.method,
|
||||
API_URLS.walletBinding.buildURL(),
|
||||
{
|
||||
requestTime: String(new Date().toISOString()),
|
||||
request: {
|
||||
@@ -788,7 +789,7 @@ export const EsignetMosipVCItemMachine = model.createMachine(
|
||||
return walletResponse;
|
||||
},
|
||||
generateKeyPair: async context => {
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
return await generateKeys();
|
||||
}
|
||||
const isBiometricsEnabled = SecureKeystore.hasBiometricsEnabled();
|
||||
@@ -800,8 +801,8 @@ export const EsignetMosipVCItemMachine = model.createMachine(
|
||||
},
|
||||
requestBindingOtp: async context => {
|
||||
const response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/binding-otp',
|
||||
API_URLS.bindingOtp.method,
|
||||
API_URLS.bindingOtp.buildURL(),
|
||||
{
|
||||
requestTime: String(new Date().toISOString()),
|
||||
request: {
|
||||
@@ -825,7 +826,7 @@ export const EsignetMosipVCItemMachine = model.createMachine(
|
||||
return vc != null;
|
||||
},
|
||||
|
||||
isCustomSecureKeystore: () => isCustomSecureKeystore(),
|
||||
isCustomSecureKeystore: () => isHardwareKeystoreExists,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -128,7 +128,7 @@ export interface Typegen0 {
|
||||
sendWalletBindingSuccess:
|
||||
| 'done.invoke.vc-item-openid4vci.kebabPopUp.addingWalletBindingId:invocation[0]'
|
||||
| 'done.invoke.vc-item-openid4vci.kebabPopUp.updatingPrivateKey:invocation[0]';
|
||||
setContext: 'STORE_RESPONSE';
|
||||
setContext: 'GET_VC_RESPONSE' | 'STORE_RESPONSE';
|
||||
setGeneratedOn: 'GET_VC_RESPONSE';
|
||||
setOtp: 'INPUT_OTP';
|
||||
setPinCard: 'PIN_CARD';
|
||||
|
||||
@@ -4,10 +4,10 @@ import {MIMOTO_BASE_URL, MY_VCS_STORE_KEY} from '../../../shared/constants';
|
||||
import {AppServices} from '../../../shared/GlobalContext';
|
||||
import {CredentialDownloadResponse, request} from '../../../shared/request';
|
||||
import {
|
||||
VC,
|
||||
VerifiableCredential,
|
||||
VcIdType,
|
||||
DecodedCredential,
|
||||
VC,
|
||||
VcIdType,
|
||||
VerifiableCredential,
|
||||
} from '../../../types/VC/ExistingMosipVC/vc';
|
||||
import {StoreEvents} from '../../store';
|
||||
import {ActivityLogEvents} from '../../activityLog';
|
||||
@@ -15,7 +15,7 @@ import {verifyCredential} from '../../../shared/vcjs/verifyCredential';
|
||||
import {log} from 'xstate/lib/actions';
|
||||
import {
|
||||
generateKeys,
|
||||
isCustomSecureKeystore,
|
||||
isHardwareKeystoreExists,
|
||||
WalletBindingResponse,
|
||||
} from '../../../shared/cryptoutil/cryptoUtil';
|
||||
import {KeyPair} from 'react-native-rsa-native';
|
||||
@@ -31,11 +31,12 @@ import i18n from '../../../i18n';
|
||||
import SecureKeystore from 'react-native-secure-keystore';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {
|
||||
sendStartEvent,
|
||||
getData,
|
||||
getEndData,
|
||||
getEndEventData,
|
||||
getStartEventData,
|
||||
sendEndEvent,
|
||||
sendStartEvent,
|
||||
} from '../../../shared/telemetry/TelemetryUtils';
|
||||
import {API_URLS} from '../../../shared/api';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -173,7 +174,10 @@ export const ExistingMosipVCItemMachine =
|
||||
actions: ['setMaxDownloadCount', 'setDownloadInterval'],
|
||||
},
|
||||
onError: {
|
||||
actions: log((_, event) => (event.data as Error).message),
|
||||
actions: [
|
||||
log((_, event) => (event.data as Error).message),
|
||||
'sendDownloadLimitExpire',
|
||||
],
|
||||
target: 'checkingStatus',
|
||||
},
|
||||
},
|
||||
@@ -216,6 +220,7 @@ export const ExistingMosipVCItemMachine =
|
||||
'setVerifiableCredential',
|
||||
'updateVc',
|
||||
'logDownloaded',
|
||||
'sendTelemetryEvents',
|
||||
'removeVcFromInProgressDownloads',
|
||||
],
|
||||
target: '#vc-item.checkingVerificationStatus',
|
||||
@@ -301,7 +306,9 @@ export const ExistingMosipVCItemMachine =
|
||||
showBindingWarning: {
|
||||
on: {
|
||||
CONFIRM: {
|
||||
actions: [() => sendStartEvent(getData('VC activation'))],
|
||||
actions: [
|
||||
() => sendStartEvent(getStartEventData('VC activation')),
|
||||
],
|
||||
target: '#vc-item.kebabPopUp.requestingBindingOtp',
|
||||
},
|
||||
CANCEL: {
|
||||
@@ -416,7 +423,8 @@ export const ExistingMosipVCItemMachine =
|
||||
'setWalletBindingErrorEmpty',
|
||||
'sendWalletBindingSuccess',
|
||||
'logWalletBindingSuccess',
|
||||
() => sendEndEvent(getEndData('VC activation')),
|
||||
() =>
|
||||
sendEndEvent(getEndEventData('VC activation', 'SUCCESS')),
|
||||
],
|
||||
target: '#vc-item.kebabPopUp',
|
||||
},
|
||||
@@ -633,7 +641,7 @@ export const ExistingMosipVCItemMachine =
|
||||
showBindingWarning: {
|
||||
on: {
|
||||
CONFIRM: {
|
||||
actions: () => sendStartEvent(getData('VC activation')),
|
||||
actions: () => sendStartEvent(getStartEventData('VC activation')),
|
||||
target: 'requestingBindingOtp',
|
||||
},
|
||||
CANCEL: {
|
||||
@@ -743,7 +751,7 @@ export const ExistingMosipVCItemMachine =
|
||||
'setWalletBindingErrorEmpty',
|
||||
'setWalletBindingSuccess',
|
||||
'logWalletBindingSuccess',
|
||||
() => sendEndEvent(getEndData('VC activation')),
|
||||
() => sendEndEvent(getEndEventData('VC activation', 'SUCCESS')),
|
||||
],
|
||||
target: 'idle',
|
||||
},
|
||||
@@ -804,6 +812,18 @@ export const ExistingMosipVCItemMachine =
|
||||
},
|
||||
),
|
||||
|
||||
sendDownloadLimitExpire: send(
|
||||
(_context, event) => {
|
||||
return {
|
||||
type: 'DOWNLOAD_LIMIT_EXPIRED',
|
||||
vcMetadata: _context.vcMetadata,
|
||||
};
|
||||
},
|
||||
{
|
||||
to: context => context.serviceRefs.vc,
|
||||
},
|
||||
),
|
||||
|
||||
setWalletBindingError: assign({
|
||||
walletBindingError: () =>
|
||||
i18n.t(`errors.genericError`, {
|
||||
@@ -835,7 +855,7 @@ export const ExistingMosipVCItemMachine =
|
||||
),
|
||||
setPublicKey: assign({
|
||||
publicKey: (context, event) => {
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
return (event.data as KeyPair).public;
|
||||
}
|
||||
return event.data as string;
|
||||
@@ -1000,7 +1020,11 @@ export const ExistingMosipVCItemMachine =
|
||||
};
|
||||
case 'GET_VC_RESPONSE':
|
||||
case 'CREDENTIAL_DOWNLOADED':
|
||||
return {...context, ...event.vc, vcMetadata: context.vcMetadata};
|
||||
return {
|
||||
...context,
|
||||
...event.vc,
|
||||
vcMetadata: context.vcMetadata,
|
||||
};
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -1019,6 +1043,9 @@ export const ExistingMosipVCItemMachine =
|
||||
to: context => context.serviceRefs.activityLog,
|
||||
},
|
||||
),
|
||||
sendTelemetryEvents: () => {
|
||||
sendEndEvent({type: 'VC Download', status: 'SUCCESS'});
|
||||
},
|
||||
|
||||
logWalletBindingSuccess: send(
|
||||
context =>
|
||||
@@ -1177,8 +1204,8 @@ export const ExistingMosipVCItemMachine =
|
||||
|
||||
addWalletBindnigId: async context => {
|
||||
const response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/wallet-binding',
|
||||
API_URLS.walletBinding.method,
|
||||
API_URLS.walletBinding.buildURL(),
|
||||
{
|
||||
requestTime: String(new Date().toISOString()),
|
||||
request: {
|
||||
@@ -1224,7 +1251,7 @@ export const ExistingMosipVCItemMachine =
|
||||
},
|
||||
|
||||
generateKeyPair: async context => {
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
return await generateKeys();
|
||||
}
|
||||
const isBiometricsEnabled = SecureKeystore.hasBiometricsEnabled();
|
||||
@@ -1237,8 +1264,8 @@ export const ExistingMosipVCItemMachine =
|
||||
|
||||
requestBindingOtp: async context => {
|
||||
const response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/binding-otp',
|
||||
API_URLS.bindingOtp.method,
|
||||
API_URLS.bindingOtp.buildURL(),
|
||||
{
|
||||
requestTime: String(new Date().toISOString()),
|
||||
request: {
|
||||
@@ -1261,8 +1288,10 @@ export const ExistingMosipVCItemMachine =
|
||||
onReceive(async event => {
|
||||
if (event.type === 'POLL_STATUS') {
|
||||
const response = await request(
|
||||
'GET',
|
||||
`/residentmobileapp/credentialshare/request/status/${context.vcMetadata.requestId}`,
|
||||
API_URLS.credentialStatus.method,
|
||||
API_URLS.credentialStatus.buildURL(
|
||||
context.vcMetadata.requestId,
|
||||
),
|
||||
);
|
||||
switch (response.response?.statusCode) {
|
||||
case 'NEW':
|
||||
@@ -1287,8 +1316,8 @@ export const ExistingMosipVCItemMachine =
|
||||
onReceive(async event => {
|
||||
if (event.type === 'POLL_DOWNLOAD') {
|
||||
const response: CredentialDownloadResponse = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/credentialshare/download',
|
||||
API_URLS.credentialDownload.method,
|
||||
API_URLS.credentialDownload.buildURL(),
|
||||
{
|
||||
individualId: context.vcMetadata.id,
|
||||
requestId: context.vcMetadata.requestId,
|
||||
@@ -1322,12 +1351,16 @@ export const ExistingMosipVCItemMachine =
|
||||
|
||||
requestOtp: async context => {
|
||||
try {
|
||||
return request('POST', '/residentmobileapp/req/otp', {
|
||||
individualId: context.vcMetadata.id,
|
||||
individualIdType: context.vcMetadata.idType,
|
||||
otpChannel: ['EMAIL', 'PHONE'],
|
||||
transactionID: context.transactionId,
|
||||
});
|
||||
return request(
|
||||
API_URLS.requestOtp.method,
|
||||
API_URLS.requestOtp.buildURL(),
|
||||
{
|
||||
individualId: context.vcMetadata.id,
|
||||
individualIdType: context.vcMetadata.idType,
|
||||
otpChannel: ['EMAIL', 'PHONE'],
|
||||
transactionID: context.transactionId,
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@@ -1337,8 +1370,8 @@ export const ExistingMosipVCItemMachine =
|
||||
let response = null;
|
||||
if (context.locked) {
|
||||
response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/req/auth/unlock',
|
||||
API_URLS.authUnLock.method,
|
||||
API_URLS.authUnLock.buildURL(),
|
||||
{
|
||||
individualId: context.vcMetadata.id,
|
||||
individualIdType: context.vcMetadata.idType,
|
||||
@@ -1350,8 +1383,8 @@ export const ExistingMosipVCItemMachine =
|
||||
);
|
||||
} else {
|
||||
response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/req/auth/lock',
|
||||
API_URLS.authLock.method,
|
||||
API_URLS.authLock.buildURL(),
|
||||
{
|
||||
individualId: context.vcMetadata.id,
|
||||
individualIdType: context.vcMetadata.idType,
|
||||
@@ -1367,8 +1400,8 @@ export const ExistingMosipVCItemMachine =
|
||||
requestRevoke: async context => {
|
||||
try {
|
||||
return request(
|
||||
'PATCH',
|
||||
`/residentmobileapp/vid/${context.vcMetadata.id}`,
|
||||
API_URLS.requestRevoke.method,
|
||||
API_URLS.requestRevoke.buildURL(context.vcMetadata.id),
|
||||
{
|
||||
transactionID: context.transactionId,
|
||||
vidStatus: 'REVOKED',
|
||||
@@ -1399,7 +1432,7 @@ export const ExistingMosipVCItemMachine =
|
||||
return context.isVerified;
|
||||
},
|
||||
|
||||
isCustomSecureKeystore: () => isCustomSecureKeystore(),
|
||||
isCustomSecureKeystore: () => isHardwareKeystoreExists,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -208,15 +208,19 @@ export interface Typegen0 {
|
||||
| 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
|
||||
| 'done.invoke.vc-item.updatingPrivateKey:invocation[0]';
|
||||
markVcValid: 'done.invoke.vc-item.verifyingCredential:invocation[0]';
|
||||
refreshMyVcs: 'STORE_RESPONSE';
|
||||
removeTamperedVcItem: 'TAMPERED_VC';
|
||||
removeVcFromInProgressDownloads: 'STORE_RESPONSE';
|
||||
removeVcItem: 'CONFIRM';
|
||||
removeVcMetaDataFromStorage: 'STORE_ERROR';
|
||||
removeVcMetaDataFromVcMachine: 'DISMISS';
|
||||
removedVc: 'STORE_RESPONSE';
|
||||
requestStoredContext: 'GET_VC_RESPONSE' | 'REFRESH';
|
||||
requestVcContext: 'DISMISS' | 'xstate.init';
|
||||
resetWalletBindingSuccess: 'DISMISS';
|
||||
revokeVID: 'done.invoke.vc-item.requestingRevoke:invocation[0]';
|
||||
sendDownloadLimitExpire: 'error.platform.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]';
|
||||
sendTamperedVc: 'TAMPERED_VC';
|
||||
sendTelemetryEvents: 'STORE_RESPONSE';
|
||||
sendVcUpdated: 'PIN_CARD';
|
||||
sendWalletBindingSuccess:
|
||||
| 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]'
|
||||
|
||||
100
machines/app.ts
100
machines/app.ts
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import {init} from 'mosip-inji-face-sdk';
|
||||
import {assign, ContextFrom, EventFrom, send, StateFrom} from 'xstate';
|
||||
import {createModel} from 'xstate/lib/model';
|
||||
import getAllConfigurations, {
|
||||
|
||||
@@ -1,64 +1,47 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'': {type: ''};
|
||||
'done.invoke.auth.authorized:invocation[0]': {
|
||||
type: 'done.invoke.auth.authorized:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.auth.introSlider:invocation[0]': {
|
||||
type: 'done.invoke.auth.introSlider:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
downloadFaceSdkModel: 'done.invoke.auth.authorized:invocation[0]';
|
||||
generatePasscodeSalt: 'done.invoke.auth.introSlider:invocation[0]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
requestStoredContext: 'xstate.init';
|
||||
setBiometrics: 'SETUP_BIOMETRICS';
|
||||
setContext: 'STORE_RESPONSE';
|
||||
setLanguage: 'SETUP_BIOMETRICS' | 'SETUP_PASSCODE';
|
||||
setPasscode: 'SETUP_PASSCODE';
|
||||
setPasscodeSalt: 'done.invoke.auth.introSlider:invocation[0]';
|
||||
storeContext:
|
||||
| 'SETUP_BIOMETRICS'
|
||||
| 'SETUP_PASSCODE'
|
||||
| 'STORE_RESPONSE'
|
||||
| 'done.invoke.auth.authorized:invocation[0]'
|
||||
| 'done.invoke.auth.introSlider:invocation[0]';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {
|
||||
hasBiometricSet: '';
|
||||
hasData: 'STORE_RESPONSE';
|
||||
hasLanguageset: '';
|
||||
hasPasscodeSet: '';
|
||||
};
|
||||
eventsCausingServices: {
|
||||
downloadFaceSdkModel: 'LOGIN' | 'SETUP_PASSCODE';
|
||||
generatePasscodeSalt: 'SELECT';
|
||||
};
|
||||
matchesStates:
|
||||
| 'authorized'
|
||||
| 'checkingAuth'
|
||||
| 'init'
|
||||
| 'introSlider'
|
||||
| 'languagesetup'
|
||||
| 'savingDefaults'
|
||||
| 'settingUp'
|
||||
| 'unauthorized';
|
||||
tags: never;
|
||||
}
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"": { type: "" };
|
||||
"done.invoke.auth.authorized:invocation[0]": { type: "done.invoke.auth.authorized:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.auth.introSlider:invocation[0]": { type: "done.invoke.auth.introSlider:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"downloadFaceSdkModel": "done.invoke.auth.authorized:invocation[0]";
|
||||
"generatePasscodeSalt": "done.invoke.auth.introSlider:invocation[0]";
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"requestStoredContext": "xstate.init";
|
||||
"setBiometrics": "SETUP_BIOMETRICS";
|
||||
"setContext": "STORE_RESPONSE";
|
||||
"setLanguage": "SETUP_BIOMETRICS" | "SETUP_PASSCODE";
|
||||
"setPasscode": "SETUP_PASSCODE";
|
||||
"setPasscodeSalt": "done.invoke.auth.introSlider:invocation[0]";
|
||||
"storeContext": "SETUP_BIOMETRICS" | "SETUP_PASSCODE" | "STORE_RESPONSE" | "done.invoke.auth.authorized:invocation[0]" | "done.invoke.auth.introSlider:invocation[0]";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
"hasBiometricSet": "";
|
||||
"hasData": "STORE_RESPONSE";
|
||||
"hasLanguageset": "";
|
||||
"hasPasscodeSet": "";
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"downloadFaceSdkModel": "LOGIN" | "SETUP_PASSCODE";
|
||||
"generatePasscodeSalt": "SELECT";
|
||||
};
|
||||
matchesStates: "authorized" | "checkingAuth" | "init" | "introSlider" | "languagesetup" | "savingDefaults" | "settingUp" | "unauthorized";
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { createModel } from 'xstate/lib/model';
|
||||
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 {EventFrom, MetaObject, StateFrom} from 'xstate';
|
||||
import {Platform} from 'react-native';
|
||||
import {isAndroid} from '../shared/constants';
|
||||
|
||||
// ----- CREATE MODEL ---------------------------------------------------------
|
||||
const model = createModel(
|
||||
@@ -11,18 +12,19 @@ const model = createModel(
|
||||
isEnrolled: false,
|
||||
status: null,
|
||||
retry: false,
|
||||
error: {},
|
||||
},
|
||||
{
|
||||
events: {
|
||||
SET_IS_AVAILABLE: (data: boolean) => ({ data }),
|
||||
SET_AUTH: (data: unknown[]) => ({ data }),
|
||||
SET_IS_ENROLLED: (data: boolean) => ({ data }),
|
||||
SET_STATUS: (data: boolean) => ({ data }),
|
||||
SET_IS_AVAILABLE: (data: boolean) => ({data}),
|
||||
SET_AUTH: (data: unknown[]) => ({data}),
|
||||
SET_IS_ENROLLED: (data: boolean) => ({data}),
|
||||
SET_STATUS: (data: boolean) => ({data}),
|
||||
|
||||
AUTHENTICATE: () => ({}),
|
||||
RETRY_AUTHENTICATE: () => ({}),
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -98,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({
|
||||
@@ -108,9 +110,20 @@ export const biometricsMachine = model.createMachine(
|
||||
// disableDeviceFallback: true,
|
||||
// fallbackLabel: 'Invalid fingerprint attempts, Please try again.'
|
||||
});
|
||||
|
||||
if (res.error) {
|
||||
throw new Error(JSON.stringify(res));
|
||||
}
|
||||
|
||||
return res.success;
|
||||
},
|
||||
onError: 'failure',
|
||||
onError: [
|
||||
{
|
||||
target: 'failure',
|
||||
actions: ['sendFailedEndEvent'],
|
||||
},
|
||||
],
|
||||
|
||||
onDone: {
|
||||
target: 'authentication',
|
||||
actions: ['setStatus'],
|
||||
@@ -192,6 +205,7 @@ export const biometricsMachine = model.createMachine(
|
||||
meta: {
|
||||
message: 'errors.generic',
|
||||
},
|
||||
exit: 'resetError',
|
||||
},
|
||||
},
|
||||
on: {
|
||||
@@ -222,15 +236,26 @@ export const biometricsMachine = model.createMachine(
|
||||
setRetry: model.assign({
|
||||
retry: () => true,
|
||||
}),
|
||||
|
||||
sendFailedEndEvent: model.assign({
|
||||
error: (_context, event) => {
|
||||
const res = JSON.parse((event.data as Error).message);
|
||||
return {res: res, stacktrace: event};
|
||||
},
|
||||
}),
|
||||
|
||||
resetError: model.assign({
|
||||
error: () => null,
|
||||
}),
|
||||
},
|
||||
guards: {
|
||||
isStatusSuccess: (ctx) => ctx.status,
|
||||
isStatusFail: (ctx) => !ctx.status,
|
||||
checkIfAvailable: (ctx) => ctx.isAvailable && ctx.isEnrolled,
|
||||
checkIfUnavailable: (ctx) => !ctx.isAvailable,
|
||||
checkIfUnenrolled: (ctx) => !ctx.isEnrolled,
|
||||
isStatusSuccess: ctx => ctx.status,
|
||||
isStatusFail: ctx => !ctx.status,
|
||||
checkIfAvailable: ctx => ctx.isAvailable && ctx.isEnrolled,
|
||||
checkIfUnavailable: ctx => !ctx.isAvailable,
|
||||
checkIfUnenrolled: ctx => !ctx.isEnrolled,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -253,7 +278,7 @@ export function selectFailMessage(state: State) {
|
||||
}
|
||||
|
||||
export function selectIsEnabled(state: State) {
|
||||
return state.matches('available') || state.matches({ failure: 'unenrolled' });
|
||||
return state.matches('available') || state.matches({failure: 'unenrolled'});
|
||||
}
|
||||
|
||||
export function selectIsAvailable(state: State) {
|
||||
@@ -261,11 +286,11 @@ export function selectIsAvailable(state: State) {
|
||||
}
|
||||
|
||||
export function selectIsUnvailable(state: State) {
|
||||
return state.matches({ failure: 'unavailable' });
|
||||
return state.matches({failure: 'unavailable'});
|
||||
}
|
||||
|
||||
export function selectIsUnenrolled(state: State) {
|
||||
return state.matches({ failure: 'unenrolled' });
|
||||
return state.matches({failure: 'unenrolled'});
|
||||
}
|
||||
|
||||
export function selectIsSuccess(state: State) {
|
||||
@@ -273,11 +298,15 @@ export function selectIsSuccess(state: State) {
|
||||
}
|
||||
|
||||
export function selectError(state: State) {
|
||||
return state.matches({ failure: 'error' }) ? selectFailMessage(state) : null;
|
||||
return state.matches({failure: 'error'}) ? selectFailMessage(state) : null;
|
||||
}
|
||||
|
||||
export function selectUnenrolledNotice(state: State) {
|
||||
return state.matches({ failure: 'unenrolled' }) && state.context.retry
|
||||
return state.matches({failure: 'unenrolled'}) && state.context.retry
|
||||
? selectFailMessage(state)
|
||||
: null;
|
||||
}
|
||||
|
||||
export function selectErrorResponse(state: State) {
|
||||
return state.context.error;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,14 +38,14 @@ 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 {
|
||||
getData,
|
||||
getEndData,
|
||||
getStartEventData,
|
||||
getEndEventData,
|
||||
sendStartEvent,
|
||||
sendEndEvent,
|
||||
} from '../../../shared/telemetry/TelemetryUtils';
|
||||
import {logState} from '../../../shared/commonUtil';
|
||||
|
||||
const {wallet, EventTypes, VerificationStatus} = tuvali;
|
||||
|
||||
@@ -432,7 +432,10 @@ export const scanMachine =
|
||||
},
|
||||
navigatingToHistory: {},
|
||||
},
|
||||
entry: ['sendScanData', () => sendStartEvent(getData('QR login'))],
|
||||
entry: [
|
||||
'sendScanData',
|
||||
() => sendStartEvent(getStartEventData('QR login')),
|
||||
],
|
||||
},
|
||||
connecting: {
|
||||
invoke: {
|
||||
@@ -567,7 +570,10 @@ export const scanMachine =
|
||||
},
|
||||
},
|
||||
accepted: {
|
||||
entry: ['logShared', () => sendEndEvent(getEndData('VC share'))],
|
||||
entry: [
|
||||
'logShared',
|
||||
() => sendEndEvent(getEndEventData('VC share', 'SUCCESS')),
|
||||
],
|
||||
on: {
|
||||
DISMISS: {
|
||||
target: 'navigatingToHome',
|
||||
@@ -715,7 +721,7 @@ export const scanMachine =
|
||||
value: context.linkCode,
|
||||
}),
|
||||
openBluetoothSettings: () => {
|
||||
Platform.OS === 'android'
|
||||
isAndroid()
|
||||
? BluetoothStateManager.openSettings().catch()
|
||||
: Linking.openURL('App-Prefs:Bluetooth');
|
||||
},
|
||||
@@ -899,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);
|
||||
}
|
||||
|
||||
@@ -1006,7 +1012,7 @@ export const scanMachine =
|
||||
},
|
||||
|
||||
startConnection: context => callback => {
|
||||
sendStartEvent(getData('VC share'));
|
||||
sendStartEvent(getStartEventData('VC share'));
|
||||
wallet.startConnection(context.openId4VpUri);
|
||||
const statusCallback = (event: WalletDataEvent) => {
|
||||
if (event.type === EventTypes.onSecureChannelEstablished) {
|
||||
@@ -1101,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),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Camera, CameraCapturedPicture, PermissionResponse } from 'expo-camera';
|
||||
import { CameraType, Face, ImageType } from 'expo-camera/build/Camera.types';
|
||||
import { Linking } from 'react-native';
|
||||
import { assign, EventFrom, StateFrom } from 'xstate';
|
||||
import { createModel } from 'xstate/lib/model';
|
||||
import {Camera, CameraCapturedPicture, PermissionResponse} from 'expo-camera';
|
||||
import {CameraType, Face, ImageType} from 'expo-camera/build/Camera.types';
|
||||
import {Linking} from 'react-native';
|
||||
import {assign, EventFrom, StateFrom} from 'xstate';
|
||||
import {createModel} from 'xstate/lib/model';
|
||||
|
||||
import mosipFaceAuth from '../lib/mosip-inji-face-sdk/faceAuth';
|
||||
import {faceAuth} from 'mosip-mobileid-sdk';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -19,15 +19,15 @@ const model = createModel(
|
||||
},
|
||||
{
|
||||
events: {
|
||||
READY: (cameraRef: Camera) => ({ cameraRef }),
|
||||
READY: (cameraRef: Camera) => ({cameraRef}),
|
||||
FLIP_CAMERA: () => ({}),
|
||||
CAPTURE: () => ({}),
|
||||
DENIED: (response: PermissionResponse) => ({ response }),
|
||||
DENIED: (response: PermissionResponse) => ({response}),
|
||||
GRANTED: () => ({}),
|
||||
OPEN_SETTINGS: () => ({}),
|
||||
APP_FOCUSED: () => ({}),
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export const FaceScannerEvents = model.events;
|
||||
@@ -176,7 +176,7 @@ export const createFaceScannerMachine = (vcImage: string) =>
|
||||
}),
|
||||
|
||||
flipWhichCamera: model.assign({
|
||||
whichCamera: (context) =>
|
||||
whichCamera: context =>
|
||||
context.whichCamera === Camera.Constants.Type.front
|
||||
? Camera.Constants.Type.back
|
||||
: Camera.Constants.Type.front,
|
||||
@@ -190,7 +190,7 @@ export const createFaceScannerMachine = (vcImage: string) =>
|
||||
},
|
||||
|
||||
services: {
|
||||
checkPermission: () => async (callback) => {
|
||||
checkPermission: () => async callback => {
|
||||
const result = await Camera.getCameraPermissionsAsync();
|
||||
if (result.granted) {
|
||||
callback(FaceScannerEvents.GRANTED());
|
||||
@@ -199,7 +199,7 @@ export const createFaceScannerMachine = (vcImage: string) =>
|
||||
}
|
||||
},
|
||||
|
||||
requestPermission: () => async (callback) => {
|
||||
requestPermission: () => async callback => {
|
||||
const result = await Camera.requestCameraPermissionsAsync();
|
||||
if (result.granted) {
|
||||
callback(FaceScannerEvents.GRANTED());
|
||||
@@ -208,19 +208,19 @@ export const createFaceScannerMachine = (vcImage: string) =>
|
||||
}
|
||||
},
|
||||
|
||||
captureImage: (context) => {
|
||||
captureImage: context => {
|
||||
return context.cameraRef.takePictureAsync({
|
||||
base64: true,
|
||||
imageType: ImageType.jpg,
|
||||
});
|
||||
},
|
||||
|
||||
verifyImage: (context) => {
|
||||
verifyImage: context => {
|
||||
context.cameraRef.pausePreview();
|
||||
const rxDataURI =
|
||||
/data:(?<mime>[\w/\-.]+);(?<encoding>\w+),(?<data>.*)/;
|
||||
const matches = rxDataURI.exec(vcImage).groups;
|
||||
return mosipFaceAuth(context.capturedImage.base64, matches.data);
|
||||
return faceAuth(context.capturedImage.base64, matches.data);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@ export const createFaceScannerMachine = (vcImage: string) =>
|
||||
|
||||
doesFaceMatch: (_context, event) => event.data,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
type State = StateFrom<ReturnType<typeof createFaceScannerMachine>>;
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
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';
|
||||
import {
|
||||
generateKeys,
|
||||
isCustomSecureKeystore,
|
||||
isHardwareKeystoreExists,
|
||||
} from '../shared/cryptoutil/cryptoUtil';
|
||||
import SecureKeystore from 'react-native-secure-keystore';
|
||||
import {KeyPair} from 'react-native-rsa-native';
|
||||
@@ -20,9 +24,18 @@ import {
|
||||
vcDownloadTimeout,
|
||||
OIDCErrors,
|
||||
ErrorMessage,
|
||||
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,
|
||||
getImpressionEventData,
|
||||
sendEndEvent,
|
||||
sendImpressionEvent,
|
||||
} from '../shared/telemetry/TelemetryUtils';
|
||||
import {
|
||||
CredentialWrapper,
|
||||
VerifiableCredential,
|
||||
@@ -62,7 +75,6 @@ const model = createModel(
|
||||
export const IssuerScreenTabEvents = model.events;
|
||||
export const Issuer_Tab_Ref_Id = 'issuersMachine';
|
||||
|
||||
export const Issuers_Key_Ref = 'OpenId4VCI';
|
||||
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 */
|
||||
@@ -82,7 +94,11 @@ export const IssuersMachine = model.createMachine(
|
||||
invoke: {
|
||||
src: 'downloadIssuersList',
|
||||
onDone: {
|
||||
actions: ['setIssuers', 'resetLoadingReason'],
|
||||
actions: [
|
||||
'sendImpressionEvent',
|
||||
'setIssuers',
|
||||
'resetLoadingReason',
|
||||
],
|
||||
target: 'selectingIssuer',
|
||||
},
|
||||
onError: {
|
||||
@@ -109,7 +125,7 @@ export const IssuersMachine = model.createMachine(
|
||||
},
|
||||
{
|
||||
description: 'not fetched issuers config yet',
|
||||
actions: ['setLoadingReasonAsDisplayIssuers', 'resetError'],
|
||||
actions: ['setLoadingReasonAsSettingUp', 'resetError'],
|
||||
target: 'downloadIssuerConfig',
|
||||
},
|
||||
],
|
||||
@@ -126,7 +142,7 @@ export const IssuersMachine = model.createMachine(
|
||||
actions: sendParent('DOWNLOAD_ID'),
|
||||
},
|
||||
SELECTED_ISSUER: {
|
||||
actions: 'setSelectedIssuerId',
|
||||
actions: ['setSelectedIssuerId', 'setLoadingReasonAsSettingUp'],
|
||||
target: 'downloadIssuerConfig',
|
||||
},
|
||||
},
|
||||
@@ -161,7 +177,8 @@ export const IssuersMachine = model.createMachine(
|
||||
},
|
||||
],
|
||||
onError: {
|
||||
actions: () => console.log('checkInternet error caught'),
|
||||
actions: () =>
|
||||
console.log('Error Occurred while checking Internet'),
|
||||
target: 'error',
|
||||
},
|
||||
},
|
||||
@@ -195,7 +212,11 @@ export const IssuersMachine = model.createMachine(
|
||||
actions: [
|
||||
'setError',
|
||||
'resetLoadingReason',
|
||||
(_, event) => console.log('error in invokeAuth - ', event.data),
|
||||
(_, event) =>
|
||||
console.log(
|
||||
'Error Occurred while invoking Auth - ',
|
||||
event.data,
|
||||
),
|
||||
],
|
||||
target: 'error',
|
||||
},
|
||||
@@ -204,7 +225,7 @@ export const IssuersMachine = model.createMachine(
|
||||
},
|
||||
checkKeyPair: {
|
||||
description: 'checks whether key pair is generated',
|
||||
entry: [send('CHECK_KEY_PAIR')],
|
||||
entry: ['setLoadingReasonAsSettingUp', send('CHECK_KEY_PAIR')],
|
||||
on: {
|
||||
CHECK_KEY_PAIR: [
|
||||
{
|
||||
@@ -272,12 +293,16 @@ export const IssuersMachine = model.createMachine(
|
||||
src: 'verifyCredential',
|
||||
onDone: [
|
||||
{
|
||||
actions: ['sendSuccessEndEvent'],
|
||||
target: 'storing',
|
||||
},
|
||||
],
|
||||
onError: [
|
||||
{
|
||||
actions: log((_, event) => (event.data as Error).message),
|
||||
actions: [
|
||||
log((_, event) => (event.data as Error).message),
|
||||
'sendErrorEndEvent',
|
||||
],
|
||||
//TODO: Move to state according to the required flow when verification of VC fails
|
||||
target: 'idle',
|
||||
},
|
||||
@@ -435,7 +460,7 @@ export const IssuersMachine = model.createMachine(
|
||||
}),
|
||||
setPublicKey: assign({
|
||||
publicKey: (_, event) => {
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
return (event.data as KeyPair).public;
|
||||
}
|
||||
return event.data as string;
|
||||
@@ -460,6 +485,17 @@ export const IssuersMachine = model.createMachine(
|
||||
to: context => context.serviceRefs.activityLog,
|
||||
},
|
||||
),
|
||||
sendSuccessEndEvent: () => {
|
||||
sendEndEvent(getEndEventData('VC Download', 'SUCCESS'));
|
||||
},
|
||||
sendErrorEndEvent: () => {
|
||||
sendEndEvent(getEndEventData('VC Download', 'FAILURE'));
|
||||
},
|
||||
sendImpressionEvent: () => {
|
||||
sendImpressionEvent(
|
||||
getImpressionEventData('VC Download', 'Issuer List'),
|
||||
);
|
||||
},
|
||||
},
|
||||
services: {
|
||||
downloadIssuersList: async () => {
|
||||
@@ -474,7 +510,7 @@ export const IssuersMachine = model.createMachine(
|
||||
const downloadTimeout = await vcDownloadTimeout();
|
||||
let credential = await request(
|
||||
'POST',
|
||||
context.selectedIssuer.serviceConfiguration.credentialEndpoint,
|
||||
context.selectedIssuer.credential_endpoint,
|
||||
body,
|
||||
'',
|
||||
{
|
||||
@@ -490,10 +526,18 @@ export const IssuersMachine = model.createMachine(
|
||||
return credential;
|
||||
},
|
||||
invokeAuthorization: async context => {
|
||||
return await authorize(context.selectedIssuer);
|
||||
sendImpressionEvent(
|
||||
getImpressionEventData(
|
||||
'VC Download',
|
||||
context.selectedIssuer.credential_issuer + ' Web View Page',
|
||||
),
|
||||
);
|
||||
return await authorize(
|
||||
constructAuthorizationConfiguration(context.selectedIssuer),
|
||||
);
|
||||
},
|
||||
generateKeyPair: async context => {
|
||||
if (!isCustomSecureKeystore()) {
|
||||
generateKeyPair: async () => {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
return await generateKeys();
|
||||
}
|
||||
const isBiometricsEnabled = SecureKeystore.hasBiometricsEnabled();
|
||||
@@ -538,7 +582,7 @@ export const IssuersMachine = model.createMachine(
|
||||
);
|
||||
},
|
||||
shouldFetchIssuersAgain: context => context.issuers.length === 0,
|
||||
isCustomSecureKeystore: () => isCustomSecureKeystore(),
|
||||
isCustomSecureKeystore: () => isHardwareKeystoreExists,
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -576,32 +620,27 @@ export function selectStoring(state: State) {
|
||||
return state.matches('storing');
|
||||
}
|
||||
|
||||
interface issuerType {
|
||||
id: string;
|
||||
displayName: string;
|
||||
logoUrl: string;
|
||||
export interface logoType {
|
||||
url: string;
|
||||
alt_text: string;
|
||||
}
|
||||
|
||||
const updateCredentialInformation = (context, credential) => {
|
||||
let credentialWrapper: CredentialWrapper = {};
|
||||
credentialWrapper.verifiableCredential = credential;
|
||||
credentialWrapper.verifiableCredential.issuerLogo =
|
||||
context.selectedIssuer.logoUrl;
|
||||
credentialWrapper.identifier = getIdentifier(context, credential);
|
||||
credentialWrapper.generatedOn = new Date();
|
||||
credentialWrapper.issuerLogo = context.selectedIssuer.logoUrl;
|
||||
return credentialWrapper;
|
||||
};
|
||||
|
||||
const getVCMetadata = context => {
|
||||
const [issuer, protocol, requestId] =
|
||||
context.credentialWrapper?.identifier.split(':');
|
||||
return VCMetadata.fromVC({
|
||||
requestId: requestId ? requestId : null,
|
||||
issuer: issuer,
|
||||
protocol: protocol,
|
||||
id: context.verifiableCredential?.credential.credentialSubject.UIN
|
||||
? context.verifiableCredential?.credential.credentialSubject.UIN
|
||||
: context.verifiableCredential?.credential.credentialSubject.VID,
|
||||
});
|
||||
};
|
||||
export interface displayType {
|
||||
name: string;
|
||||
logo: logoType;
|
||||
language: string;
|
||||
}
|
||||
export interface issuerType {
|
||||
credential_issuer: string;
|
||||
protocol: string;
|
||||
client_id: string;
|
||||
'.well-known': string;
|
||||
redirect_uri: string;
|
||||
scopes_supported: [string];
|
||||
additional_headers: object;
|
||||
authorization_endpoint: string;
|
||||
token_endpoint: string;
|
||||
credential_endpoint: string;
|
||||
credential_audience: string;
|
||||
display: [displayType];
|
||||
}
|
||||
|
||||
@@ -58,6 +58,10 @@ export interface Typegen0 {
|
||||
type: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.verifyingCredential:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
@@ -89,6 +93,9 @@ export interface Typegen0 {
|
||||
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadIssuerConfig:invocation[0]'
|
||||
| 'error.platform.issuersMachine.performAuthorization:invocation[0]';
|
||||
sendErrorEndEvent: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
sendImpressionEvent: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
|
||||
sendSuccessEndEvent: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
|
||||
setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
|
||||
setError:
|
||||
| 'error.platform.issuersMachine.displayIssuers:invocation[0]'
|
||||
@@ -98,7 +105,10 @@ export interface Typegen0 {
|
||||
setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
|
||||
setLoadingReasonAsDisplayIssuers: 'TRY_AGAIN';
|
||||
setLoadingReasonAsDownloadingCredentials: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
|
||||
setLoadingReasonAsSettingUp: 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
|
||||
setLoadingReasonAsSettingUp:
|
||||
| 'SELECTED_ISSUER'
|
||||
| 'TRY_AGAIN'
|
||||
| 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
|
||||
setNoInternet: 'done.invoke.checkInternet';
|
||||
setOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
|
||||
setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {TextInput} from 'react-native';
|
||||
import {assign, ErrorPlatformEvent, StateFrom, send, EventFrom} from 'xstate';
|
||||
import {assign, ErrorPlatformEvent, EventFrom, send, StateFrom} from 'xstate';
|
||||
import {log} from 'xstate/lib/actions';
|
||||
|
||||
import i18n from '../i18n';
|
||||
@@ -11,6 +11,7 @@ import {request} from '../shared/request';
|
||||
import {VcIdType} from '../types/VC/ExistingMosipVC/vc';
|
||||
import {MY_VCS_STORE_KEY} from '../shared/constants';
|
||||
import {VCMetadata} from '../shared/VCMetadata';
|
||||
import {API_URLS} from '../shared/api';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -236,12 +237,16 @@ export const revokeVidsMachine =
|
||||
services: {
|
||||
requestOtp: async context => {
|
||||
const transactionId = String(new Date().valueOf()).substring(3, 13);
|
||||
return request('POST', '/residentmobileapp/req/otp', {
|
||||
individualId: context.VIDsMetadata[0].id,
|
||||
individualIdType: 'VID',
|
||||
otpChannel: ['EMAIL', 'PHONE'],
|
||||
transactionID: transactionId,
|
||||
});
|
||||
return request(
|
||||
API_URLS.requestOtp.method,
|
||||
API_URLS.requestOtp.buildURL(),
|
||||
{
|
||||
individualId: context.VIDsMetadata[0].id,
|
||||
individualIdType: 'VID',
|
||||
otpChannel: ['EMAIL', 'PHONE'],
|
||||
transactionID: transactionId,
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
requestRevoke: context => async callback => {
|
||||
@@ -253,8 +258,8 @@ export const revokeVidsMachine =
|
||||
13,
|
||||
);
|
||||
return request(
|
||||
'PATCH',
|
||||
`/residentmobileapp/vid/${metadata.id}`,
|
||||
API_URLS.requestRevoke.method,
|
||||
API_URLS.requestRevoke.buildURL(metadata.id),
|
||||
{
|
||||
transactionID: transactionId,
|
||||
vidStatus: 'REVOKED',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
'internalEvents': {
|
||||
internalEvents: {
|
||||
'done.invoke.RevokeVids.acceptingVIDs.requestingOtp:invocation[0]': {
|
||||
type: 'done.invoke.RevokeVids.acceptingVIDs.requestingOtp:invocation[0]';
|
||||
data: unknown;
|
||||
@@ -12,19 +12,19 @@ export interface Typegen0 {
|
||||
type: 'error.platform.RevokeVids.acceptingVIDs.requestingOtp:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': { type: 'xstate.init' };
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
'invokeSrcNameMap': {
|
||||
invokeSrcNameMap: {
|
||||
requestOtp: 'done.invoke.RevokeVids.acceptingVIDs.requestingOtp:invocation[0]';
|
||||
requestRevoke: 'done.invoke.RevokeVids.requestingRevoke:invocation[0]';
|
||||
};
|
||||
'missingImplementations': {
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
'eventsCausingActions': {
|
||||
eventsCausingActions: {
|
||||
clearOtp:
|
||||
| 'DISMISS'
|
||||
| 'ERROR'
|
||||
@@ -39,13 +39,13 @@ export interface Typegen0 {
|
||||
setTransactionId: 'DISMISS' | 'REVOKE_VCS' | 'xstate.init';
|
||||
setVIDs: 'REVOKE_VCS';
|
||||
};
|
||||
'eventsCausingDelays': {};
|
||||
'eventsCausingGuards': {};
|
||||
'eventsCausingServices': {
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {};
|
||||
eventsCausingServices: {
|
||||
requestOtp: never;
|
||||
requestRevoke: 'INPUT_OTP';
|
||||
};
|
||||
'matchesStates':
|
||||
matchesStates:
|
||||
| 'acceptingOtpInput'
|
||||
| 'acceptingVIDs'
|
||||
| 'acceptingVIDs.idle'
|
||||
@@ -57,6 +57,6 @@ export interface Typegen0 {
|
||||
| 'loggingRevoke'
|
||||
| 'requestingRevoke'
|
||||
| 'revokingVc'
|
||||
| { acceptingVIDs?: 'idle' | 'requestingOtp'; invalid?: 'backend' | 'otp' };
|
||||
'tags': never;
|
||||
| {acceptingVIDs?: 'idle' | 'requestingOtp'; invalid?: 'backend' | 'otp'};
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import getAllConfigurations, {
|
||||
import Storage from '../shared/storage';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import {__AppId} from '../shared/GlobalVariables';
|
||||
import {isCustomSecureKeystore} from '../shared/cryptoutil/cryptoUtil';
|
||||
import {isHardwareKeystoreExists} from '../shared/cryptoutil/cryptoUtil';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -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: {
|
||||
@@ -274,7 +269,7 @@ function generateAppId() {
|
||||
}
|
||||
|
||||
function deviceSupportsHardwareKeystore() {
|
||||
return isIOS() ? true : isCustomSecureKeystore();
|
||||
return isIOS() ? true : isHardwareKeystoreExists;
|
||||
}
|
||||
|
||||
type State = StateFrom<typeof settingsMachine>;
|
||||
|
||||
@@ -16,15 +16,15 @@ import {MY_VCS_STORE_KEY} from '../shared/constants';
|
||||
import SecureKeystore from 'react-native-secure-keystore';
|
||||
import {
|
||||
AUTH_TIMEOUT,
|
||||
clear,
|
||||
decryptJson,
|
||||
DUMMY_KEY_FOR_BIOMETRIC_ALIAS,
|
||||
ENCRYPTION_ID,
|
||||
encryptJson,
|
||||
HMAC_ALIAS,
|
||||
isCustomSecureKeystore,
|
||||
isHardwareKeystoreExists,
|
||||
} from '../shared/cryptoutil/cryptoUtil';
|
||||
import {VCMetadata} from '../shared/VCMetadata';
|
||||
import FileStorage, {getFilePath} from '../shared/fileStorage';
|
||||
|
||||
export const keyinvalidatedString =
|
||||
'Key Invalidated due to biometric enrollment';
|
||||
@@ -81,7 +81,7 @@ export const storeMachine =
|
||||
events: {} as EventFrom<typeof model>,
|
||||
},
|
||||
id: 'store',
|
||||
initial: !isCustomSecureKeystore()
|
||||
initial: !isHardwareKeystoreExists
|
||||
? 'gettingEncryptionKey'
|
||||
: 'checkEncryptionKey',
|
||||
states: {
|
||||
@@ -104,7 +104,7 @@ export const storeMachine =
|
||||
},
|
||||
on: {
|
||||
KEY_RECEIVED: {
|
||||
actions: ['setEncryptionKey', 'logKey'],
|
||||
actions: ['setEncryptionKey'],
|
||||
target: 'ready',
|
||||
},
|
||||
ERROR: {
|
||||
@@ -173,7 +173,7 @@ export const storeMachine =
|
||||
},
|
||||
},
|
||||
ready: {
|
||||
entry: 'notifyParent',
|
||||
entry: ['notifyParent', 'cacheVCFilesData'],
|
||||
invoke: {
|
||||
src: 'store',
|
||||
id: '_store',
|
||||
@@ -259,10 +259,22 @@ export const storeMachine =
|
||||
setEncryptionKey: model.assign({
|
||||
encryptionKey: (_, event) => event.key,
|
||||
}),
|
||||
|
||||
cacheVCFilesData: context => {
|
||||
getItem(MY_VCS_STORE_KEY, [], context.encryptionKey).then(vcList => {
|
||||
if (vcList) {
|
||||
vcList?.forEach((vcMetadataStr: string) => {
|
||||
const vcKey =
|
||||
VCMetadata.fromVcMetadataString(vcMetadataStr).getVcKey();
|
||||
FileStorage.readAndCacheFile(getFilePath(vcKey));
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
services: {
|
||||
clear,
|
||||
clear: () => clear(),
|
||||
hasAndroidEncryptionKey: () => async callback => {
|
||||
const hasSetCredentials = SecureKeystore.hasAlias(ENCRYPTION_ID);
|
||||
if (hasSetCredentials) {
|
||||
@@ -289,6 +301,7 @@ export const storeMachine =
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
checkStorageInitialisedOrNot: () => async callback => {
|
||||
const isDirectoryExist = await Storage.isVCStorageInitialised();
|
||||
if (!isDirectoryExist) {
|
||||
@@ -427,7 +440,7 @@ export const storeMachine =
|
||||
generateEncryptionKey: () => async callback => {
|
||||
const randomBytes = await generateSecureRandom(32);
|
||||
const randomBytesString = binaryToBase64(randomBytes);
|
||||
if (!isCustomSecureKeystore()) {
|
||||
if (!isHardwareKeystoreExists) {
|
||||
const hasSetCredentials = await Keychain.setGenericPassword(
|
||||
ENCRYPTION_ID,
|
||||
randomBytesString,
|
||||
@@ -461,7 +474,7 @@ export const storeMachine =
|
||||
},
|
||||
|
||||
guards: {
|
||||
isCustomSecureKeystore: () => isCustomSecureKeystore(),
|
||||
isCustomSecureKeystore: () => isHardwareKeystoreExists,
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -616,6 +629,18 @@ export async function removeVCMetaData(
|
||||
}
|
||||
}
|
||||
|
||||
export async function clear() {
|
||||
try {
|
||||
console.log('clearing entire storage');
|
||||
if (isHardwareKeystoreExists) {
|
||||
SecureKeystore.clearKeys();
|
||||
}
|
||||
await Storage.clear();
|
||||
} catch (e) {
|
||||
console.error('error clear:', e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
export async function removeItems(
|
||||
key: string,
|
||||
values: string[],
|
||||
|
||||
@@ -1,54 +1,5 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
<<<<<<< HEAD
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"done.invoke._store": { type: "done.invoke._store"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.store.resettingStorage:invocation[0]": { type: "done.invoke.store.resettingStorage:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"error.platform._store": { type: "error.platform._store"; data: unknown };
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"checkStorageInitialisedOrNot": "done.invoke.store.checkStorageInitialisation:invocation[0]";
|
||||
"clear": "done.invoke.store.resettingStorage:invocation[0]";
|
||||
"generateEncryptionKey": "done.invoke.store.generatingEncryptionKey:invocation[0]";
|
||||
"getEncryptionKey": "done.invoke.store.gettingEncryptionKey:invocation[0]";
|
||||
"hasAndroidEncryptionKey": "done.invoke.store.checkEncryptionKey:invocation[0]";
|
||||
"store": "done.invoke._store";
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: "logKey";
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"forwardStoreRequest": "APPEND" | "CLEAR" | "GET" | "PREPEND" | "REMOVE" | "REMOVE_ITEMS" | "REMOVE_VC_METADATA" | "SET" | "UPDATE";
|
||||
"logKey": "KEY_RECEIVED";
|
||||
"notifyParent": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
|
||||
"setEncryptionKey": "KEY_RECEIVED";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
"isCustomSecureKeystore": "KEY_RECEIVED";
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"checkStorageInitialisedOrNot": "ERROR";
|
||||
"clear": "KEY_RECEIVED";
|
||||
"generateEncryptionKey": "ERROR" | "IGNORE" | "READY";
|
||||
"getEncryptionKey": "TRY_AGAIN";
|
||||
"hasAndroidEncryptionKey": never;
|
||||
"store": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
|
||||
};
|
||||
matchesStates: "checkEncryptionKey" | "checkStorageInitialisation" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage";
|
||||
tags: never;
|
||||
}
|
||||
|
||||
=======
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
@@ -74,12 +25,16 @@ export interface Typegen0 {
|
||||
store: 'done.invoke._store';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: 'logKey';
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
cacheVCFilesData:
|
||||
| 'KEY_RECEIVED'
|
||||
| 'READY'
|
||||
| 'done.invoke.store.resettingStorage:invocation[0]';
|
||||
forwardStoreRequest:
|
||||
| 'APPEND'
|
||||
| 'CLEAR'
|
||||
@@ -90,14 +45,11 @@ export interface Typegen0 {
|
||||
| 'REMOVE_VC_METADATA'
|
||||
| 'SET'
|
||||
| 'UPDATE';
|
||||
logKey: 'KEY_RECEIVED';
|
||||
notifyParent:
|
||||
| 'KEY_RECEIVED'
|
||||
| 'READY'
|
||||
| 'done.invoke.store.resettingStorage:invocation[0]';
|
||||
resetIsTamperedVc: 'RESET_IS_TAMPERED';
|
||||
setEncryptionKey: 'KEY_RECEIVED';
|
||||
setIsTamperedVc: 'TAMPERED_VC';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {
|
||||
@@ -124,4 +76,3 @@ export interface Typegen0 {
|
||||
| 'resettingStorage';
|
||||
tags: never;
|
||||
}
|
||||
>>>>>>> 5b53b069 (refactor(INJI-205): Check Internet before OIDC AuthZ)
|
||||
|
||||
@@ -7,7 +7,7 @@ import {log, respond} from 'xstate/lib/actions';
|
||||
import {ExistingMosipVCItemEvents} from './VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine';
|
||||
import {MY_VCS_STORE_KEY, RECEIVED_VCS_STORE_KEY} from '../shared/constants';
|
||||
import {parseMetadatas, VCMetadata} from '../shared/VCMetadata';
|
||||
import {OpenId4VCIProtocol} from '../shared/openId4VCI/Utils';
|
||||
import {Protocols} from '../shared/openId4VCI/Utils';
|
||||
import {EsignetMosipVCItemEvents} from './VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine';
|
||||
import {ActivityLogEvents} from './activityLog';
|
||||
import {ActivityLog} from '../components/ActivityLogEvent';
|
||||
@@ -22,6 +22,7 @@ const model = createModel(
|
||||
areAllVcsDownloaded: false as boolean,
|
||||
walletBindingSuccess: false,
|
||||
tamperedVcs: [] as VCMetadata[],
|
||||
downloadingFailedVcs: [] as VCMetadata[],
|
||||
},
|
||||
{
|
||||
events: {
|
||||
@@ -52,6 +53,8 @@ const model = createModel(
|
||||
RESET_ARE_ALL_VCS_DOWNLOADED: () => ({}),
|
||||
TAMPERED_VC: (VC: VCMetadata) => ({VC}),
|
||||
REMOVE_TAMPERED_VCS: () => ({}),
|
||||
DOWNLOAD_LIMIT_EXPIRED: (vcMetadata: VCMetadata) => ({vcMetadata}),
|
||||
DELETE_VC: () => ({}),
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -201,6 +204,13 @@ export const vcMachine =
|
||||
actions: 'setTamperedVcs',
|
||||
target: 'tamperedVCs',
|
||||
},
|
||||
DOWNLOAD_LIMIT_EXPIRED: {
|
||||
actions: [
|
||||
'removeVcFromInProgressDownlods',
|
||||
'setDownloadingFailedVcs',
|
||||
],
|
||||
target: 'downloadLimitExpired',
|
||||
},
|
||||
},
|
||||
},
|
||||
tamperedVCs: {
|
||||
@@ -211,6 +221,25 @@ export const vcMachine =
|
||||
},
|
||||
},
|
||||
},
|
||||
downloadLimitExpired: {
|
||||
on: {
|
||||
DELETE_VC: {
|
||||
target: 'deletingFailedVcs',
|
||||
},
|
||||
},
|
||||
},
|
||||
deletingFailedVcs: {
|
||||
entry: 'removeDownloadFailedVcsFromStorage',
|
||||
on: {
|
||||
STORE_RESPONSE: {
|
||||
actions: [
|
||||
'removeDownloadingFailedVcsFromMyVcs',
|
||||
'resetDownloadFailedVcs',
|
||||
],
|
||||
target: '#vc.ready.myVcs.refreshing',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -222,7 +251,7 @@ export const vcMachine =
|
||||
|
||||
getVcItemResponse: respond((context, event) => {
|
||||
const vc = context.vcs[event.vcMetadata?.getVcKey()];
|
||||
if (event.protocol === OpenId4VCIProtocol) {
|
||||
if (event.protocol === Protocols.OpenId4VCI) {
|
||||
return EsignetMosipVCItemEvents.GET_VC_RESPONSE(vc);
|
||||
}
|
||||
return ExistingMosipVCItemEvents.GET_VC_RESPONSE(vc);
|
||||
@@ -252,6 +281,17 @@ export const vcMachine =
|
||||
tamperedVcs: (context, event) => [event.VC, ...context.tamperedVcs],
|
||||
}),
|
||||
|
||||
setDownloadingFailedVcs: model.assign({
|
||||
downloadingFailedVcs: (context, event) => [
|
||||
event.vcMetadata,
|
||||
...context.downloadingFailedVcs,
|
||||
],
|
||||
}),
|
||||
|
||||
resetDownloadFailedVcs: model.assign({
|
||||
downloadingFailedVcs: (context, event) => [],
|
||||
}),
|
||||
|
||||
setDownloadedVc: (context, event) => {
|
||||
const vcUniqueId = VCMetadata.fromVC(event.vc).getVcKey();
|
||||
context.vcs[vcUniqueId] = event.vc;
|
||||
@@ -271,7 +311,10 @@ export const vcMachine =
|
||||
inProgressVcDownloads: (context, event) => {
|
||||
let paresedInProgressList: Set<string> =
|
||||
context.inProgressVcDownloads;
|
||||
const removeVcRequestID = event.requestId;
|
||||
const removeVcRequestID =
|
||||
event.type === 'REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS'
|
||||
? event.requestId
|
||||
: event.vcMetadata.requestId;
|
||||
paresedInProgressList.delete(removeVcRequestID);
|
||||
return paresedInProgressList;
|
||||
},
|
||||
@@ -323,6 +366,26 @@ export const vcMachine =
|
||||
),
|
||||
}),
|
||||
|
||||
removeDownloadingFailedVcsFromMyVcs: model.assign({
|
||||
myVcs: (context, event) =>
|
||||
context.myVcs.filter(
|
||||
value =>
|
||||
!context.downloadingFailedVcs.some(item => item?.equals(value)),
|
||||
),
|
||||
}),
|
||||
|
||||
removeDownloadFailedVcsFromStorage: send(
|
||||
context => {
|
||||
return StoreEvents.REMOVE_ITEMS(
|
||||
MY_VCS_STORE_KEY,
|
||||
context.downloadingFailedVcs.map(m => m.getVcKey()),
|
||||
);
|
||||
},
|
||||
{
|
||||
to: context => context.serviceRefs.store,
|
||||
},
|
||||
),
|
||||
|
||||
removeTamperedVcs: model.assign({
|
||||
myVcs: (context, event) =>
|
||||
context.myVcs.filter(
|
||||
@@ -430,8 +493,8 @@ export function selectAreAllVcsDownloaded(state: State) {
|
||||
return state.context.areAllVcsDownloaded;
|
||||
}
|
||||
|
||||
export function selectInProgressVcDownloadsCount(state: State) {
|
||||
return state.context.inProgressVcDownloads.size;
|
||||
export function selectInProgressVcDownloads(state: State) {
|
||||
return state.context.inProgressVcDownloads;
|
||||
}
|
||||
|
||||
function getUpdatedVCMetadatas(
|
||||
@@ -462,3 +525,11 @@ export function selectWalletBindingSuccess(state: State) {
|
||||
export function selectIsTampered(state: State) {
|
||||
return state.matches('tamperedVCs');
|
||||
}
|
||||
|
||||
export function selectIsDownloadLimitExpired(state: State) {
|
||||
return state.matches('downloadLimitExpired');
|
||||
}
|
||||
|
||||
export function selectDownloadingFailedVcs(state: State) {
|
||||
return state.context.downloadingFailedVcs;
|
||||
}
|
||||
|
||||
203
package-lock.json
generated
203
package-lock.json
generated
@@ -42,7 +42,7 @@
|
||||
"i18next": "^21.6.16",
|
||||
"iso-639-3": "^3.0.1",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"mosip-inji-face-sdk": "^0.1.12",
|
||||
"mosip-mobileid-sdk": "git://github.com/mosip/mosip-mobileid-sdk.git#IrisScan",
|
||||
"node-forge": "^1.3.1",
|
||||
"node-jose": "^2.2.0",
|
||||
"patch-package": "^6.5.1",
|
||||
@@ -84,7 +84,7 @@
|
||||
"react-native-vector-icons": "^10.0.0",
|
||||
"short-unique-id": "^4.4.4",
|
||||
"simple-pem2jwk": "^0.2.4",
|
||||
"telemetry-sdk": "git://github.com/mosip/sunbird-telemetry-sdk.git#develop",
|
||||
"telemetry-sdk": "git://github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
|
||||
"xstate": "^4.35.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -9623,7 +9623,7 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/core/node_modules/typescript": {
|
||||
"node_modules/@svgr/core/node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
@@ -9742,7 +9742,7 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/plugin-svgo/node_modules/typescript": {
|
||||
"node_modules/@svgr/plugin-svgo/node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
@@ -10269,7 +10269,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
|
||||
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||
@@ -10552,7 +10552,7 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/array-each": {
|
||||
"node_modules/array-each": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
|
||||
"integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==",
|
||||
@@ -12872,7 +12872,7 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dateformat": {
|
||||
"node_modules/dateformat": {
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
|
||||
"integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
|
||||
@@ -13223,7 +13223,7 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-file": {
|
||||
"node_modules/detect-file": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
|
||||
"integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==",
|
||||
@@ -13460,7 +13460,7 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/encoding": {
|
||||
"node_modules/encoding": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
||||
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
||||
@@ -14347,7 +14347,7 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter2": {
|
||||
"node_modules/eventemitter2": {
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
|
||||
"integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==",
|
||||
@@ -14402,7 +14402,7 @@
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
||||
"integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
|
||||
"engines": {
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
@@ -14591,7 +14591,7 @@
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/expand-tilde": {
|
||||
"node_modules/expand-tilde": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
|
||||
"integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==",
|
||||
@@ -15670,7 +15670,7 @@
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.5.1.tgz",
|
||||
"integrity": "sha512-yt5a1VCp2BF9CrsO689PCD5oXKP14MMhnOanQMvDn4BDpURYfzAlDVGC5fZrNQKtwn/eq3bcrxIwZ7D9QjVVRg==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@expo/config": "~8.1.0",
|
||||
"chalk": "^4.1.0",
|
||||
@@ -15687,7 +15687,7 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
@@ -15702,7 +15702,7 @@
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
@@ -15718,7 +15718,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
@@ -15736,7 +15736,7 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -15745,7 +15745,7 @@
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
@@ -15760,7 +15760,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -15769,7 +15769,7 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
@@ -15781,7 +15781,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
@@ -16771,7 +16771,7 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/findup-sync": {
|
||||
"node_modules/findup-sync": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz",
|
||||
"integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==",
|
||||
@@ -16878,7 +16878,7 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/for-own": {
|
||||
"node_modules/for-own": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
|
||||
"integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==",
|
||||
@@ -17092,7 +17092,7 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/getobject": {
|
||||
"node_modules/getobject": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz",
|
||||
"integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==",
|
||||
@@ -17154,7 +17154,7 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/global-modules": {
|
||||
"node_modules/global-modules": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
|
||||
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
|
||||
@@ -17291,7 +17291,7 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||
},
|
||||
"node_modules/grunt": {
|
||||
"node_modules/grunt": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.1.tgz",
|
||||
"integrity": "sha512-/ABUy3gYWu5iBmrUSRBP97JLpQUm0GgVveDCp6t3yRNIoltIYw7rEj3g5y1o2PGPR2vfTRGa7WC/LZHLTXnEzA==",
|
||||
@@ -17367,7 +17367,7 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
||||
"integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ=="
|
||||
},
|
||||
"node_modules/grunt-known-options": {
|
||||
"node_modules/grunt-known-options": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz",
|
||||
"integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==",
|
||||
@@ -17777,7 +17777,7 @@
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/homedir-polyfill": {
|
||||
"node_modules/homedir-polyfill": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
||||
"integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
|
||||
@@ -18161,7 +18161,7 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/interpret": {
|
||||
"node_modules/interpret": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
|
||||
"integrity": "sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==",
|
||||
@@ -18196,7 +18196,7 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/is-absolute": {
|
||||
"node_modules/is-absolute": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
|
||||
"integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
|
||||
@@ -18610,7 +18610,7 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-relative": {
|
||||
"node_modules/is-relative": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
|
||||
"integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
|
||||
@@ -18713,7 +18713,7 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-unc-path": {
|
||||
"node_modules/is-unc-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
|
||||
"integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
|
||||
@@ -22324,7 +22324,7 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/liftup": {
|
||||
"node_modules/liftup": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz",
|
||||
"integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==",
|
||||
@@ -22402,7 +22402,7 @@
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-x64": {
|
||||
"node_modules/lightningcss-darwin-x64": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz",
|
||||
"integrity": "sha512-Lif1wD6P4poaw9c/4Uh2z+gmrWhw/HtXFoeZ3bEsv6Ia4tt8rOJBdkfVaUJ6VXmpKHALve+iTyP2+50xY1wKPw==",
|
||||
@@ -23006,7 +23006,7 @@
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/make-iterator": {
|
||||
"node_modules/make-iterator": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
|
||||
"integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==",
|
||||
@@ -24420,14 +24420,16 @@
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mosip-inji-face-sdk": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/mosip-inji-face-sdk/-/mosip-inji-face-sdk-0.1.12.tgz",
|
||||
"integrity": "sha512-lnoaa2lL0pS9u/9fwH4Q9OU2U56oqjXf2z4JjGxX80DQOqJGWvj49PfvPMYGFEfVucqIJyQBZUfvfpqfYO0+vw==",
|
||||
"node_modules/mosip-mobileid-sdk": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "git+ssh://git@github.com/mosip/mosip-mobileid-sdk.git#ff4647a6c949b0acf8f36ae968dcbd407df7fb83",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-fs": "*"
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
@@ -24709,7 +24711,7 @@
|
||||
"url": "https://github.com/sponsors/antelle"
|
||||
}
|
||||
},
|
||||
"node_modules/nopt": {
|
||||
"node_modules/nopt": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
||||
"integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
|
||||
@@ -24959,7 +24961,7 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/object.defaults": {
|
||||
"node_modules/object.defaults": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
|
||||
"integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==",
|
||||
@@ -25027,7 +25029,7 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/object.map": {
|
||||
"node_modules/object.map": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
|
||||
"integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==",
|
||||
@@ -25365,7 +25367,7 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-filepath": {
|
||||
"node_modules/parse-filepath": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
|
||||
"integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==",
|
||||
@@ -25391,7 +25393,7 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-passwd": {
|
||||
"node_modules/parse-passwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
|
||||
"integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==",
|
||||
@@ -25703,7 +25705,7 @@
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
},
|
||||
"node_modules/path-root": {
|
||||
"node_modules/path-root": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
|
||||
"integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==",
|
||||
@@ -26413,7 +26415,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"node_modules/react-dom": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz",
|
||||
"integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==",
|
||||
@@ -26750,7 +26752,7 @@
|
||||
"react-native": ">0.62.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-flipper-xstate/node_modules/ws": {
|
||||
"node_modules/react-native-flipper-xstate/node_modules/ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
@@ -27613,7 +27615,7 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||
},
|
||||
"node_modules/rechoir": {
|
||||
"node_modules/rechoir": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
|
||||
"integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
|
||||
@@ -27864,7 +27866,7 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-dir": {
|
||||
"node_modules/resolve-dir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
|
||||
"integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==",
|
||||
@@ -29562,9 +29564,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/telemetry-sdk": {
|
||||
"name": "@project-sunbird/telemetry-sdk",
|
||||
"version": "0.0.21",
|
||||
"resolved": "git+ssh://git@github.com/mosip/sunbird-telemetry-sdk.git#7ff643a81acd54ddb2ad8ad588314004513a3749",
|
||||
"resolved": "git+ssh://git@github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
|
||||
"integrity": "sha512-aeA7uO77JzNQVSuUpxzUXK3I+BtYiOzDhcmYbD6R3pAETun4toP1/GR5PBfT9/iE3N5MdGJg70sQArwCIL1XaQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
@@ -30201,7 +30203,7 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/unc-path-regex": {
|
||||
"node_modules/unc-path-regex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
||||
"integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==",
|
||||
@@ -30598,7 +30600,7 @@
|
||||
"node": ">=10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/v8flags": {
|
||||
"node_modules/v8flags": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz",
|
||||
"integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==",
|
||||
@@ -38294,7 +38296,7 @@
|
||||
"json-parse-even-better-errors": "^2.3.0",
|
||||
"lines-and-columns": "^1.1.6"
|
||||
}
|
||||
},
|
||||
},
|
||||
"typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
@@ -38361,7 +38363,7 @@
|
||||
"json-parse-even-better-errors": "^2.3.0",
|
||||
"lines-and-columns": "^1.1.6"
|
||||
}
|
||||
},
|
||||
},
|
||||
"typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
@@ -38747,7 +38749,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
|
||||
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="
|
||||
},
|
||||
"abbrev": {
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||
@@ -38962,7 +38964,7 @@
|
||||
"is-array-buffer": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"array-each": {
|
||||
"array-each": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
|
||||
"integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==",
|
||||
@@ -40771,7 +40773,7 @@
|
||||
"resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz",
|
||||
"integrity": "sha512-lAJqBmFzCLcDJdI9cEnJ7loSkLTh1PbIgZUndlzvYbf6NyFEr5n9rQhOwr6CIGwZqyQ3sYeQQiP9NOVQmgmRMA=="
|
||||
},
|
||||
"dateformat": {
|
||||
"dateformat": {
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
|
||||
"integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
|
||||
@@ -41028,7 +41030,7 @@
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
|
||||
},
|
||||
"detect-file": {
|
||||
"detect-file": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
|
||||
"integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==",
|
||||
@@ -41209,7 +41211,7 @@
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"encoding": {
|
||||
"encoding": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
||||
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
||||
@@ -41887,7 +41889,7 @@
|
||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||
},
|
||||
"eventemitter2": {
|
||||
"eventemitter2": {
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
|
||||
"integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==",
|
||||
@@ -42080,7 +42082,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"expand-tilde": {
|
||||
"expand-tilde": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
|
||||
"integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==",
|
||||
@@ -43163,7 +43165,7 @@
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.5.1.tgz",
|
||||
"integrity": "sha512-yt5a1VCp2BF9CrsO689PCD5oXKP14MMhnOanQMvDn4BDpURYfzAlDVGC5fZrNQKtwn/eq3bcrxIwZ7D9QjVVRg==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@expo/config": "~8.1.0",
|
||||
"chalk": "^4.1.0",
|
||||
@@ -43177,7 +43179,7 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
@@ -43186,7 +43188,7 @@
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
@@ -43196,7 +43198,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
@@ -43217,7 +43219,7 @@
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
@@ -43235,7 +43237,7 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"peer": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
@@ -43817,7 +43819,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"findup-sync": {
|
||||
"findup-sync": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz",
|
||||
"integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==",
|
||||
@@ -43892,7 +43894,7 @@
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
"integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
|
||||
},
|
||||
"for-own": {
|
||||
"for-own": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
|
||||
"integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==",
|
||||
@@ -44039,7 +44041,7 @@
|
||||
"resolved": "https://registry.npmjs.org/getenv/-/getenv-1.0.0.tgz",
|
||||
"integrity": "sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg=="
|
||||
},
|
||||
"getobject": {
|
||||
"getobject": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz",
|
||||
"integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==",
|
||||
@@ -44088,7 +44090,7 @@
|
||||
"is-glob": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"global-modules": {
|
||||
"global-modules": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
|
||||
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
|
||||
@@ -44193,7 +44195,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"grunt": {
|
||||
"grunt": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.1.tgz",
|
||||
"integrity": "sha512-/ABUy3gYWu5iBmrUSRBP97JLpQUm0GgVveDCp6t3yRNIoltIYw7rEj3g5y1o2PGPR2vfTRGa7WC/LZHLTXnEzA==",
|
||||
@@ -44307,7 +44309,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"grunt-known-options": {
|
||||
"grunt-known-options": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz",
|
||||
"integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==",
|
||||
@@ -44570,7 +44572,7 @@
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"homedir-polyfill": {
|
||||
"homedir-polyfill": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
||||
"integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
|
||||
@@ -44834,7 +44836,7 @@
|
||||
"side-channel": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"interpret": {
|
||||
"interpret": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
|
||||
"integrity": "sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==",
|
||||
@@ -44863,7 +44865,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||
},
|
||||
"is-absolute": {
|
||||
"is-absolute": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
|
||||
"integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
|
||||
@@ -45135,7 +45137,7 @@
|
||||
"has-tostringtag": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-relative": {
|
||||
"is-relative": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
|
||||
"integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
|
||||
@@ -45199,7 +45201,7 @@
|
||||
"which-typed-array": "^1.1.11"
|
||||
}
|
||||
},
|
||||
"is-unc-path": {
|
||||
"is-unc-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
|
||||
"integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
|
||||
@@ -47942,7 +47944,7 @@
|
||||
"type-check": "~0.4.0"
|
||||
}
|
||||
},
|
||||
"liftup": {
|
||||
"liftup": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz",
|
||||
"integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==",
|
||||
@@ -47994,7 +47996,7 @@
|
||||
"integrity": "sha512-wIJmFtYX0rXHsXHSr4+sC5clwblEMji7HHQ4Ub1/CznVRxtCFha6JIt5JZaNf8vQrfdZnBxLLC6R8pC818jXqg==",
|
||||
"optional": true
|
||||
},
|
||||
"lightningcss-darwin-x64": {
|
||||
"lightningcss-darwin-x64": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz",
|
||||
"integrity": "sha512-Lif1wD6P4poaw9c/4Uh2z+gmrWhw/HtXFoeZ3bEsv6Ia4tt8rOJBdkfVaUJ6VXmpKHALve+iTyP2+50xY1wKPw==",
|
||||
@@ -48398,7 +48400,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"make-iterator": {
|
||||
"make-iterator": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
|
||||
"integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==",
|
||||
@@ -49542,11 +49544,9 @@
|
||||
"minimist": "^1.2.6"
|
||||
}
|
||||
},
|
||||
"mosip-inji-face-sdk": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/mosip-inji-face-sdk/-/mosip-inji-face-sdk-0.1.12.tgz",
|
||||
"integrity": "sha512-lnoaa2lL0pS9u/9fwH4Q9OU2U56oqjXf2z4JjGxX80DQOqJGWvj49PfvPMYGFEfVucqIJyQBZUfvfpqfYO0+vw==",
|
||||
"requires": {}
|
||||
"mosip-mobileid-sdk": {
|
||||
"version": "git+ssh://git@github.com/mosip/mosip-mobileid-sdk.git#ff4647a6c949b0acf8f36ae968dcbd407df7fb83",
|
||||
"from": "mosip-mobileid-sdk@git://github.com/mosip/mosip-mobileid-sdk.git#IrisScan"
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
@@ -49764,7 +49764,7 @@
|
||||
"resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz",
|
||||
"integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw=="
|
||||
},
|
||||
"nopt": {
|
||||
"nopt": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
||||
"integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
|
||||
@@ -49956,7 +49956,7 @@
|
||||
"object-keys": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"object.defaults": {
|
||||
"object.defaults": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
|
||||
"integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==",
|
||||
@@ -50008,7 +50008,7 @@
|
||||
"es-abstract": "^1.22.1"
|
||||
}
|
||||
},
|
||||
"object.map": {
|
||||
"object.map": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
|
||||
"integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==",
|
||||
@@ -50256,7 +50256,7 @@
|
||||
"callsites": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"parse-filepath": {
|
||||
"parse-filepath": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
|
||||
"integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==",
|
||||
@@ -50276,7 +50276,7 @@
|
||||
"json-parse-better-errors": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"parse-passwd": {
|
||||
"parse-passwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
|
||||
"integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==",
|
||||
@@ -50505,7 +50505,7 @@
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
},
|
||||
"path-root": {
|
||||
"path-root": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
|
||||
"integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==",
|
||||
@@ -51920,7 +51920,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"rechoir": {
|
||||
"rechoir": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
|
||||
"integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
|
||||
@@ -52118,7 +52118,7 @@
|
||||
"resolve-from": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"resolve-dir": {
|
||||
"resolve-dir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
|
||||
"integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==",
|
||||
@@ -53473,8 +53473,9 @@
|
||||
}
|
||||
},
|
||||
"telemetry-sdk": {
|
||||
"version": "git+ssh://git@github.com/mosip/sunbird-telemetry-sdk.git#7ff643a81acd54ddb2ad8ad588314004513a3749",
|
||||
"from": "telemetry-sdk@git://github.com/mosip/sunbird-telemetry-sdk.git#develop",
|
||||
"version": "git+ssh://git@github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
|
||||
"integrity": "sha512-aeA7uO77JzNQVSuUpxzUXK3I+BtYiOzDhcmYbD6R3pAETun4toP1/GR5PBfT9/iE3N5MdGJg70sQArwCIL1XaQ==",
|
||||
"from": "telemetry-sdk@git://github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
|
||||
"requires": {
|
||||
"axios": "^1.4.0",
|
||||
"grunt-karma": "^0.12.2",
|
||||
@@ -53930,7 +53931,7 @@
|
||||
"which-boxed-primitive": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"unc-path-regex": {
|
||||
"unc-path-regex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
||||
"integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==",
|
||||
@@ -54232,7 +54233,7 @@
|
||||
"convert-source-map": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"v8flags": {
|
||||
"v8flags": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz",
|
||||
"integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==",
|
||||
|
||||
11
package.json
11
package.json
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"scripts": {
|
||||
"prepare": "husky install",
|
||||
"jetify": "jetify",
|
||||
"start": "react-native start",
|
||||
"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"
|
||||
"postinstall": "patch-package && npm run jetify && sh tools/talisman/talisman-precommit.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@digitalbazaar/ed25519-signature-2018": "digitalbazaar/ed25519-signature-2018",
|
||||
@@ -44,7 +44,7 @@
|
||||
"i18next": "^21.6.16",
|
||||
"iso-639-3": "^3.0.1",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"mosip-inji-face-sdk": "^0.1.12",
|
||||
"mosip-mobileid-sdk": "git://github.com/mosip/mosip-mobileid-sdk.git#IrisScan",
|
||||
"node-forge": "^1.3.1",
|
||||
"node-jose": "^2.2.0",
|
||||
"patch-package": "^6.5.1",
|
||||
@@ -86,7 +86,7 @@
|
||||
"react-native-vector-icons": "^10.0.0",
|
||||
"short-unique-id": "^4.4.4",
|
||||
"simple-pem2jwk": "^0.2.4",
|
||||
"telemetry-sdk": "git://github.com/mosip/sunbird-telemetry-sdk.git#develop",
|
||||
"telemetry-sdk": "git://github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
|
||||
"xstate": "^4.35.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -126,8 +126,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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,24 @@ import {Button, Column, Text} from '../components/ui';
|
||||
import {Theme} from '../components/ui/styleUtils';
|
||||
import {RootRouteProps} from '../routes';
|
||||
import {useAuthScreen} from './AuthScreenController';
|
||||
import {
|
||||
getStartEventData,
|
||||
getInteractEventData,
|
||||
sendInteractEvent,
|
||||
sendStartEvent,
|
||||
} from '../shared/telemetry/TelemetryUtils';
|
||||
|
||||
export const AuthScreen: React.FC<RootRouteProps> = props => {
|
||||
const {t} = useTranslation('AuthScreen');
|
||||
const controller = useAuthScreen(props);
|
||||
|
||||
const handleUsePasscodeButtonPress = () => {
|
||||
sendStartEvent(getStartEventData('App Onboarding'));
|
||||
sendInteractEvent(
|
||||
getInteractEventData('App Onboarding', 'TOUCH', 'Use Passcode Button'),
|
||||
);
|
||||
controller.usePasscode();
|
||||
};
|
||||
return (
|
||||
<Column
|
||||
fill
|
||||
@@ -27,12 +40,14 @@ export const AuthScreen: React.FC<RootRouteProps> = props => {
|
||||
<Column margin="30 0 0 0">
|
||||
<Text
|
||||
testID="selectAppUnlockMethod"
|
||||
style={{paddingTop: 3}}
|
||||
align="center"
|
||||
style={Theme.TextStyles.header}>
|
||||
{t('header')}
|
||||
</Text>
|
||||
<Text
|
||||
align="center"
|
||||
style={{paddingTop: 3}}
|
||||
weight="semibold"
|
||||
color={Theme.Colors.GrayText}
|
||||
margin="6 0">
|
||||
@@ -54,7 +69,7 @@ export const AuthScreen: React.FC<RootRouteProps> = props => {
|
||||
testID="usePasscode"
|
||||
type="clear"
|
||||
title={t('usePasscode')}
|
||||
onPress={controller.usePasscode}
|
||||
onPress={() => handleUsePasscodeButtonPress()}
|
||||
/>
|
||||
</Column>
|
||||
</Column>
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { useMachine, useSelector } from '@xstate/react';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import {useMachine, useSelector} from '@xstate/react';
|
||||
import {useContext, useEffect, useState} from 'react';
|
||||
import * as LocalAuthentication from 'expo-local-authentication';
|
||||
|
||||
import {
|
||||
AuthEvents,
|
||||
selectSettingUp,
|
||||
selectAuthorized,
|
||||
} from '../machines/auth';
|
||||
import { RootRouteProps } from '../routes';
|
||||
import { GlobalContext } from '../shared/GlobalContext';
|
||||
import {AuthEvents, selectSettingUp, selectAuthorized} from '../machines/auth';
|
||||
import {RootRouteProps} from '../routes';
|
||||
import {GlobalContext} from '../shared/GlobalContext';
|
||||
import {
|
||||
biometricsMachine,
|
||||
selectError,
|
||||
@@ -16,12 +12,23 @@ import {
|
||||
selectIsSuccess,
|
||||
selectIsUnvailable,
|
||||
selectUnenrolledNotice,
|
||||
selectErrorResponse,
|
||||
} from '../machines/biometrics';
|
||||
import { SettingsEvents } from '../machines/settings';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {SettingsEvents} from '../machines/settings';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {
|
||||
sendStartEvent,
|
||||
sendImpressionEvent,
|
||||
sendInteractEvent,
|
||||
getStartEventData,
|
||||
getInteractEventData,
|
||||
getImpressionEventData,
|
||||
getEndEventData,
|
||||
sendEndEvent,
|
||||
} from '../shared/telemetry/TelemetryUtils';
|
||||
|
||||
export function useAuthScreen(props: RootRouteProps) {
|
||||
const { appService } = useContext(GlobalContext);
|
||||
const {appService} = useContext(GlobalContext);
|
||||
const authService = appService.children.get('auth');
|
||||
const settingsService = appService.children.get('settings');
|
||||
|
||||
@@ -38,12 +45,13 @@ export function useAuthScreen(props: RootRouteProps) {
|
||||
const isSuccessBio = useSelector(bioService, selectIsSuccess);
|
||||
const errorMsgBio = useSelector(bioService, selectError);
|
||||
const unEnrolledNoticeBio = useSelector(bioService, selectUnenrolledNotice);
|
||||
const errorResponse = useSelector(bioService, selectErrorResponse);
|
||||
|
||||
const usePasscode = () => {
|
||||
props.navigation.navigate('Passcode', { setup: isSettingUp });
|
||||
props.navigation.navigate('Passcode', {setup: isSettingUp});
|
||||
};
|
||||
|
||||
const { t } = useTranslation('AuthScreen');
|
||||
const {t} = useTranslation('AuthScreen');
|
||||
|
||||
const fetchIsAvailable = async () => {
|
||||
const result = await LocalAuthentication.hasHardwareAsync();
|
||||
@@ -53,10 +61,12 @@ export function useAuthScreen(props: RootRouteProps) {
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthorized) {
|
||||
sendEndEvent(getEndEventData('App Onboarding', 'SUCCESS'));
|
||||
props.navigation.reset({
|
||||
index: 0,
|
||||
routes: [{ name: 'Main' }],
|
||||
routes: [{name: 'Main'}],
|
||||
});
|
||||
sendImpressionEvent(getImpressionEventData('App Onboarding', 'Home'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -69,8 +79,17 @@ export function useAuthScreen(props: RootRouteProps) {
|
||||
|
||||
// handle biometric failure unknown error
|
||||
} else if (errorMsgBio) {
|
||||
sendEndEvent(
|
||||
getEndEventData('App Onboarding', 'FAILURE', {
|
||||
errorId: errorResponse.res.error,
|
||||
errorMessage: errorResponse.res.warning,
|
||||
stackTrace: errorResponse.stacktrace,
|
||||
}),
|
||||
);
|
||||
// show alert message whenever biometric state gets failure
|
||||
setHasAlertMsg(t(errorMsgBio));
|
||||
if (errorResponse.res.error !== 'user_cancel') {
|
||||
setHasAlertMsg(t(errorMsgBio));
|
||||
}
|
||||
|
||||
// handle any unenrolled notice
|
||||
} else if (unEnrolledNoticeBio) {
|
||||
@@ -78,6 +97,7 @@ export function useAuthScreen(props: RootRouteProps) {
|
||||
|
||||
// we dont need to see this page to user once biometric is unavailable on its device
|
||||
} else if (isUnavailableBio) {
|
||||
sendStartEvent(getStartEventData('App Onboarding'));
|
||||
usePasscode();
|
||||
}
|
||||
}, [isSuccessBio, isUnavailableBio, errorMsgBio, unEnrolledNoticeBio]);
|
||||
@@ -85,12 +105,21 @@ export function useAuthScreen(props: RootRouteProps) {
|
||||
const useBiometrics = async () => {
|
||||
const isBiometricsEnrolled = await LocalAuthentication.isEnrolledAsync();
|
||||
if (isBiometricsEnrolled) {
|
||||
if (biometricState.matches({ failure: 'unenrolled' })) {
|
||||
biometricSend({ type: 'RETRY_AUTHENTICATE' });
|
||||
sendStartEvent(getStartEventData('App Onboarding'));
|
||||
sendInteractEvent(
|
||||
getInteractEventData(
|
||||
'App Onboarding',
|
||||
'TOUCH',
|
||||
'Use Biometrics Button',
|
||||
),
|
||||
);
|
||||
|
||||
if (biometricState.matches({failure: 'unenrolled'})) {
|
||||
biometricSend({type: 'RETRY_AUTHENTICATE'});
|
||||
return;
|
||||
}
|
||||
|
||||
biometricSend({ type: 'AUTHENTICATE' });
|
||||
biometricSend({type: 'AUTHENTICATE'});
|
||||
} else {
|
||||
setHasAlertMsg(t('errors.unenrolled'));
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"unlock": "Unlock with biometrics"
|
||||
}
|
||||
@@ -1,17 +1,26 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import { Button, Centered, Column } from '../components/ui';
|
||||
import { Theme } from '../components/ui/styleUtils';
|
||||
import { RootRouteProps } from '../routes';
|
||||
import { useBiometricScreen } from './BiometricScreenController';
|
||||
import { Passcode } from '../components/Passcode';
|
||||
import React, {useEffect} from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {TouchableOpacity} from 'react-native';
|
||||
import {Icon} from 'react-native-elements';
|
||||
import {Button, Centered, Column} from '../components/ui';
|
||||
import {Theme} from '../components/ui/styleUtils';
|
||||
import {RootRouteProps} from '../routes';
|
||||
import {useBiometricScreen} from './BiometricScreenController';
|
||||
import {Passcode} from '../components/Passcode';
|
||||
import {
|
||||
getEventType,
|
||||
incrementPasscodeRetryCount,
|
||||
} from '../shared/telemetry/TelemetryUtils';
|
||||
|
||||
export const BiometricScreen: React.FC<RootRouteProps> = (props) => {
|
||||
const { t } = useTranslation('BiometricScreen');
|
||||
export const BiometricScreen: React.FC<RootRouteProps> = props => {
|
||||
const {t} = useTranslation('BiometricScreen');
|
||||
const controller = useBiometricScreen(props);
|
||||
|
||||
const handlePasscodeMismatch = (error: string) => {
|
||||
incrementPasscodeRetryCount(getEventType(props.route.params?.setup));
|
||||
controller.onError(error);
|
||||
};
|
||||
|
||||
return (
|
||||
<Column
|
||||
fill
|
||||
@@ -34,10 +43,11 @@ export const BiometricScreen: React.FC<RootRouteProps> = (props) => {
|
||||
<Passcode
|
||||
message="Enter your passcode to re-enable biometrics authentication."
|
||||
onSuccess={() => controller.onSuccess()}
|
||||
onError={(value: string) => controller.onError(value)}
|
||||
onError={handlePasscodeMismatch}
|
||||
storedPasscode={controller.storedPasscode}
|
||||
onDismiss={() => controller.onDismiss()}
|
||||
error={controller.error}
|
||||
salt={controller.passcodeSalt}
|
||||
/>
|
||||
)}
|
||||
</Column>
|
||||
|
||||
@@ -1,20 +1,38 @@
|
||||
import { useMachine, useSelector } from '@xstate/react';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import {useMachine, useSelector} from '@xstate/react';
|
||||
import {useContext, useEffect, useState} from 'react';
|
||||
import {Platform} from 'react-native';
|
||||
import RNFingerprintChange from 'react-native-biometrics-changed';
|
||||
import { AuthEvents, selectAuthorized, selectPasscode } from '../machines/auth';
|
||||
import { RootRouteProps } from '../routes';
|
||||
import { GlobalContext } from '../shared/GlobalContext';
|
||||
import {
|
||||
AuthEvents,
|
||||
selectAuthorized,
|
||||
selectPasscode,
|
||||
selectPasscodeSalt,
|
||||
} from '../machines/auth';
|
||||
import {
|
||||
biometricsMachine,
|
||||
selectError,
|
||||
selectErrorResponse,
|
||||
selectIsAvailable,
|
||||
selectIsSuccess,
|
||||
selectIsUnenrolled,
|
||||
selectIsUnvailable,
|
||||
} from '../machines/biometrics';
|
||||
import { Platform } from 'react-native';
|
||||
import {RootRouteProps} from '../routes';
|
||||
import {GlobalContext} from '../shared/GlobalContext';
|
||||
import {
|
||||
getStartEventData,
|
||||
getEndEventData,
|
||||
getImpressionEventData,
|
||||
getInteractEventData,
|
||||
sendEndEvent,
|
||||
sendImpressionEvent,
|
||||
sendInteractEvent,
|
||||
sendStartEvent,
|
||||
} from '../shared/telemetry/TelemetryUtils';
|
||||
import {isAndroid} from '../shared/constants';
|
||||
|
||||
export function useBiometricScreen(props: RootRouteProps) {
|
||||
const { appService } = useContext(GlobalContext);
|
||||
const {appService} = useContext(GlobalContext);
|
||||
const authService = appService.children.get('auth');
|
||||
|
||||
const [error, setError] = useState('');
|
||||
@@ -27,12 +45,29 @@ export function useBiometricScreen(props: RootRouteProps) {
|
||||
const isUnavailable = useSelector(bioService, selectIsUnvailable);
|
||||
const isSuccessBio = useSelector(bioService, selectIsSuccess);
|
||||
const isUnenrolled = useSelector(bioService, selectIsUnenrolled);
|
||||
const errorMsgBio = useSelector(bioService, selectError);
|
||||
const errorResponse = useSelector(bioService, selectErrorResponse);
|
||||
const passcodeSalt = useSelector(authService, selectPasscodeSalt);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAvailable) {
|
||||
sendStartEvent(getStartEventData('App login'));
|
||||
sendInteractEvent(
|
||||
getInteractEventData(
|
||||
'App login',
|
||||
'TOUCH',
|
||||
'Unlock with Biometrics button',
|
||||
),
|
||||
);
|
||||
}
|
||||
}, [isAvailable]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthorized) {
|
||||
sendEndEvent(getEndEventData('App Login', 'SUCCESS'));
|
||||
props.navigation.reset({
|
||||
index: 0,
|
||||
routes: [{ name: 'Main' }],
|
||||
routes: [{name: 'Main'}],
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -50,25 +85,46 @@ export function useBiometricScreen(props: RootRouteProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (errorMsgBio && !isReEnabling) {
|
||||
sendEndEvent(
|
||||
getEndEventData('App Login', 'FAILURE', {
|
||||
errorId: errorResponse.res.error,
|
||||
errorMessage: errorResponse.res.warning,
|
||||
stackTrace: errorResponse.stacktrace,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (isUnavailable || isUnenrolled) {
|
||||
props.navigation.reset({
|
||||
index: 0,
|
||||
routes: [{ name: 'Passcode' }],
|
||||
routes: [{name: 'Passcode'}],
|
||||
});
|
||||
sendStartEvent(getStartEventData('App Login'));
|
||||
sendInteractEvent(
|
||||
getInteractEventData('App Login', 'TOUCH', 'Unlock application button'),
|
||||
);
|
||||
}
|
||||
}, [isAuthorized, isAvailable, isUnenrolled, isUnavailable, isSuccessBio]);
|
||||
}, [
|
||||
isAuthorized,
|
||||
isAvailable,
|
||||
isUnenrolled,
|
||||
isUnavailable,
|
||||
isSuccessBio,
|
||||
errorMsgBio,
|
||||
]);
|
||||
|
||||
const checkBiometricsChange = () => {
|
||||
if (Platform.OS === 'android') {
|
||||
if (isAndroid()) {
|
||||
RNFingerprintChange.hasFingerPrintChanged().then(
|
||||
async (biometricsHasChanged: boolean) => {
|
||||
//if new biometrics are added, re-enable Biometrics Authentication
|
||||
if (biometricsHasChanged) {
|
||||
setReEnabling(true);
|
||||
} else {
|
||||
bioSend({ type: 'AUTHENTICATE' });
|
||||
bioSend({type: 'AUTHENTICATE'});
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// TODO: solution for iOS
|
||||
@@ -76,11 +132,20 @@ export function useBiometricScreen(props: RootRouteProps) {
|
||||
};
|
||||
|
||||
const useBiometrics = () => {
|
||||
bioSend({ type: 'AUTHENTICATE' });
|
||||
sendStartEvent(getStartEventData('App login'));
|
||||
sendInteractEvent(
|
||||
getInteractEventData(
|
||||
'App Login',
|
||||
'TOUCH',
|
||||
'Unlock with biometrics button',
|
||||
),
|
||||
);
|
||||
bioSend({type: 'AUTHENTICATE'});
|
||||
};
|
||||
|
||||
const onSuccess = () => {
|
||||
bioSend({ type: 'AUTHENTICATE' });
|
||||
bioSend({type: 'AUTHENTICATE'});
|
||||
setError('');
|
||||
};
|
||||
|
||||
const onError = (value: string) => {
|
||||
@@ -88,6 +153,12 @@ export function useBiometricScreen(props: RootRouteProps) {
|
||||
};
|
||||
|
||||
const onDismiss = () => {
|
||||
sendEndEvent(
|
||||
getEndEventData('App Login', 'FAILURE', {
|
||||
errorId: 'user_cancel',
|
||||
errorMessage: 'Authentication canceled',
|
||||
}),
|
||||
);
|
||||
setReEnabling(false);
|
||||
};
|
||||
|
||||
@@ -95,6 +166,7 @@ export function useBiometricScreen(props: RootRouteProps) {
|
||||
error,
|
||||
isReEnabling,
|
||||
isSuccessBio,
|
||||
passcodeSalt,
|
||||
storedPasscode: useSelector(authService, selectPasscode),
|
||||
useBiometrics,
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"noHistory": "No history available yet",
|
||||
"downloaded": "downloaded",
|
||||
"shared": "shared",
|
||||
"received": "received",
|
||||
"deleted": "deleted"
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
import React from 'react';
|
||||
import { RefreshControl } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Centered, Column, Text } from '../../components/ui';
|
||||
import { useHistoryTab } from './HistoryScreenController';
|
||||
import { ActivityLogText } from '../../components/ActivityLogText';
|
||||
import { MainRouteProps } from '../../routes/main';
|
||||
import { Theme } from '../../components/ui/styleUtils';
|
||||
import {RefreshControl} from 'react-native';
|
||||
import {Icon} from 'react-native-elements';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {Centered, Column, Text} from '../../components/ui';
|
||||
import {useHistoryTab} from './HistoryScreenController';
|
||||
import {ActivityLogText} from '../../components/ActivityLogText';
|
||||
import {MainRouteProps} from '../../routes/main';
|
||||
import {Theme} from '../../components/ui/styleUtils';
|
||||
|
||||
export const HistoryScreen: React.FC<MainRouteProps> = () => {
|
||||
const { t } = useTranslation('HistoryScreen');
|
||||
const {t} = useTranslation('HistoryScreen');
|
||||
const controller = useHistoryTab();
|
||||
|
||||
return (
|
||||
@@ -23,7 +23,7 @@ export const HistoryScreen: React.FC<MainRouteProps> = () => {
|
||||
onRefresh={controller.REFRESH}
|
||||
/>
|
||||
}>
|
||||
{controller.activities.map((activity) => (
|
||||
{controller.activities.map(activity => (
|
||||
<ActivityLogText
|
||||
key={`${activity.timestamp}-${activity._vcKey}`}
|
||||
activity={activity}
|
||||
@@ -32,11 +32,15 @@ export const HistoryScreen: React.FC<MainRouteProps> = () => {
|
||||
{controller.activities.length === 0 && (
|
||||
<Centered fill>
|
||||
<Icon
|
||||
style={{ marginBottom: 20 }}
|
||||
style={{marginBottom: 20}}
|
||||
size={40}
|
||||
name="sentiment-dissatisfied"
|
||||
/>
|
||||
<Text align="center" weight="semibold" margin="0 0 4 0">
|
||||
<Text
|
||||
align="center"
|
||||
style={{paddingTop: 3}}
|
||||
weight="semibold"
|
||||
margin="0 0 4 0">
|
||||
{t('noHistory')}
|
||||
</Text>
|
||||
</Centered>
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"myVcsTab": "My\nCards",
|
||||
"receivedVcsTab": "Received\nCards",
|
||||
"historyTab": "History"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import {Icon, Tab} from 'react-native-elements';
|
||||
import {Button, Column, Text} from '../../components/ui';
|
||||
import {Column, Text} from '../../components/ui';
|
||||
import {Theme} from '../../components/ui/styleUtils';
|
||||
import {HomeRouteProps} from '../../routes/main';
|
||||
import {MyVcsTab} from './MyVcsTab';
|
||||
@@ -11,10 +11,10 @@ import {TabRef} from './HomeScreenMachine';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {ActorRefFrom} from 'xstate';
|
||||
import {ExistingMosipVCItemMachine} from '../../machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine';
|
||||
import {isOpenId4VCIEnabled} from '../../shared/openId4VCI/Utils';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import {EsignetMosipVCItemMachine} from '../../machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine';
|
||||
import {ErrorMessageOverlay} from '../../components/MessageOverlay';
|
||||
import {Pressable} from 'react-native';
|
||||
|
||||
export const HomeScreen: React.FC<HomeRouteProps> = props => {
|
||||
const {t} = useTranslation('HomeScreen');
|
||||
@@ -44,16 +44,19 @@ export const HomeScreen: React.FC<HomeRouteProps> = props => {
|
||||
return (
|
||||
<LinearGradient
|
||||
colors={Theme.Colors.gradientBtn}
|
||||
style={Theme.Styles.downloadFabIcon}>
|
||||
<Button
|
||||
testID="downloadIcon"
|
||||
icon={plusIcon}
|
||||
style={Theme.Styles.downloadFabIconContainer}>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
controller.GOTO_ISSUERS();
|
||||
}}
|
||||
type={'clearAddIdBtnBg'}
|
||||
fill
|
||||
/>
|
||||
testID="downloadIcon"
|
||||
style={({pressed}) =>
|
||||
pressed
|
||||
? Theme.Styles.downloadFabIconPressed
|
||||
: Theme.Styles.downloadFabIconNormal
|
||||
}>
|
||||
{plusIcon}
|
||||
</Pressable>
|
||||
</LinearGradient>
|
||||
);
|
||||
};
|
||||
@@ -76,7 +79,7 @@ export const HomeScreen: React.FC<HomeRouteProps> = props => {
|
||||
</Column>
|
||||
)}
|
||||
</Column>
|
||||
{isOpenId4VCIEnabled() && <DownloadFABIcon />}
|
||||
<DownloadFABIcon />
|
||||
<ErrorMessageOverlay
|
||||
translationPath={'MyVcsTab'}
|
||||
isVisible={controller.isMinimumStorageLimitReached}
|
||||
|
||||
@@ -25,13 +25,13 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
|
||||
key: 'two',
|
||||
title: t('stepTwoTitle'),
|
||||
text: t('stepTwoText'),
|
||||
image: Theme.sharingIntro,
|
||||
image: Theme.walletIntro,
|
||||
},
|
||||
{
|
||||
key: 'three',
|
||||
title: t('stepThreeTitle'),
|
||||
text: t('stepThreeText'),
|
||||
image: Theme.walletIntro,
|
||||
image: Theme.sharingIntro,
|
||||
},
|
||||
{
|
||||
key: 'four',
|
||||
@@ -64,34 +64,45 @@ 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}
|
||||
styles={{height: 150}}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
testID="skip"
|
||||
type="plain"
|
||||
title={t('skip')}
|
||||
onPress={controller.NEXT}
|
||||
styles={{height: 150}}
|
||||
/>
|
||||
)}
|
||||
</Column>
|
||||
</Row>
|
||||
<Image source={item.image} />
|
||||
<Image
|
||||
source={item.image}
|
||||
resizeMode="contain"
|
||||
style={{height: Dimensions.get('screen').height * 0.6}}
|
||||
/>
|
||||
<Column
|
||||
testID="introSlide"
|
||||
style={Theme.OnboardingOverlayStyles.bottomContainer}
|
||||
crossAlign="center"
|
||||
backgroundColor={Theme.Colors.whiteText}
|
||||
width={Dimensions.get('screen').width}>
|
||||
<Text testID="introTitle" weight="semibold" margin="0 0 18 0">
|
||||
<Text
|
||||
testID="introTitle"
|
||||
style={{paddingTop: 3}}
|
||||
weight="semibold"
|
||||
margin="0 0 18 0">
|
||||
{item.title}
|
||||
</Text>
|
||||
<Text
|
||||
testID="introText"
|
||||
style={{paddingTop: 7}}
|
||||
margin="0 0 150 0"
|
||||
size="large"
|
||||
color={Theme.Colors.GrayText}>
|
||||
@@ -111,6 +122,7 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
|
||||
style={{borderRadius: 10, height: 50, marginTop: -10}}>
|
||||
<Text
|
||||
testID="next"
|
||||
style={{paddingTop: 3}}
|
||||
weight="semibold"
|
||||
align="center"
|
||||
color="#FFFFFF"
|
||||
@@ -129,11 +141,12 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
|
||||
style={{borderRadius: 10, height: 50, marginTop: -10}}>
|
||||
<Text
|
||||
testID="getStarted"
|
||||
style={{paddingTop: 3}}
|
||||
weight="semibold"
|
||||
align="center"
|
||||
color="#FFFFFF"
|
||||
margin="15 0 0 0">
|
||||
{controller.isPasscodeSet() ? t('getStarted') : t('goBack')}
|
||||
{controller.isPasscodeSet() ? t('goBack') : t('getStarted')}
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</View>
|
||||
@@ -156,7 +169,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>
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,44 @@
|
||||
import React from 'react';
|
||||
import { MessageOverlay } from '../../../components/MessageOverlay';
|
||||
import { AddVcModalProps, useAddVcModal } from './AddVcModalController';
|
||||
import { OtpVerificationModal } from './OtpVerificationModal';
|
||||
import { IdInputModal } from './IdInputModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {MessageOverlay} from '../../../components/MessageOverlay';
|
||||
import {AddVcModalProps, useAddVcModal} from './AddVcModalController';
|
||||
import {OtpVerificationModal} from './OtpVerificationModal';
|
||||
import {IdInputModal} from './IdInputModal';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {GET_INDIVIDUAL_ID} from '../../../shared/constants';
|
||||
import {Button, Column} from '../../../components/ui';
|
||||
|
||||
export const AddVcModal: React.FC<AddVcModalProps> = (props) => {
|
||||
const { t } = useTranslation('AddVcModal');
|
||||
export const AddVcModal: React.FC<AddVcModalProps> = props => {
|
||||
const {t} = useTranslation('AddVcModal');
|
||||
const controller = useAddVcModal(props);
|
||||
|
||||
const shouldShowAddVcModal = () => {
|
||||
if (controller.isRequestingCredential) {
|
||||
GET_INDIVIDUAL_ID({id: '', idType: 'UIN'});
|
||||
}
|
||||
return (
|
||||
(!controller.isAcceptingOtpInput && !controller.isRequestingCredential) ||
|
||||
!controller.isDownloadCancelled
|
||||
);
|
||||
};
|
||||
|
||||
const dismissIdInputModal = () => {
|
||||
GET_INDIVIDUAL_ID({id: '', idType: 'UIN'});
|
||||
controller.DISMISS();
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<IdInputModal
|
||||
service={props.service}
|
||||
isVisible={
|
||||
!controller.isAcceptingOtpInput && !controller.isRequestingCredential
|
||||
}
|
||||
onDismiss={controller.DISMISS}
|
||||
isVisible={shouldShowAddVcModal()}
|
||||
onDismiss={dismissIdInputModal}
|
||||
onPress={props.onPress}
|
||||
/>
|
||||
|
||||
<OtpVerificationModal
|
||||
isVisible={controller.isAcceptingOtpInput}
|
||||
isVisible={
|
||||
controller.isAcceptingOtpInput || controller.isDownloadCancelled
|
||||
}
|
||||
onDismiss={controller.DISMISS}
|
||||
onInputDone={controller.INPUT_OTP}
|
||||
error={controller.otpError}
|
||||
@@ -33,6 +50,26 @@ export const AddVcModal: React.FC<AddVcModalProps> = (props) => {
|
||||
title={t('requestingCredential')}
|
||||
progress
|
||||
/>
|
||||
|
||||
<MessageOverlay
|
||||
isVisible={controller.isDownloadCancelled}
|
||||
title={t('confirmationDialog.title')}
|
||||
message={t('confirmationDialog.message')}
|
||||
customHeight={250}>
|
||||
<Column>
|
||||
<Button
|
||||
type="gradient"
|
||||
title={t('confirmationDialog.wait')}
|
||||
onPress={controller.WAIT}
|
||||
margin={[0, 0, 8, 0]}
|
||||
/>
|
||||
<Button
|
||||
type="clear"
|
||||
title={t('confirmationDialog.cancel')}
|
||||
onPress={controller.CANCEL}
|
||||
/>
|
||||
</Column>
|
||||
</MessageOverlay>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useSelector } from '@xstate/react';
|
||||
import { ActorRefFrom } from 'xstate';
|
||||
import {useSelector} from '@xstate/react';
|
||||
import {ActorRefFrom} from 'xstate';
|
||||
import {
|
||||
AddVcModalEvents,
|
||||
AddVcModalMachine,
|
||||
@@ -7,9 +7,10 @@ import {
|
||||
selectIsRequestingCredential,
|
||||
selectOtpError,
|
||||
selectIsAcceptingIdInput,
|
||||
selectIsCancellingDownload,
|
||||
} from './AddVcModalMachine';
|
||||
|
||||
export function useAddVcModal({ service }: AddVcModalProps) {
|
||||
export function useAddVcModal({service}: AddVcModalProps) {
|
||||
return {
|
||||
isRequestingCredential: useSelector(service, selectIsRequestingCredential),
|
||||
|
||||
@@ -17,12 +18,17 @@ export function useAddVcModal({ service }: AddVcModalProps) {
|
||||
|
||||
isAcceptingUinInput: useSelector(service, selectIsAcceptingIdInput),
|
||||
isAcceptingOtpInput: useSelector(service, selectIsAcceptingOtpInput),
|
||||
isDownloadCancelled: useSelector(service, selectIsCancellingDownload),
|
||||
|
||||
INPUT_OTP: (otp: string) => service.send(AddVcModalEvents.INPUT_OTP(otp)),
|
||||
|
||||
RESEND_OTP: () => service.send(AddVcModalEvents.RESEND_OTP()),
|
||||
|
||||
DISMISS: () => service.send(AddVcModalEvents.DISMISS()),
|
||||
|
||||
WAIT: () => service.send(AddVcModalEvents.WAIT()),
|
||||
|
||||
CANCEL: () => service.send(AddVcModalEvents.CANCEL()),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,15 @@ import {BackendResponseError, request} from '../../../shared/request';
|
||||
import {VcIdType} from '../../../types/VC/ExistingMosipVC/vc';
|
||||
import i18n from '../../../i18n';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {
|
||||
getErrorEventData,
|
||||
getImpressionEventData,
|
||||
getInteractEventData,
|
||||
sendErrorEvent,
|
||||
sendImpressionEvent,
|
||||
sendInteractEvent,
|
||||
} from '../../../shared/telemetry/TelemetryUtils';
|
||||
import {API_URLS} from '../../../shared/api';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -33,6 +42,8 @@ const model = createModel(
|
||||
VALIDATE_INPUT: () => ({}),
|
||||
READY: (idInputRef: TextInput) => ({idInputRef}),
|
||||
DISMISS: () => ({}),
|
||||
CANCEL: () => ({}),
|
||||
WAIT: () => ({}),
|
||||
SELECT_ID_TYPE: (idType: VcIdType) => ({idType}),
|
||||
},
|
||||
},
|
||||
@@ -57,6 +68,9 @@ export const AddVcModalMachine =
|
||||
INPUT_ID: {
|
||||
actions: 'setId',
|
||||
},
|
||||
SELECT_ID_TYPE: {
|
||||
actions: ['clearIdError', 'setIdType'],
|
||||
},
|
||||
},
|
||||
states: {
|
||||
acceptingIdInput: {
|
||||
@@ -146,6 +160,7 @@ export const AddVcModalMachine =
|
||||
src: 'requestOtp',
|
||||
onDone: [
|
||||
{
|
||||
actions: 'sendImpressionEvent',
|
||||
target: '#AddVcModal.acceptingOtpInput',
|
||||
},
|
||||
],
|
||||
@@ -172,8 +187,7 @@ export const AddVcModalMachine =
|
||||
target: 'requestingCredential',
|
||||
},
|
||||
DISMISS: {
|
||||
actions: 'resetIdInputRef',
|
||||
target: 'acceptingIdInput',
|
||||
target: 'cancelDownload',
|
||||
},
|
||||
RESEND_OTP: {
|
||||
target: '.resendOTP',
|
||||
@@ -200,6 +214,16 @@ export const AddVcModalMachine =
|
||||
},
|
||||
},
|
||||
},
|
||||
cancelDownload: {
|
||||
on: {
|
||||
CANCEL: {
|
||||
actions: ['resetIdInputRef', 'forwardToParent'],
|
||||
},
|
||||
WAIT: {
|
||||
target: 'acceptingOtpInput',
|
||||
},
|
||||
},
|
||||
},
|
||||
requestingCredential: {
|
||||
invoke: {
|
||||
src: 'requestCredential',
|
||||
@@ -269,13 +293,17 @@ export const AddVcModalMachine =
|
||||
context.idType === 'UIN' ? 'invalidUin' : 'invalidVid',
|
||||
'VID is expired/deactivated': 'deactivatedVid',
|
||||
};
|
||||
return ID_ERRORS_MAP[message]
|
||||
const backendError = ID_ERRORS_MAP[message]
|
||||
? i18n.t(`errors.backend.${ID_ERRORS_MAP[message]}`, {
|
||||
ns: 'AddVcModal',
|
||||
})
|
||||
: i18n.t(`errors.genericError`, {
|
||||
ns: 'common',
|
||||
});
|
||||
sendErrorEvent(
|
||||
getErrorEventData('VC Download', message, backendError),
|
||||
);
|
||||
return backendError;
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -318,28 +346,40 @@ export const AddVcModalMachine =
|
||||
clearOtp: assign({otp: ''}),
|
||||
|
||||
focusInput: context => context.idInputRef.focus(),
|
||||
|
||||
sendImpressionEvent: () => {
|
||||
sendImpressionEvent(
|
||||
getImpressionEventData('VC Download', 'OTP Verification'),
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
services: {
|
||||
requestOtp: async context => {
|
||||
return request('POST', '/residentmobileapp/req/otp', {
|
||||
id: 'mosip.identity.otp.internal',
|
||||
individualId: context.id,
|
||||
metadata: {},
|
||||
otpChannel: ['PHONE', 'EMAIL'],
|
||||
requestTime: String(new Date().toISOString()),
|
||||
transactionID: context.transactionId,
|
||||
version: '1.0',
|
||||
});
|
||||
sendInteractEvent(
|
||||
getInteractEventData('VC Download', 'CLICK', 'Requesting OTP'),
|
||||
);
|
||||
return request(
|
||||
API_URLS.requestOtp.method,
|
||||
API_URLS.requestOtp.buildURL(),
|
||||
{
|
||||
id: 'mosip.identity.otp.internal',
|
||||
individualId: context.id,
|
||||
metadata: {},
|
||||
otpChannel: ['PHONE', 'EMAIL'],
|
||||
requestTime: String(new Date().toISOString()),
|
||||
transactionID: context.transactionId,
|
||||
version: '1.0',
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
requestCredential: async context => {
|
||||
// force wait to fix issue with hanging overlay
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
const response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/credentialshare/request',
|
||||
API_URLS.credentialRequest.method,
|
||||
API_URLS.credentialRequest.buildURL(),
|
||||
{
|
||||
individualId: context.id,
|
||||
individualIdType: context.idType,
|
||||
@@ -409,3 +449,7 @@ export function selectIsRequestingOtp(state: State) {
|
||||
export function selectIsRequestingCredential(state: State) {
|
||||
return state.matches('requestingCredential');
|
||||
}
|
||||
|
||||
export function selectIsCancellingDownload(state: State) {
|
||||
return state.matches('cancelDownload');
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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."
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { TextInput } from 'react-native';
|
||||
import {TextInput} from 'react-native';
|
||||
import {
|
||||
assign,
|
||||
DoneInvokeEvent,
|
||||
ErrorPlatformEvent,
|
||||
EventFrom,
|
||||
DoneInvokeEvent,
|
||||
sendParent,
|
||||
StateFrom,
|
||||
} from 'xstate';
|
||||
import { createModel } from 'xstate/lib/model';
|
||||
import { BackendResponseError, request } from '../../../shared/request';
|
||||
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';
|
||||
import {AddVcModalMachine} from './AddVcModalMachine';
|
||||
import {GET_INDIVIDUAL_ID, IndividualId} from '../../../shared/constants';
|
||||
import {API_URLS} from '../../../shared/api';
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -26,16 +27,16 @@ const model = createModel(
|
||||
},
|
||||
{
|
||||
events: {
|
||||
INPUT_ID: (id: string) => ({ id }),
|
||||
INPUT_OTP: (otp: string) => ({ otp }),
|
||||
INPUT_ID: (id: string) => ({id}),
|
||||
INPUT_OTP: (otp: string) => ({otp}),
|
||||
VALIDATE_INPUT: () => ({}),
|
||||
ACTIVATE_ICON_COLOR: () => ({}),
|
||||
DEACTIVATE_ICON_COLOR: () => ({}),
|
||||
READY: (idInputRef: TextInput) => ({ idInputRef }),
|
||||
READY: (idInputRef: TextInput) => ({idInputRef}),
|
||||
DISMISS: () => ({}),
|
||||
GOT_ID: (id: string) => ({ id }),
|
||||
GOT_ID: (id: string) => ({id}),
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export const GetVcModalEvents = model.events;
|
||||
@@ -222,13 +223,14 @@ export const GetVcModalMachine =
|
||||
transactionId: () => String(new Date().valueOf()).substring(3, 13),
|
||||
}),
|
||||
|
||||
setIndividualId: (_context, event) =>
|
||||
GET_INDIVIDUAL_ID((event as DoneInvokeEvent<string>).data),
|
||||
setIndividualId: (_context, event) => {
|
||||
GET_INDIVIDUAL_ID((event as DoneInvokeEvent<IndividualId>).data);
|
||||
},
|
||||
|
||||
setIdBackendError: assign({
|
||||
idError: (context, event) => {
|
||||
if ((event as ErrorPlatformEvent).data == 'IDA-MLC-001') {
|
||||
return i18n.t('errors.backend.timeOut', { ns: 'GetVcModal' });
|
||||
return i18n.t('errors.backend.timeOut', {ns: 'GetVcModal'});
|
||||
}
|
||||
|
||||
const message = (event as ErrorPlatformEvent).data.message;
|
||||
@@ -246,15 +248,15 @@ export const GetVcModalMachine =
|
||||
},
|
||||
}),
|
||||
|
||||
clearIdError: model.assign({ idError: '' }),
|
||||
clearIdError: model.assign({idError: ''}),
|
||||
|
||||
setIdErrorEmpty: model.assign({
|
||||
idError: () => i18n.t('errors.input.empty', { ns: 'GetVcModal' }),
|
||||
idError: () => i18n.t('errors.input.empty', {ns: 'GetVcModal'}),
|
||||
}),
|
||||
|
||||
setIdErrorWrongFormat: model.assign({
|
||||
idError: () =>
|
||||
i18n.t('errors.input.invalidFormat', { ns: 'GetVcModal' }),
|
||||
i18n.t('errors.input.invalidFormat', {ns: 'GetVcModal'}),
|
||||
}),
|
||||
|
||||
setOtpError: assign({
|
||||
@@ -282,20 +284,20 @@ export const GetVcModalMachine =
|
||||
},
|
||||
}),
|
||||
|
||||
clearOtp: assign({ otp: '' }),
|
||||
clearOtp: assign({otp: ''}),
|
||||
|
||||
setIconColorActivate: assign({ iconColor: true }),
|
||||
setIconColorActivate: assign({iconColor: true}),
|
||||
|
||||
setIconColorDeactivate: assign({ iconColor: false }),
|
||||
setIconColorDeactivate: assign({iconColor: false}),
|
||||
|
||||
focusInput: (context) => context.idInputRef.focus(),
|
||||
focusInput: context => context.idInputRef.focus(),
|
||||
},
|
||||
|
||||
services: {
|
||||
requestOtp: async (context) => {
|
||||
requestOtp: async context => {
|
||||
return await request(
|
||||
'POST',
|
||||
'/residentmobileapp/req/individualId/otp',
|
||||
API_URLS.reqIndividualOTP.method,
|
||||
API_URLS.reqIndividualOTP.buildURL(),
|
||||
{
|
||||
id: 'mosip.identity.otp.internal',
|
||||
aid: context.id,
|
||||
@@ -304,35 +306,38 @@ export const GetVcModalMachine =
|
||||
requestTime: String(new Date().toISOString()),
|
||||
transactionID: context.transactionId,
|
||||
version: '1.0',
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
requestingUinVid: async (context) => {
|
||||
requestingUinVid: async context => {
|
||||
const response = await request(
|
||||
'POST',
|
||||
'/residentmobileapp/aid/get-individual-id',
|
||||
API_URLS.getIndividualId.method,
|
||||
API_URLS.getIndividualId.buildURL(),
|
||||
{
|
||||
aid: context.id,
|
||||
otp: context.otp,
|
||||
transactionID: context.transactionId,
|
||||
}
|
||||
},
|
||||
);
|
||||
return response.response.individualId;
|
||||
return {
|
||||
id: response.response.individualId,
|
||||
idType: response.response.individualIdType || 'UIN',
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
guards: {
|
||||
isEmptyId: ({ id }) => !id || !id.length,
|
||||
isEmptyId: ({id}) => !id || !id.length,
|
||||
|
||||
isWrongIdFormat: ({ id }) => !/^\d{14,29}$/.test(id),
|
||||
isWrongIdFormat: ({id}) => !/^\d{14,29}$/.test(id),
|
||||
|
||||
isIdInvalid: (_context, event: unknown) =>
|
||||
['RES-SER-449', 'IDA-MLC-001'].includes(
|
||||
(event as BackendResponseError).name
|
||||
(event as BackendResponseError).name,
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
type State = StateFrom<typeof GetVcModalMachine>;
|
||||
|
||||
@@ -50,6 +50,7 @@ export const HistoryTab: React.FC<HistoryTabProps> = props => {
|
||||
/>
|
||||
<Text
|
||||
testID="noHistory"
|
||||
style={{paddingTop: 3}}
|
||||
align="center"
|
||||
weight="semibold"
|
||||
margin="0 0 4 0">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user