[INJIMOB-2381] fix compile and target SDK 34 is causing app crash in debug build (#1877)

* [INJIMOB-2381] update package.json and resolve dependencies for react 0.73.0

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-2381] setup for 0.73.6

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-2381] fix font & image not loading issue

changes include
- move common image assets to android & iOS folders
- update gradle version to 8.2
- add expo-font asset for Inter regular
- replace useFont with expo-font
- remove flipper (reason: 0.74 react native decoupled flipper)
- npm package updates
- close icon changed to close text in QRScanner.tsx

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-2381] update android:mosip script as per updated react native version

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix android build failure issue

Changes include:
- rename android assets folder as per convention
- remove unused biometrics dependency
- use env from react-native-dotenv as per module registered in babel config
- revert conversion of close icon to image in QRScanner component

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix iOS build issue

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] rm unused local images linking in adnroid

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix splash screen not rendering issue in android

Issue: Local assets were not loaded via React Native Image component in android, to fix this @react-native/assets-registry has been added
Reference: https://github.com/expo/expo/issues/31240#issuecomment-2459049911

Other changes:
- remove usage of expo-image as we dont have any explicit usecase for expo-image and its unused

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] rm unused intro slider image assets

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] revert back using local font assets in android

Reason: Previously expo-font was used for fonts, to bring back the same compatiblity it is bought back

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] use GestureHandlerRootView in root level to handle gestures

ref - https://docs.swmansion.com/react-native-gesture-handler/docs/1.x/#js

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove custom assets and linking for images in iOS

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] use default parameters instead of defaultProps

Reason: React 18 has marked defaultProps as deprecated and it is removed in React 19 version. To avoid the issue of deprated usage, its modified.

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove unused terminal option in android build script

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove font assets in android

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] optimize import

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix failing test

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] set package.resolved version to 2

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix setting of camera view in face scanner

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix setting of camera view in face compare

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove flipper config file

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove unused debug logs

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor use component instead of type

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor use GestureHandlerRootView only on root level

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor remove unused config linking of font assets

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor remove unused image assets

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix camera persmission issue in QRScanner

use expo-camera to request and getstatus of camera permission instead of expo-barcode-scanner to avoid multiple re-renders of scan screen in flow of camera permission denial

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove package expo-barcode-scanner

expo-barcode-scanner is deprecated and its suggested to use expo-camera to handle the scanning flows. The existing bar-code-scanner implementations have been replaced with expo-camera.

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] use extracted enums instead of legacy expo-camera

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove patch for react-native-0.71.8

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] revert date-fs version to 2.28.0

date-fns is not supporting filipino langauge, so we are maintaining patch for that. The patch created is for version 2.28.0 and updating the version of date-fns is causing conflicts in patch application if updated as well. To avoid this issue, version is kept as 2.28.0

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] update readme

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove usage of legacy expo-camera in getting image type

Other changes
- remove resolutions block from package.json
- sync pbxproj

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] add active prop to expo-camera as per suggestions

expo-camera suggests "Only one Camera preview can be active at any given time. If you have multiple screens in your app, you should unmount Camera components whenever a screen is unfocused.". To handle this active prop is used which is set to false on unMount of the component whenever rendering Camera from expo-camera

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

---------

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Signed-off-by: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com>
Co-authored-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Co-authored-by: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com>
This commit is contained in:
KiruthikaJeyashankar
2025-04-10 14:37:41 +05:30
committed by GitHub
parent affeb5cff8
commit 68488f3f0c
94 changed files with 13985 additions and 12857 deletions

10
App.tsx
View File

@@ -1,6 +1,6 @@
import React, {useContext, useEffect} from 'react';
import {AppLayout} from './screens/AppLayout';
import {useFont} from './shared/hooks/useFont';
import {useFont} from "./shared/hooks/useFont";
import {GlobalContextProvider} from './components/GlobalContextProvider';
import {GlobalContext} from './shared/GlobalContext';
import {useSelector} from '@xstate/react';
@@ -25,7 +25,6 @@ import {MessageOverlay} from './components/MessageOverlay';
import {NativeModules} from 'react-native';
import {isHardwareKeystoreExists} from './shared/cryptoutil/cryptoUtil';
import i18n from './i18n';
import './shared/flipperConfig';
import {CopilotProvider} from 'react-native-copilot';
import {CopilotTooltip} from './components/CopilotTooltip';
import {Theme} from './components/ui/styleUtils';
@@ -52,7 +51,6 @@ const AppLayoutWrapper: React.FC = () => {
const isDecryptError = useSelector(appService, selectIsDecryptError);
const controller = useApp();
const {t} = useTranslation('WelcomeScreen');
useEffect(() => {
if (AppState.currentState === 'active') {
appService.send(APP_EVENTS.ACTIVE());
@@ -115,8 +113,8 @@ const AppLoadingWrapper: React.FC = () => {
const AppInitialization: React.FC = () => {
const {appService} = useContext(GlobalContext);
const hasFontsLoaded = useFont()
const isReady = useSelector(appService, selectIsReady);
const hasFontsLoaded = useFont();
const {t} = useTranslation('common');
useEffect(() => {
@@ -129,9 +127,9 @@ const AppInitialization: React.FC = () => {
}, [i18n.language]);
return isReady && hasFontsLoaded ? (
<AppLayoutWrapper />
<AppLayoutWrapper />
) : (
<AppLoadingWrapper />
<AppLoadingWrapper />
);
};

View File

@@ -14,16 +14,16 @@ for more details refer [here](https://docs.mosip.io/inji/inji-wallet/overview)
Be sure to have the following build tools installed before proceeding:
- [React Native 0.71.8](https://reactnative.dev/docs/0.71/getting-started)
- [React Native 0.74.5](https://reactnative.dev/docs/0.74/getting-started)
- Hermes Engine enabled
- [Expo 49.0.23](https://docs.expo.dev/get-started/installation/)
- [Expo 51.0.0](https://docs.expo.dev/get-started/installation/)
- [node v16.19.0](https://nodejs.org/en/blog/release/v16.19.0)
- [npm 8.19.3](https://www.npmjs.com/package/npm/v/8.19.3)
### Android
- [Java 17](https://openjdk.org/projects/jdk/17/)
- [Gradle 7.5.1](https://gradle.org/install/)
- [Gradle 8.2](https://gradle.org/install/)
- [Android SDK](https://developer.android.com/)
- minSdkVersion = 24
- compileSdkVersion = 34
@@ -54,7 +54,7 @@ ESIGNET_HOST = https://esignet.collab.mosip.net/
OBSRV_HOST = https://dataset-api.obsrv.mosip.net
Telemetry Dashboard = https://druid.obsrv.mosip.net/unified-console.html#workbench
#Application Theme can be ( grdaient | purple ), defaults to grdaient theme
#Application Theme can be ( gradient | purple ), defaults to gradient theme
APPLICATION_THEME=grdaient
#environment can be changed if it is toggled
@@ -87,6 +87,11 @@ More info here:
- [React Native - Publishing to the App Store](https://reactnative.dev/docs/publishing-to-app-store)
- [Apple Developer - Distributing Your App for Beta Testing and Releases](https://developer.apple.com/documentation/xcode/distributing-your-app-for-beta-testing-and-releases)
### Note
When application is built via IDE, metro need to be started manually (For instance, if building app via XCode open metro manually, as metro hook has been removed from building via XCode - [reference](https://github.com/facebook/react-native/issues/42173#issuecomment-1921091973)).
However, if app is built via npm commands, metro starts automatically (For instance, `npm run android:mosip` or `npm run ios`)
## Contributions
Please refer [here](https://docs.mosip.io/inji/inji-mobile-wallet/contribution) for contributing to Inji
@@ -98,16 +103,13 @@ Credits listed [here](/Credits.md)
## Troubleshooting
If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
this project runtime can be debugged using [Flipper](https://fbflipper.com/).
## Learn More
To learn more about React Native, take a look at the following resources:
- [React Native Website](https://reactnative.dev) - learn more about React Native.
- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup
your
environment.
- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how to setup your environment.
- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for

View File

@@ -306,14 +306,6 @@ dependencies {
}
compileOnly project(':react-native-android-location-services-dialog-box')
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group: 'com.facebook.flipper'
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group: 'com.facebook.flipper'
}
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
@@ -346,4 +338,4 @@ apply from: file("../../node_modules/@react-native-community/cli-platform-androi
// https://github.com/oblador/react-native-vector-icons?tab=readme-ov-file#android-setup
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
apply from: "./eas-build.gradle"
apply from: "./eas-build.gradle"

View File

@@ -12,8 +12,6 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30"/>
<!-- from Android 12, Location permission isn't required as we aren't using it to determine location -->
<application tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" android:networkSecurityConfig="@xml/network_security_config">>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false" />
</application>
<application tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" android:networkSecurityConfig="@xml/network_security_config"/>
</manifest>

View File

@@ -1,75 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package io.mosip.residentapp;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceEventListener;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;
/**
* Class responsible of loading Flipper inside your React Native application. This is the debug
* flavor of it. Here you can add your own plugins and customize the Flipper setup.
*/
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {
final FlipperClient client = AndroidFlipperClient.getInstance(context);
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
client.addPlugin(new DatabasesFlipperPlugin(context));
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
client.addPlugin(CrashReporterPlugin.getInstance());
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
client.addPlugin(networkFlipperPlugin);
client.start();
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
// Hence we run if after all native modules have been initialized
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
reactInstanceManager.removeReactInstanceEventListener(this);
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
client.addPlugin(new FrescoFlipperPlugin());
}
});
}
});
} else {
client.addPlugin(new FrescoFlipperPlugin());
}
}
}
}

View File

@@ -60,7 +60,7 @@ public class MainApplication extends Application implements ReactApplication {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load();
}
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());

View File

@@ -1,20 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package io.mosip.residentapp;
import android.content.Context;
import com.facebook.react.ReactInstanceManager;
/**
* Class responsible of loading Flipper inside your React Native application. This is the release
* flavor of it so it's empty as we don't want to load Flipper.
*/
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
// Do nothing as we don't want to initialize Flipper on Release.
}
}

View File

@@ -16,7 +16,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.3.1")
classpath("com.android.tools.build:gradle:8.2")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3")
}

View File

@@ -25,8 +25,7 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.125.0
# # The hosted JavaScript engine
# # Supported values: expo.jsEngine = "hermes" | "jsc"

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -2,7 +2,7 @@ rootProject.name = 'Inji'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
includeBuild('../node_modules/react-native-gradle-plugin')
includeBuild('../node_modules/@react-native/gradle-plugin')
include ':react-native-android-location-services-dialog-box'
project(':react-native-android-location-services-dialog-box').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-android-location-services-dialog-box/android')
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle")

View File

@@ -2,9 +2,8 @@ import {APPLICATION_THEME} from 'react-native-dotenv';
const adaptiveImage =
APPLICATION_THEME?.toLowerCase() === 'purple'
? '../assets/purpleSplashScreen.png'
: './assets/orangeSplashScreen.png';
? ('./assets/images/png/purpleSplashScreen.png')
: ('./assets/images/png/SplashScreen.png');
export default {
name: 'Inji',
slug: 'inji',
@@ -35,5 +34,5 @@ export default {
},
platforms: ['android', 'ios'],
privacy: 'hidden',
plugins: ['expo-localization'],
plugins: ['expo-localization', 'expo-font'],
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

View File

@@ -1,149 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="564" height="564" viewBox="0 0 564 564">
<defs>
<clipPath id="clip-path">
<path id="Path_155571" data-name="Path 155571" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-267.7 -336.6)"/>
</clipPath>
<clipPath id="clip-path-2">
<path id="Path_155572" data-name="Path 155572" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-57.6 -223.7)"/>
</clipPath>
<clipPath id="clip-path-3">
<path id="Path_155573" data-name="Path 155573" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-95.9 -287.1)"/>
</clipPath>
<clipPath id="clip-path-4">
<path id="Path_155574" data-name="Path 155574" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(0 -138.8)"/>
</clipPath>
<clipPath id="clip-path-5">
<path id="Path_155575" data-name="Path 155575" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-142 -105.8)"/>
</clipPath>
<clipPath id="clip-path-6">
<path id="Path_155576" data-name="Path 155576" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-123.8 -29.4)"/>
</clipPath>
<clipPath id="clip-path-7">
<path id="Path_155577" data-name="Path 155577" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-393.1 -138.5)"/>
</clipPath>
<clipPath id="clip-path-8">
<path id="Path_155578" data-name="Path 155578" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-400.7 -211.4)"/>
</clipPath>
<clipPath id="clip-path-9">
<path id="Path_155579" data-name="Path 155579" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-302.1 -124.4)"/>
</clipPath>
<clipPath id="clip-path-10">
<path id="Path_155580" data-name="Path 155580" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-248 -64)"/>
</clipPath>
<clipPath id="clip-path-11">
<path id="Path_155581" data-name="Path 155581" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-134.5 -410.9)"/>
</clipPath>
<clipPath id="clip-path-12">
<path id="Path_155582" data-name="Path 155582" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-21.7 -323.3)"/>
</clipPath>
<clipPath id="clip-path-13">
<path id="Path_155583" data-name="Path 155583" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-205.2 -410.4)"/>
</clipPath>
<clipPath id="clip-path-14">
<path id="Path_155584" data-name="Path 155584" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-389 -331.3)"/>
</clipPath>
<clipPath id="clip-path-15">
<path id="Path_155585" data-name="Path 155585" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-477.9 -273.1)"/>
</clipPath>
<clipPath id="clip-path-16">
<path id="Path_155586" data-name="Path 155586" d="M270.1,60.1c-128,0-231.8,103.8-231.8,231.8S142,523.7,270.1,523.7,501.9,419.9,501.9,291.9,398.1,60.1,270.1,60.1Zm0,350.8a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-246.7 -140.4)"/>
</clipPath>
<clipPath id="clip-path-17">
<path id="Path_155587" data-name="Path 155587" d="M270.1,60.1c-128,0-231.8,103.8-231.8,231.8S142,523.7,270.1,523.7,501.9,419.9,501.9,291.9,398.1,60.1,270.1,60.1Zm0,350.8a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-303.6 -129.2)"/>
</clipPath>
<clipPath id="clip-path-18">
<path id="Path_155588" data-name="Path 155588" d="M270.1,60.1c-128,0-231.8,103.8-231.8,231.8S142,523.7,270.1,523.7,501.9,419.9,501.9,291.9,398.1,60.1,270.1,60.1Zm0,350.8a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-308.6 -110.6)"/>
</clipPath>
<clipPath id="clip-path-19">
<path id="Path_155589" data-name="Path 155589" d="M270.1,60.1c-128,0-231.8,103.8-231.8,231.8S142,523.7,270.1,523.7,501.9,419.9,501.9,291.9,398.1,60.1,270.1,60.1Zm0,350.8a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-250.8 -75)"/>
</clipPath>
<clipPath id="clip-path-20">
<path id="Path_155590" data-name="Path 155590" d="M270.1,60.1c-128,0-231.8,103.8-231.8,231.8S142,523.7,270.1,523.7,501.9,419.9,501.9,291.9,398.1,60.1,270.1,60.1Zm0,350.8a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-141.5 -106.8)"/>
</clipPath>
<clipPath id="clip-path-21">
<path id="Path_155591" data-name="Path 155591" d="M270.1,60.1c-128,0-231.8,103.8-231.8,231.8S142,523.7,270.1,523.7,501.9,419.9,501.9,291.9,398.1,60.1,270.1,60.1Zm0,350.8a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" transform="translate(-123.4 -30.4)"/>
</clipPath>
<clipPath id="clip-MOSIP_Logo">
<rect width="564" height="564"/>
</clipPath>
</defs>
<g id="MOSIP_Logo" clip-path="url(#clip-MOSIP_Logo)">
<g id="MOSIP_Horizontal_Black" data-name="MOSIP Horizontal Black" transform="translate(11.8 0.6)">
<g id="Group_57572" data-name="Group 57572">
<g id="Group_57564" data-name="Group 57564">
<g id="Group_57563" data-name="Group 57563">
<path id="Path_155570" data-name="Path 155570" d="M408.7,106.1a39.7,39.7,0,0,1-7.6,14.7c-7.6,9.1-18.9,14.1-30.2,17.9a8.723,8.723,0,0,0-3.7,1.9c-1.4,1.5-1.6,3.8-1.7,5.9-.5,6.9-2.6,13.8-6.9,19.3-4.3,5.4-11,9.1-17.9,8.7a42.252,42.252,0,0,1-9.2-2.1c-21.1-6.3-43.1-8.8-65-10.6-13.2-1.1-26.8-2-39-7.3-11-4.7-24.8-16-23.8-29.2,1.1-15.5-.5-31.6,4.5-46.7A67.673,67.673,0,0,1,213.5,67C112.9,92.3,38.2,183.4,38.2,291.9c0,128,103.8,231.8,231.8,231.8S501.8,419.9,501.8,291.9C501.9,215.9,465.2,148.4,408.7,106.1ZM270.1,410.9a119,119,0,1,1,119-119A119.028,119.028,0,0,1,270.1,410.9Z" fill="#fec401"/>
<g id="Group_57548" data-name="Group 57548" transform="translate(267.7 336.6)" clip-path="url(#clip-path)">
<circle id="Ellipse_1146" data-name="Ellipse 1146" cx="92.4" cy="92.4" r="92.4" fill="#01a2fd"/>
</g>
<g id="Group_57549" data-name="Group 57549" transform="translate(57.6 223.7)" clip-path="url(#clip-path-2)">
<circle id="Ellipse_1147" data-name="Ellipse 1147" cx="37.8" cy="37.8" r="37.8" fill="#f97707"/>
</g>
<g id="Group_57550" data-name="Group 57550" transform="translate(95.9 287.1)" clip-path="url(#clip-path-3)">
<circle id="Ellipse_1148" data-name="Ellipse 1148" cx="68.6" cy="68.6" r="68.6" fill="#01a2fd"/>
</g>
<g id="Group_57551" data-name="Group 57551" transform="translate(0 138.8)" clip-path="url(#clip-path-4)">
<circle id="Ellipse_1149" data-name="Ellipse 1149" cx="68.6" cy="68.6" r="68.6" fill="#014daf"/>
</g>
<g id="Group_57552" data-name="Group 57552" transform="translate(142 105.8)" clip-path="url(#clip-path-5)">
<circle id="Ellipse_1150" data-name="Ellipse 1150" cx="56" cy="56" r="56" fill="#f97707"/>
</g>
<g id="Group_57553" data-name="Group 57553" transform="translate(123.8 29.4)" clip-path="url(#clip-path-6)">
<circle id="Ellipse_1151" data-name="Ellipse 1151" cx="55.5" cy="55.5" r="55.5" fill="#01a2fd"/>
</g>
<g id="Group_57554" data-name="Group 57554" transform="translate(393.1 138.5)" clip-path="url(#clip-path-7)">
<circle id="Ellipse_1152" data-name="Ellipse 1152" cx="56" cy="56" r="56" fill="#f97707"/>
</g>
<g id="Group_57555" data-name="Group 57555" transform="translate(400.7 211.4)" clip-path="url(#clip-path-8)">
<circle id="Ellipse_1153" data-name="Ellipse 1153" cx="37.1" cy="37.1" r="37.1" fill="#01a2fd"/>
</g>
<g id="Group_57556" data-name="Group 57556" transform="translate(302.1 124.4)" clip-path="url(#clip-path-9)">
<circle id="Ellipse_1154" data-name="Ellipse 1154" cx="37.1" cy="37.1" r="37.1" fill="#014daf"/>
</g>
<g id="Group_57557" data-name="Group 57557" transform="translate(248 64)" clip-path="url(#clip-path-10)">
<circle id="Ellipse_1155" data-name="Ellipse 1155" cx="26.5" cy="26.5" r="26.5" fill="#014daf"/>
</g>
<g id="Group_57558" data-name="Group 57558" transform="translate(134.5 410.9)" clip-path="url(#clip-path-11)">
<circle id="Ellipse_1156" data-name="Ellipse 1156" cx="56" cy="56" r="56" fill="#f97707"/>
</g>
<g id="Group_57559" data-name="Group 57559" transform="translate(21.7 323.3)" clip-path="url(#clip-path-12)">
<circle id="Ellipse_1157" data-name="Ellipse 1157" cx="41.4" cy="41.4" r="41.4" fill="#014daf"/>
</g>
<g id="Group_57560" data-name="Group 57560" transform="translate(205.2 410.4)" clip-path="url(#clip-path-13)">
<circle id="Ellipse_1158" data-name="Ellipse 1158" cx="75.5" cy="75.5" r="75.5" fill="#014daf"/>
</g>
<g id="Group_57561" data-name="Group 57561" transform="translate(389 331.3)" clip-path="url(#clip-path-14)">
<circle id="Ellipse_1159" data-name="Ellipse 1159" cx="37.8" cy="37.8" r="37.8" fill="#014daf"/>
</g>
<g id="Group_57562" data-name="Group 57562" transform="translate(477.9 273.1)" clip-path="url(#clip-path-15)">
<circle id="Ellipse_1160" data-name="Ellipse 1160" cx="37.8" cy="37.8" r="37.8" fill="#f97707"/>
</g>
</g>
<circle id="Ellipse_1161" data-name="Ellipse 1161" cx="20.3" cy="20.3" r="20.3" transform="translate(322 54.7)" fill="#f97707"/>
<circle id="Ellipse_1162" data-name="Ellipse 1162" cx="12.1" cy="12.1" r="12.1" transform="translate(284.3 38.4)" fill="#fec401"/>
<circle id="Ellipse_1163" data-name="Ellipse 1163" cx="20.3" cy="20.3" r="20.3" transform="translate(372.3 98.5)" fill="#014daf"/>
</g>
<g id="Group_57571" data-name="Group 57571">
<g id="Group_57565" data-name="Group 57565" transform="translate(246.7 140.4)" clip-path="url(#clip-path-16)">
<circle id="Ellipse_1164" data-name="Ellipse 1164" cx="32.6" cy="32.6" r="32.6" fill="#fec401"/>
</g>
<g id="Group_57566" data-name="Group 57566" transform="translate(303.6 129.2)" clip-path="url(#clip-path-17)">
<circle id="Ellipse_1165" data-name="Ellipse 1165" cx="42.1" cy="42.1" r="42.1" fill="#01a2fd"/>
</g>
<g id="Group_57567" data-name="Group 57567" transform="translate(308.6 110.6)" clip-path="url(#clip-path-18)">
<circle id="Ellipse_1166" data-name="Ellipse 1166" cx="20.3" cy="20.3" r="20.3" fill="#fec401"/>
</g>
<g id="Group_57568" data-name="Group 57568" transform="translate(250.8 75)" clip-path="url(#clip-path-19)">
<circle id="Ellipse_1167" data-name="Ellipse 1167" cx="26.1" cy="26.1" r="26.1" fill="#014daf"/>
</g>
<g id="Group_57569" data-name="Group 57569" transform="translate(141.5 106.8)" clip-path="url(#clip-path-20)">
<circle id="Ellipse_1168" data-name="Ellipse 1168" cx="56" cy="56" r="56" fill="#f97707"/>
</g>
<g id="Group_57570" data-name="Group 57570" transform="translate(123.4 30.4)" clip-path="url(#clip-path-21)">
<circle id="Ellipse_1169" data-name="Ellipse 1169" cx="55.5" cy="55.5" r="55.5" fill="#01a2fd"/>
</g>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -16,6 +16,7 @@ module.exports = function (api) {
verbose: false,
},
],
['@babel/plugin-transform-private-methods', {loose: true}],
[
'babel-plugin-inline-import',
{
@@ -44,7 +45,7 @@ module.exports = function (api) {
['@babel/preset-env', {targets: {node: 'current'}}],
'@babel/preset-typescript',
'@babel/preset-react',
'module:metro-react-native-babel-preset',
'module:@react-native/babel-preset',
],
sourceType: 'module',
plugins: [

View File

@@ -1,8 +1,6 @@
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 {Row, Text} from './ui';
import {useTranslation} from 'react-i18next';
import testIDProps from '../shared/commonUtil';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import {Camera, CameraType} from 'expo-camera';
import React, {useEffect, useState} from 'react';
import {CameraType, CameraView} from 'expo-camera';
import {View, TouchableOpacity} from 'react-native';
import {SvgImage} from '../ui/svg';
import {Text, Column, Row, Centered} from '../ui';
@@ -16,16 +16,25 @@ const FaceCompare: React.FC<FaceCompareProps> = ({
service,
t,
}) => {
const [isCameraActive, setIsCameraActive] = useState<boolean>(true);
useEffect(() => {
return () => {
setIsCameraActive(false);
};
}, []);
return (
<Column fill align="space-between" style={{backgroundColor: '#ffffff'}}>
<View style={{flex: 2, marginTop: 15}}>
<View style={Theme.CameraEnabledStyles.scannerContainer}>
<View>
<Camera
<CameraView
{...testIDProps('camera')}
style={Theme.CameraEnabledStyles.scanner}
type={whichCamera}
facing={whichCamera}
ref={setCameraRef}
active={isCameraActive}
/>
</View>
</View>
@@ -74,7 +83,7 @@ export default FaceCompare;
interface FaceCompareProps {
whichCamera: CameraType;
setCameraRef: (node: Camera) => void;
setCameraRef: (node: CameraView) => void;
isCapturing: boolean;
isVerifying: boolean;
flipCamera: () => void;

View File

@@ -1,40 +1,28 @@
import React, {
useCallback,
useContext,
useEffect,
useRef,
useState,
} from 'react';
import {Camera} from 'expo-camera';
import {Column, Text, Button} from '.././ui';
import React, {useCallback, useContext, useEffect, useRef, useState,} from 'react';
import {CameraType, CameraView} from 'expo-camera';
import {Button, Column, Text} from '.././ui';
import {useInterpret, useSelector} from '@xstate/react';
import {useTranslation} from 'react-i18next';
import {
FaceScannerEvents,
selectIsCheckingPermission,
selectIsValid,
selectIsPermissionDenied,
selectIsScanning,
createFaceScannerMachine,
selectIsInvalid,
selectIsCapturing,
selectIsVerifying,
FaceScannerEvents,
selectCameraRef,
selectIsCapturing,
selectIsCheckingPermission,
selectIsInvalid,
selectIsPermissionDenied, selectIsScanning,
selectIsValid,
selectIsVerifying,
} from '../../machines/faceScanner';
import {GlobalContext} from '../../shared/GlobalContext';
import {selectIsActive} from '../../machines/app';
import {Theme} from '.././ui/styleUtils';
import {getRandomInt} from '../../shared/commonUtil';
import {
checkBlink,
cropEyeAreaFromFace,
faceDetectorConfig,
getFaceBounds,
imageCaptureConfig,
} from './FaceScannerHelper';
import {cropEyeAreaFromFace, faceDetectorConfig, getFaceBounds, imageCaptureConfig,} from './FaceScannerHelper';
import LivenessDetection from './LivenessDetection';
import FaceCompare from './FaceCompare';
import {LIVENESS_CHECK} from '../../shared/constants';
import {CameraPosition} from "../../shared/Utils";
export const FaceScanner: React.FC<FaceScannerProps> = props => {
const {t} = useTranslation('FaceScanner');
@@ -44,7 +32,7 @@ export const FaceScanner: React.FC<FaceScannerProps> = props => {
const machine = useRef(createFaceScannerMachine(props.vcImages));
const service = useInterpret(machine.current);
const [cameraType, setCameraType] = useState(Camera.Constants.Type.front);
const [cameraType, setCameraType] = useState<CameraType>(CameraPosition.FRONT);
const cameraRef = useSelector(service, selectCameraRef);
const isPermissionDenied = useSelector(service, selectIsPermissionDenied);
@@ -68,35 +56,34 @@ export const FaceScanner: React.FC<FaceScannerProps> = props => {
const [infoText, setInfoText] = useState<string>(t('livenessCaptureGuide'));
const setCameraRef = useCallback(
(node: Camera) => {
(node: CameraView) => {
if (node != null && !isScanning) {
service.send(FaceScannerEvents.READY(node));
}
},
[isScanning],
[isScanning, service],
);
const flipCamera = () => {
setCameraType(prevType =>
prevType === Camera.Constants.Type.front
? Camera.Constants.Type.back
: Camera.Constants.Type.front,
prevType === CameraPosition.FRONT ? CameraPosition.BACK : CameraPosition.FRONT,
);
};
function handleOnCancel() {
const handleOnCancel = () => {
props.onCancel();
}
};
async function captureImage(screenColor) {
const captureImage = async (screenColor: string) => {
try {
if (cameraRef) {
const capturedImage = await cameraRef.takePictureAsync(
imageCaptureConfig,
);
setPicArray([...picArray, {color: screenColor, image: capturedImage}]);
setPicArray(prevArray => [
...prevArray,
{color: screenColor, image: capturedImage},
]);
if (counter === randomNumToFaceCompare) {
setFaceToCompare(capturedImage);
}
@@ -104,14 +91,14 @@ export const FaceScanner: React.FC<FaceScannerProps> = props => {
} catch (error) {
console.error('Error capturing image:', error);
}
}
};
async function handleFacesDetected({faces}) {
checkBlink(faces[0]);
const handleFacesDetected = async ({faces}: {faces: any[]}) => {
if (!faces || faces.length === 0) return;
if (counter == MAX_COUNTER) {
setCounter(counter + 1);
cameraRef.pausePreview();
if (counter === MAX_COUNTER) {
setCounter(prev => prev + 1);
cameraRef?.pausePreview();
setScreenColor('#ffffff');
setInfoText(t('faceProcessingInfo'));
@@ -122,46 +109,38 @@ export const FaceScanner: React.FC<FaceScannerProps> = props => {
faceToCompare,
);
return result ? props.onValid() : props.onInvalid();
} else if (faces.length > 0) {
const [withinXBounds, withinYBounds, withinYawAngle, withinRollAngle] =
getFaceBounds(faces[0]);
setInfoText(t('faceOutGuide'));
if (
withinXBounds &&
withinYBounds &&
withinRollAngle &&
withinYawAngle &&
counter < MAX_COUNTER
) {
const randomNum = getRandomInt(0, 2);
const randomColor = screenFlashColors[randomNum];
setScreenColor(randomColor);
setCounter(counter + 1);
setInfoText(t('faceInGuide'));
await captureImage(screenColor);
}
}
}
const face = faces[0];
const [withinXBounds, withinYBounds, withinYawAngle, withinRollAngle] =
getFaceBounds(face);
if (withinXBounds && withinYBounds && withinRollAngle && withinYawAngle) {
setScreenColor(screenFlashColors[getRandomInt(0, 2)]);
setCounter(prev => prev + 1);
setInfoText(t('faceInGuide'));
await captureImage(screenColor);
} else {
setInfoText(t('faceOutGuide'));
}
};
useEffect(() => {
if (isValid) {
props.onValid();
} else if (isInvalid) {
props.onInvalid();
}
}, [isValid, isInvalid]);
if (isValid) props.onValid();
if (isInvalid) props.onInvalid();
}, [isValid, isInvalid, props]);
useEffect(() => {
if (isActive) {
service.send(FaceScannerEvents.APP_FOCUSED());
}
}, [isActive]);
}, [isActive, service]);
if (isCheckingPermission) {
return <Column></Column>;
} else if (isPermissionDenied) {
return <Column children={undefined} />;
}
if (isPermissionDenied) {
return (
<Column padding="24" fill align="space-between">
<Text
@@ -194,24 +173,24 @@ export const FaceScanner: React.FC<FaceScannerProps> = props => {
t={t}
/>
);
} else {
return (
<FaceCompare
whichCamera={cameraType}
setCameraRef={setCameraRef}
flipCamera={flipCamera}
isCapturing={isCapturing}
isVerifying={isVerifying}
service={service}
t={t}
/>
);
}
return (
<FaceCompare
whichCamera={cameraType}
setCameraRef={setCameraRef}
flipCamera={flipCamera}
isCapturing={isCapturing}
isVerifying={isVerifying}
service={service}
t={t}
/>
);
};
interface FaceScannerProps {
vcImages: string[];
onValid: () => void;
onInvalid: () => void;
isLiveness: boolean;
onCancel: () => void;
}

View File

@@ -3,7 +3,6 @@ import {LIVENESS_THRESHOLD, isAndroid} from '../../shared/constants';
import {closest} from 'color-diff';
import * as FaceDetector from 'expo-face-detector';
import ImageEditor from '@react-native-community/image-editor';
import {ImageType} from 'expo-camera';
import {getColors} from 'react-native-image-colors';
import {faceCompare} from '@iriscan/biometric-sdk-react-native';
@@ -39,6 +38,10 @@ const colorComparePalette = [
{R: 0, G: 0, B: 255},
];
export enum ImageType {
jpg = 'jpg',
}
export const imageCaptureConfig = {
base64: true,
quality: 1,

View File

@@ -10,7 +10,7 @@ import getAllConfigurations from '../shared/api';
export const HelpScreen: React.FC<HelpScreenProps> = props => {
const {t} = useTranslation('HelpScreen');
const [showHelpPage, setShowHelpPage] = useState(false);
var [injiHelpUrl, setInjiHelpUrl] = useState('');
const [injiHelpUrl, setInjiHelpUrl] = useState('');
const listingRef = useRef();
useEffect(() => {
@@ -395,5 +395,5 @@ export const HelpScreen: React.FC<HelpScreenProps> = props => {
interface HelpScreenProps {
source: 'Inji' | 'BackUp' | 'keyManagement';
triggerComponent: React.ReactElement;
isDisabled?: boolean;
isDisabled?: boolean;
}

View File

@@ -1,10 +1,8 @@
import React, {useContext, useEffect, useState} from 'react';
import Icon from 'react-native-vector-icons/MaterialIcons';
import {Camera} from 'expo-camera';
import {BarCodeEvent, BarCodeScanner} from 'expo-barcode-scanner';
import {Linking, TouchableOpacity, View, Pressable} from 'react-native';
import {Linking, Pressable, TouchableOpacity, View} from 'react-native';
import {Theme} from './ui/styleUtils';
import {Column, Text, Row} from './ui';
import {Column, Row, Text} from './ui';
import {GlobalContext} from '../shared/GlobalContext';
import {useSelector} from '@xstate/react';
import {selectIsActive} from '../machines/app';
@@ -12,12 +10,14 @@ import {useTranslation} from 'react-i18next';
import testIDProps from '../shared/commonUtil';
import {SvgImage} from './ui/svg';
import {isAndroid} from '../shared/constants';
import {CameraView, useCameraPermissions, PermissionStatus, BarcodeScanningResult, CameraType} from 'expo-camera';
import {CameraPosition} from "../shared/Utils";
export const QrScanner: React.FC<QrScannerProps> = props => {
const {t} = useTranslation('QrScanner');
const {appService} = useContext(GlobalContext);
const [scanned, setScanned] = useState(false);
const [cameraType, setCameraType] = useState(Camera.Constants.Type.back);
const [cameraType, setCameraType] = useState<CameraType>(CameraPosition.BACK);
const [hasCameraPermission, setHasCameraPermission] = useState<
boolean | null
>(null);
@@ -25,6 +25,14 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
showCameraPermissionDeniedBanner,
setShowCameraPermissionDeniedBanner,
] = useState(false);
const [_, requestCameraPermission, getCameraPermissionsAsync] = useCameraPermissions();
const [isCameraActive, setIsCameraActive] = useState<boolean>(true);
useEffect(() => {
return () => {
setIsCameraActive(false);
};
}, []);
const isActive = useSelector(appService, selectIsActive);
@@ -40,16 +48,16 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
if (isActive && !Boolean(hasCameraPermission)) {
(async () => {
setShowCameraPermissionDeniedBanner(false);
const cameraPermissionResult = await Camera.getCameraPermissionsAsync();
if (cameraPermissionResult.status === 'undetermined') {
const response = await Camera.requestCameraPermissionsAsync();
const cameraPermissionResult = await getCameraPermissionsAsync();
if (cameraPermissionResult.status === PermissionStatus.UNDETERMINED) {
const response = await requestCameraPermission();
setHasCameraPermission(response.granted);
if (response.granted === false) {
setShowCameraPermissionDeniedBanner(true);
}
} else if (cameraPermissionResult.status === 'granted') {
} else if (cameraPermissionResult.status === PermissionStatus.GRANTED) {
setHasCameraPermission(true);
} else if (cameraPermissionResult.status === 'denied') {
} else {
setHasCameraPermission(false);
setShowCameraPermissionDeniedBanner(true);
}
@@ -85,11 +93,11 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
</Column>
<Pressable>
<Icon
testID="close"
name="close"
onPress={() => setShowCameraPermissionDeniedBanner(false)}
color={Theme.Colors.whiteText}
size={18}
testID="close"
name="close"
onPress={() => setShowCameraPermissionDeniedBanner(false)}
color={Theme.Colors.whiteText}
size={18}
/>
</Pressable>
</Row>
@@ -109,19 +117,21 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
</View>
);
};
return (
<>
{hasCameraPermission ? (
<Column style={Theme.CameraEnabledStyles.container}>
<View style={Theme.CameraEnabledStyles.scannerContainer}>
<Camera
<CameraView
{...testIDProps('camera')}
style={Theme.CameraEnabledStyles.scanner}
barCodeScannerSettings={{
barcodeTypes: [BarCodeScanner.Constants.BarCodeType.qr],
barcodeScannerSettings={{
barcodeTypes: [BarCodeTypes.QR],
}}
onBarCodeScanned={scanned ? undefined : onBarcodeScanned}
type={cameraType}
onBarcodeScanned={scanned ? undefined : onBarcodeScanned}
facing={cameraType}
active={isCameraActive}
/>
</View>
<Column fill align="space-between" style={{marginTop: 24}}>
@@ -138,9 +148,9 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
<TouchableOpacity
onPress={() => {
setCameraType(
cameraType === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back,
cameraType === CameraType.back
? CameraType.front
: CameraType.back,
);
}}>
{SvgImage.FlipCameraIcon()}
@@ -160,7 +170,7 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
</>
);
function onBarcodeScanned(event: BarCodeEvent) {
function onBarcodeScanned(event: BarcodeScanningResult) {
props.onQrFound(event.data);
setScanned(true);
}
@@ -170,3 +180,7 @@ interface QrScannerProps {
onQrFound: (data: string) => void;
title?: string;
}
enum BarCodeTypes {
QR = 'qr',
}

View File

@@ -9,7 +9,7 @@ export const SectionLayout: React.FC<SectionLayoutProps> = ({
headerText,
children,
testId,
marginBottom,
marginBottom = 0,
}) => {
return (
<View
@@ -22,45 +22,22 @@ export const SectionLayout: React.FC<SectionLayoutProps> = ({
rowGap: 2,
}}>
<Row
style={{
alignItems: 'center',
padding: 16,
backgroundColor: Theme.Colors.whiteBackgroundColor,
borderTopLeftRadius: 6,
borderTopRightRadius: 6,
}}>
style={Theme.SectionLayoutStyles.headerContainer}>
{headerIcon}
<Text
style={{
justifyContent: 'center',
paddingLeft: 12,
fontFamily: 'Inter_500Medium',
fontWeight: '600',
fontSize: 14,
letterSpacing: 0,
lineHeight: 17,
}}
style={Theme.SectionLayoutStyles.headerText}
testID={`${testId}Header`}>
{headerText}
</Text>
</Row>
<Row
style={{
padding: 16,
backgroundColor: Theme.Colors.whiteBackgroundColor,
borderBottomLeftRadius: 6,
borderBottomRightRadius: 6,
}}>
style={Theme.SectionLayoutStyles.content}>
<Column fill>{children}</Column>
</Row>
</View>
);
};
SectionLayout.defaultProps = {
marginBottom: 0,
};
export type SectionLayoutProps = {
headerIcon: React.ReactNode;
headerText: string;

View File

@@ -9,20 +9,20 @@ import {
selectCredential,
} from '../../machines/VerifiableCredential/VCItemMachine/VCItemSelectors';
import {useInterpret, useSelector} from '@xstate/react';
import {VCItemProps} from './Views/VCCardView';
import {
createVCItemMachine,
VCItemEvents,
} from '../../machines/VerifiableCredential/VCItemMachine/VCItemMachine';
import {selectIsSavingFailedInIdle} from '../../screens/Home/MyVcsTabMachine';
import {selectIsTourGuide} from '../../machines/auth';
import {VCMetadata} from "../../shared/VCMetadata";
export function useVcItemController(props: VCItemProps) {
export function useVcItemController(vcMetadata: VCMetadata) {
const {appService} = useContext(GlobalContext);
const machine = useRef(
createVCItemMachine(
appService.getSnapshot().context.serviceRefs,
props.vcMetadata,
vcMetadata,
),
);
const VCItemService = useInterpret(machine.current, {devTools: __DEV__});

View File

@@ -1,4 +1,5 @@
import React, {useEffect, useState} from 'react';
import * as React from 'react';
import {useEffect, useState} from 'react';
import {Pressable} from 'react-native';
import {ActorRefFrom} from 'xstate';
import {ErrorMessageOverlay} from '../../MessageOverlay';
@@ -16,8 +17,20 @@ import {useTranslation} from 'react-i18next';
import {Copilot} from '../../ui/Copilot';
import {VCProcessor} from '../common/VCProcessor';
export const VCCardView: React.FC<VCItemProps> = props => {
const controller = useVcItemController(props);
export const VCCardView: React.FC<VCItemProps> = ({
vcMetadata,
margin,
selectable,
selected,
onPress,
onShow,
isDownloading,
isPinned,
flow,
isInitialLaunch = false,
isTopCard = false,
}) => {
const controller = useVcItemController(vcMetadata);
const {t} = useTranslation();
const service = controller.VCItemService;
@@ -25,11 +38,11 @@ export const VCCardView: React.FC<VCItemProps> = props => {
const generatedOn = -controller.generatedOn;
let formattedDate =
generatedOn && format(new Date(generatedOn), 'MM/dd/yyyy');
generatedOn && format(new Date(generatedOn), 'MM/dd/yyyy');
useEffect(() => {
controller.UPDATE_VC_METADATA(props.vcMetadata);
}, [props.vcMetadata]);
controller.UPDATE_VC_METADATA(vcMetadata);
}, [vcMetadata]);
const [fields, setFields] = useState([]);
const [wellknown, setWellknown] = useState(null);
@@ -37,17 +50,17 @@ export const VCCardView: React.FC<VCItemProps> = props => {
useEffect(() => {
async function loadVc() {
if (!props.isDownloading) {
if (!isDownloading) {
const processedData = await VCProcessor.processForRendering(
controller.credential,
controller.verifiableCredentialData.format,
controller.credential,
controller.verifiableCredentialData.format,
);
setVc(processedData);
}
}
loadVc();
}, [props.isDownloading, controller.credential]);
}, [isDownloading, controller.credential]);
useEffect(() => {
const {
@@ -58,22 +71,22 @@ export const VCCardView: React.FC<VCItemProps> = props => {
} = verifiableCredentialData;
if (wellKnown) {
getCredentialIssuersWellKnownConfig(
issuer,
CARD_VIEW_DEFAULT_FIELDS,
credentialConfigurationId,
format,
props.vcMetadata.issuerHost,
issuer,
CARD_VIEW_DEFAULT_FIELDS,
credentialConfigurationId,
format,
vcMetadata.issuerHost,
)
.then(response => {
setWellknown(response.matchingCredentialIssuerMetadata);
setFields(response.fields);
})
.catch(error => {
console.error(
'Error occurred while fetching wellknown for viewing VC ',
error,
);
});
.then(response => {
setWellknown(response.matchingCredentialIssuerMetadata);
setFields(response.fields);
})
.catch(error => {
console.error(
'Error occurred while fetching wellknown for viewing VC ',
error,
);
});
}
}, [verifiableCredentialData?.wellKnown]);
@@ -81,60 +94,60 @@ export const VCCardView: React.FC<VCItemProps> = props => {
return <VCCardSkeleton />;
}
const CardViewContent = props => (
<VCCardViewContent
vcMetadata={props.vcMetadata}
context={controller.context}
walletBindingResponse={controller.walletBindingResponse}
credential={vc}
verifiableCredentialData={verifiableCredentialData}
fields={fields}
wellknown={wellknown}
generatedOn={formattedDate}
selectable={props.selectable}
selected={props.selected}
service={service}
isPinned={props.isPinned}
onPress={() => props.onPress(service)}
isDownloading={props.isDownloading}
flow={props.flow}
isKebabPopUp={controller.isKebabPopUp}
DISMISS={controller.DISMISS}
KEBAB_POPUP={controller.KEBAB_POPUP}
isInitialLaunch={props.isInitialLaunch}
/>
const CardViewContent = () => (
<VCCardViewContent
vcMetadata={vcMetadata}
context={controller.context}
walletBindingResponse={controller.walletBindingResponse}
credential={vc}
verifiableCredentialData={verifiableCredentialData}
fields={fields}
wellknown={wellknown}
generatedOn={formattedDate}
selectable={selectable}
selected={selected}
service={service}
isPinned={isPinned}
onPress={() => onPress(service)}
isDownloading={isDownloading}
flow={flow}
isKebabPopUp={controller.isKebabPopUp}
DISMISS={controller.DISMISS}
KEBAB_POPUP={controller.KEBAB_POPUP}
isInitialLaunch={isInitialLaunch}
/>
);
const wrapTopCard = props => (
<Copilot
description={t('copilot:cardMessage')}
order={6}
title={t('copilot:cardTitle')}
children={CardViewContent(props)}
/>
const wrapTopCard = () => (
<Copilot
description={t('copilot:cardMessage')}
order={6}
title={t('copilot:cardTitle')}
children={CardViewContent()}
/>
);
return (
<React.Fragment>
<Pressable
accessible={false}
onPress={() => props.onPress(service)}
style={
props.selected
? Theme.Styles.selectedBindedVc
: Theme.Styles.closeCardBgContainer
}>
{(props.isInitialLaunch || controller.isTourGuide) && props.isTopCard
? wrapTopCard(props)
: CardViewContent(props)}
</Pressable>
<ErrorMessageOverlay
isVisible={controller.isSavingFailedInIdle}
error={controller.storeErrorTranslationPath}
onDismiss={controller.DISMISS}
translationPath={'VcDetails'}
/>
</React.Fragment>
<React.Fragment>
<Pressable
accessible={false}
onPress={() => onPress(service)}
style={
selected
? Theme.Styles.selectedBindedVc
: Theme.Styles.closeCardBgContainer
}>
{(isInitialLaunch || controller.isTourGuide) && isTopCard
? wrapTopCard()
: CardViewContent()}
</Pressable>
<ErrorMessageOverlay
isVisible={controller.isSavingFailedInIdle}
error={controller.storeErrorTranslationPath}
onDismiss={controller.DISMISS}
translationPath={'VcDetails'}
/>
</React.Fragment>
);
};
@@ -143,16 +156,11 @@ export interface VCItemProps {
margin?: string;
selectable?: boolean;
selected?: boolean;
onPress?: (vcRef?: ActorRefFrom<typeof VCItemMachine>) => void;
onPress: (vcRef?: ActorRefFrom<typeof VCItemMachine>) => void;
onShow?: (vcRef?: ActorRefFrom<typeof VCItemMachine>) => void;
isDownloading?: boolean;
isPinned?: boolean;
flow?: string;
isInitialLaunch?: boolean;
isTopCard?: boolean;
}
VCCardView.defaultProps = {
isInitialLaunch: false,
isTopCard: false,
};
}

View File

@@ -1,5 +1,5 @@
import React from 'react';
import {ImageBackground, Pressable, Image, View} from 'react-native';
import {ImageBackground, Pressable, View, Image, ImageBackgroundProps} from 'react-native';
import {VCMetadata} from '../../../shared/VCMetadata';
import {KebabPopUp} from '../../KebabPopUp';
import {Credential} from '../../../machines/VerifiableCredential/VCMetaMachine/vc';
@@ -20,14 +20,14 @@ import {useCopilot} from 'react-native-copilot';
import {useTranslation} from 'react-i18next';
import testIDProps from '../../../shared/commonUtil';
export const VCCardViewContent: React.FC<VCItemContentProps> = props => {
const wellknownDisplayProperty = new Display(props.wellknown);
const vcSelectableButton =
props.selectable &&
(props.flow === VCItemContainerFlowType.VP_SHARE ? (
export const VCCardViewContent: React.FC<VCItemContentProps> = ({isPinned = false, context, credential, verifiableCredentialData, fields, wellknown, generatedOn, selectable, selected, service, onPress, isDownloading, flow, walletBindingResponse, KEBAB_POPUP, DISMISS, isKebabPopUp, vcMetadata, isInitialLaunch}) => {
const wellknownDisplayProperty = new Display(wellknown);
const vcSelectableButton =
selectable &&
(flow === VCItemContainerFlowType.VP_SHARE ? (
<CheckBox
checked={props.selected}
checked={selected}
checkedIcon={SvgImage.selectedCheckBox()}
uncheckedIcon={
<Icon
@@ -36,11 +36,11 @@ export const VCCardViewContent: React.FC<VCItemContentProps> = props => {
size={22}
/>
}
onPress={() => props.onPress()}
onPress={() => onPress()}
/>
) : (
<CheckBox
checked={props.selected}
checked={selected}
checkedIcon={
<Icon name="check-circle" type="material" color={Theme.Colors.Icon} />
}
@@ -50,17 +50,17 @@ export const VCCardViewContent: React.FC<VCItemContentProps> = props => {
color={Theme.Colors.uncheckedIcon}
/>
}
onPress={() => props.onPress()}
onPress={() => onPress()}
/>
));
const issuerLogo = props.verifiableCredentialData.issuerLogo;
const faceImage = props.verifiableCredentialData.face;
const issuerLogo = verifiableCredentialData.issuerLogo;
const faceImage = verifiableCredentialData.face;
const {start} = useCopilot();
const {t} = useTranslation();
return (
<ImageBackground
source={wellknownDisplayProperty.getBackgroundImage(Theme.CloseCard)}
source={wellknownDisplayProperty.getBackgroundImage(Theme.CloseCard) as ImageBackgroundProps}
resizeMode="stretch"
imageStyle={Theme.Styles.vcBg}
style={[
@@ -69,61 +69,60 @@ export const VCCardViewContent: React.FC<VCItemContentProps> = props => {
]}>
<View
onLayout={
props.isInitialLaunch
isInitialLaunch
? () => start(t('copilot:cardTitle'))
: undefined
}>
<Row crossAlign="center" padding="3 0 0 3">
{VcItemContainerProfileImage(props)}
<VcItemContainerProfileImage isPinned={isPinned} verifiableCredentialData={verifiableCredentialData} />
<Column fill align={'space-around'} margin="0 10 0 10">
<VCItemFieldValue
key={'credentialType'}
testID="credentialType"
fieldValue={getCredentialType(props.wellknown)}
fieldValue={getCredentialType(wellknown)}
fieldValueColor={wellknownDisplayProperty.getTextColor(
Theme.Colors.Details,
)}
/>
<Row>
<VCVerification
vcMetadata={props.verifiableCredentialData?.vcMetadata}
vcMetadata={verifiableCredentialData?.vcMetadata}
display={wellknownDisplayProperty}
/>
</Row>
</Column>
{isVCLoaded(props.credential, props.fields) && (
{isVCLoaded(credential, fields) && (
<Image
{...testIDProps('issuerLogo')}
src={issuerLogo?.url}
alt={issuerLogo?.alt_text}
style={Theme.Styles.issuerLogo}
resizeMethod="scale"
resizeMode="contain"
resizeMode="cover"
/>
)}
{!Object.values(VCItemContainerFlowType).includes(props.flow) && (
{!Object.values(VCItemContainerFlowType).includes(flow) && (
<>
{!props.verifiableCredentialData?.vcMetadata.isExpired &&
(!props.walletBindingResponse &&
isActivationNeeded(props.verifiableCredentialData?.issuer)
{!verifiableCredentialData?.vcMetadata.isExpired &&
(!walletBindingResponse &&
isActivationNeeded(verifiableCredentialData?.issuer)
? SvgImage.walletUnActivatedIcon()
: SvgImage.walletActivatedIcon())}
<Pressable
onPress={props.KEBAB_POPUP}
onPress={KEBAB_POPUP}
accessible={false}
style={Theme.Styles.kebabPressableContainer}>
<KebabPopUp
iconColor={wellknownDisplayProperty.getTextColor(
Theme.Colors.helpText,
)}
vcMetadata={props.vcMetadata}
vcMetadata={vcMetadata}
iconName="dots-three-horizontal"
iconType="entypo"
isVisible={props.isKebabPopUp}
onDismiss={props.DISMISS}
service={props.service}
isVisible={isKebabPopUp}
onDismiss={DISMISS}
service={service}
vcHasImage={faceImage !== undefined}
/>
</Pressable>
@@ -132,15 +131,15 @@ export const VCCardViewContent: React.FC<VCItemContentProps> = props => {
{vcSelectableButton}
</Row>
<WalletBinding service={props.service} vcMetadata={props.vcMetadata} />
<WalletBinding service={service} vcMetadata={vcMetadata} />
<RemoveVcWarningOverlay
testID="removeVcWarningOverlay"
service={props.service}
vcMetadata={props.vcMetadata}
service={service}
vcMetadata={vcMetadata}
/>
<HistoryTab service={props.service} vcMetadata={props.vcMetadata} />
<HistoryTab service={service} vcMetadata={vcMetadata} />
</View>
</ImageBackground>
);
@@ -157,7 +156,7 @@ export interface VCItemContentProps {
selected: boolean;
isPinned?: boolean;
service: any;
onPress?: () => void;
onPress: () => void;
isDownloading?: boolean;
flow?: string;
walletBindingResponse: {};
@@ -166,8 +165,4 @@ export interface VCItemContentProps {
isKebabPopUp: boolean;
vcMetadata: VCMetadata;
isInitialLaunch?: boolean;
}
VCCardViewContent.defaultProps = {
isPinned: false,
};
}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import {useTranslation} from 'react-i18next';
import {Image, ImageBackground, View} from 'react-native';
import {Image, ImageBackground, ImageBackgroundProps, View} from 'react-native';
import {
Credential,
CredentialWrapper,
@@ -38,7 +38,7 @@ const getProfileImage = (face: any) => {
);
};
export const VCDetailView: React.FC<VCItemDetailsProps> = props => {
export const VCDetailView: React.FC<VCItemDetailsProps> = (props: VCItemDetailsProps) => {
const {t} = useTranslation('VcDetails');
const logo = props.verifiableCredentialData.issuerLogo;
const face = props.verifiableCredentialData.face;
@@ -91,7 +91,7 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = props => {
]}
source={wellknownDisplayProperty.getBackgroundImage(
Theme.OpenCard,
)}>
) as ImageBackgroundProps}>
<Row padding="14 14 0 14" margin="0 0 0 0">
<Column crossAlign="center">
{getProfileImage(face)}

View File

@@ -158,7 +158,6 @@ export const getFieldName = (
return i18n.t(`VcDetails:${field}`);
};
export function getAddressFields() {
return [
'addressLine1',
@@ -300,7 +299,7 @@ export const getCredentialTypeFromWellKnown = (
export class Display {
private readonly textColor: string | undefined = undefined;
private readonly backgroundColor: {backgroundColor: string};
private readonly backgroundImage: string | undefined = undefined;
private readonly backgroundImage: { uri: string } | undefined = undefined;
private defaultBackgroundColor = Theme.Colors.whiteBackgroundColor;

View File

@@ -1,27 +1,31 @@
import {VCItemContentProps} from './VC/Views/VCCardViewContent';
import {ImageBackground} from 'react-native';
import {Theme} from './ui/styleUtils';
import React from 'react';
import {ProfileIcon} from './ProfileIcon';
import {SvgImage} from './ui/svg';
export const VcItemContainerProfileImage = (props: VCItemContentProps) => {
const imageUri = props.verifiableCredentialData.face;
export const VcItemContainerProfileImage = ({verifiableCredentialData, isPinned}: VcItemContainerProfileImageProps) => {
const imageUri = verifiableCredentialData.face;
return imageUri ? (
<ImageBackground
imageStyle={Theme.Styles.faceImage}
source={{uri: imageUri}}
style={Theme.Styles.closeCardImage}>
{props?.isPinned && SvgImage.pinIcon()}
{isPinned && SvgImage.pinIcon()}
</ImageBackground>
) : (
<>
<ProfileIcon
isPinned={props?.isPinned}
isPinned={isPinned}
profileIconContainerStyles={Theme.Styles.ProfileIconContainer}
profileIconSize={30}
/>
</>
);
};
interface VcItemContainerProfileImageProps {
verifiableCredentialData: any;
isPinned?: boolean;
}

View File

@@ -11,82 +11,108 @@ import {Modal} from './Modal';
export const Error: React.FC<ErrorProps> = props => {
const {t} = useTranslation('common');
const {
testID,
customStyles = {},
customImageStyles = {},
goBackType,
isModal = false,
isVisible,
showClose = true,
alignActionsOnEnd = false,
title,
message,
helpText,
image,
goBack,
goBackButtonVisible = false,
tryAgain,
onDismiss,
primaryButtonText,
primaryButtonEvent,
testIDTextButton,
textButtonText,
textButtonEvent,
primaryButtonTestID,
textButtonTestID,
} = props;
const errorContent = () => {
return (
<Fragment>
<View
style={[
{alignItems: 'center', marginHorizontal: 1},
props.customStyles,
customStyles,
]}>
<View>
<Row
align="center"
style={[Theme.ErrorStyles.image, props.customImageStyles]}>
{props.image}
style={[Theme.ErrorStyles.image, customImageStyles]}>
{image}
</Row>
<Text
style={Theme.ErrorStyles.title}
testID={`${props.testID}Title`}>
{props.title}
testID={`${testID}Title`}>
{title}
</Text>
<Text
style={Theme.ErrorStyles.message}
testID={`${props.testID}Message`}>
{props.message}
testID={`${testID}Message`}>
{message}
</Text>
</View>
{!props.alignActionsOnEnd && (
{!alignActionsOnEnd && (
<Fragment>
{props.primaryButtonText && (
{primaryButtonText && (
<Button
onPress={props.primaryButtonEvent}
title={t(props.primaryButtonText)}
onPress={primaryButtonEvent}
title={t(primaryButtonText)}
type={
props.primaryButtonText === 'tryAgain'
primaryButtonText === 'tryAgain'
? 'outline'
: 'gradient'
}
width={
props.primaryButtonText === 'tryAgain'
primaryButtonText === 'tryAgain'
? Dimensions.get('screen').width * 0.54
: undefined
}
testID={props.primaryButtonTestID}
testID={primaryButtonTestID}
/>
)}
{props.textButtonText && (
{textButtonText && (
<Button
onPress={props.textButtonEvent}
onPress={textButtonEvent}
width={Dimensions.get('screen').width * 0.54}
title={t(props.textButtonText)}
title={t(textButtonText)}
type="clear"
testID={props.textButtonTestID}
testID={textButtonTestID}
/>
)}
</Fragment>
)}
</View>
{props.alignActionsOnEnd && (
{alignActionsOnEnd && (
<Column fill crossAlign="center" align="flex-end" margin="0 0 30 0">
<Row style={{marginHorizontal: 30, marginBottom: 15}}>
{props.primaryButtonText && (
{primaryButtonText && (
<Button
fill
onPress={props.primaryButtonEvent}
title={t(props.primaryButtonText)}
onPress={primaryButtonEvent}
title={t(primaryButtonText)}
type="gradient"
testID={props.primaryButtonTestID}
testID={primaryButtonTestID}
/>
)}
</Row>
<Row>
{props.textButtonText && (
{textButtonText && (
<Button
onPress={props.textButtonEvent}
title={t(props.textButtonText)}
onPress={textButtonEvent}
title={t(textButtonText)}
type="clear"
testID={props.textButtonTestID}
testID={textButtonTestID}
/>
)}
</Row>
@@ -99,7 +125,7 @@ export const Error: React.FC<ErrorProps> = props => {
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
props.onDismiss && props.onDismiss();
onDismiss && onDismiss();
return true;
};
@@ -112,16 +138,16 @@ export const Error: React.FC<ErrorProps> = props => {
}, []),
);
return props.isModal ? (
return isModal ? (
<Modal
isVisible={props.isVisible}
showClose={props.showClose}
onDismiss={props.onDismiss}
{...testIDProps(props.testID)}>
isVisible={isVisible}
showClose={showClose}
onDismiss={onDismiss}
{...testIDProps(testID)}>
<Column
fill
safe
align={props.alignActionsOnEnd ? 'space-around' : 'space-evenly'}>
align={alignActionsOnEnd ? 'space-around' : 'space-evenly'}>
{errorContent()}
</Column>
</Modal>
@@ -131,9 +157,9 @@ export const Error: React.FC<ErrorProps> = props => {
...Theme.ModalStyles.modal,
backgroundColor: Theme.Colors.whiteBackgroundColor,
}}
{...testIDProps(props.testID)}>
{...testIDProps(testID)}>
<Column fill safe>
{props.goBack && <Header testID="errorHeader" goBack={props.goBack} />}
{goBack && <Header testID="errorHeader" goBack={goBack} />}
<Column fill safe align="space-evenly">
{errorContent()}
</Column>
@@ -142,13 +168,6 @@ export const Error: React.FC<ErrorProps> = props => {
);
};
Error.defaultProps = {
isModal: false,
goBackButtonVisible: false,
alignActionsOnEnd: false,
showClose: true,
};
export interface ErrorProps {
testID: string;
customStyles?: {};
@@ -173,4 +192,4 @@ export interface ErrorProps {
textButtonEvent?: () => void;
primaryButtonTestID?: string;
textButtonTestID?: string;
}
}

View File

@@ -48,12 +48,12 @@ function createLayout(
const ViewType = props.safe ? SafeAreaView : View;
return props.scroll ? (
<ScrollView
{...testIDProps(props.testID)}
contentContainerStyle={styles}
refreshControl={props.refreshControl}>
{props.children}
</ScrollView>
<ScrollView
{...testIDProps(props.testID)}
contentContainerStyle={styles}
refreshControl={props.refreshControl}>
{props.children}
</ScrollView>
) : (
<ViewType {...testIDProps(props.testID)} style={styles}>
{props.children}

View File

@@ -8,7 +8,21 @@ import {Modal} from './Modal';
import {BannerNotification} from '../../components/BannerNotification';
import {BannerStatusType} from '../../components/BannerNotification';
export const Loader: React.FC<LoaderProps> = props => {
export const Loader: React.FC<LoaderProps> = ({
title,
subTitle,
isModal = false,
hint,
onStayInProgress,
isHintVisible,
onCancel,
onRetry,
showBanner,
bannerMessage,
onBannerClose,
bannerType,
bannerTestID,
}) => {
const {t} = useTranslation('ScanScreen');
useEffect(() => {
@@ -28,37 +42,37 @@ export const Loader: React.FC<LoaderProps> = props => {
<Column margin="24 0" align="space-around">
<LoaderAnimation testID={'loader'} />
</Column>
{(props.isHintVisible || props.onCancel) && (
{(isHintVisible || onCancel) && (
<Column style={Theme.SelectVcOverlayStyles.timeoutHintContainer}>
{props.hint && (
{hint && (
<Text
align="center"
margin="10"
color={Theme.Colors.TimeoutHintText}
size="small"
style={Theme.TextStyles.bold}>
{props.hint}
{hint}
</Text>
)}
{props.onStayInProgress && (
{onStayInProgress && (
<Button
type="clear"
title={t('status.stayOnTheScreen')}
onPress={props.onStayInProgress}
onPress={onStayInProgress}
/>
)}
{props.onRetry && (
{onRetry && (
<Button
type="clear"
title={t('status.retry')}
onPress={props.onRetry}
onPress={onRetry}
/>
)}
{props.onCancel && (
{onCancel && (
<Button
type="clear"
title={t('common:cancel')}
onPress={props.onCancel}
onPress={onCancel}
/>
)}
</Column>
@@ -69,10 +83,10 @@ export const Loader: React.FC<LoaderProps> = props => {
return (
<Fragment>
{props.isModal ? (
{isModal ? (
<Modal
headerTitle={props.title}
isVisible={props.isModal}
headerTitle={title}
isVisible={isModal}
headerElevation={3}
headerLeft={<Fragment></Fragment>}
showClose={false}>
@@ -95,14 +109,14 @@ export const Loader: React.FC<LoaderProps> = props => {
<Text
style={Theme.TextStyles.semiBoldHeader}
testID="loaderTitle">
{props.title}
{title}
</Text>
{props.subTitle && (
{subTitle && (
<Text
style={Theme.TextStyles.subHeader}
color={Theme.Colors.textLabel}
testID="loaderSubTitle">
{props.subTitle}
{subTitle}
</Text>
)}
</View>
@@ -110,28 +124,24 @@ export const Loader: React.FC<LoaderProps> = props => {
</SafeAreaView>
</Row>
<View style={Theme.Styles.hrLineFill}></View>
{props.showBanner && (
{showBanner && (
<BannerNotification
type={
props.bannerType ? props.bannerType : BannerStatusType.SUCCESS
bannerType ? bannerType : BannerStatusType.SUCCESS
}
message={props.bannerMessage as string}
onClosePress={props.onBannerClose as () => void}
testId={props.bannerTestID as string}
message={bannerMessage as string}
onClosePress={onBannerClose as () => void}
testId={bannerTestID as string}
/>
)}
{loaderContent()}
</Fragment>
)}
</Fragment>
{loaderContent()}
</Fragment>
)}
</Fragment>
);
};
Loader.defaultProps = {
isModal: false,
};
export interface LoaderProps {
title: string;
subTitle?: string;
@@ -146,4 +156,4 @@ export interface LoaderProps {
onBannerClose?: () => void;
bannerType?: BannerStatusType;
bannerTestID?: string;
}
}

View File

@@ -6,7 +6,7 @@ import testIDProps from '../../shared/commonUtil';
import {SvgImage} from './svg';
export const LoaderAnimation: React.FC<LoaderAnimationProps> = ({
showLogo,
showLogo = true,
testID,
}) => {
return (
@@ -23,10 +23,6 @@ export const LoaderAnimation: React.FC<LoaderAnimationProps> = ({
);
};
LoaderAnimation.defaultProps = {
showLogo: true,
};
interface LoaderAnimationProps {
showLogo?: boolean;
testID: string;

View File

@@ -8,50 +8,67 @@ import {ElevationLevel, Theme} from './styleUtils';
import testIDProps from '../../shared/commonUtil';
import {BackButton} from './backButton/BackButton';
export const Modal: React.FC<ModalProps> = props => {
export const Modal: React.FC<ModalProps> = ({
testID,
isVisible,
requester,
showClose = true,
showHeader = true,
modalStyle = Theme.ModalStyles.defaultModal,
onDismiss,
headerTitle,
headerElevation,
headerLabel,
headerLabelColor,
headerRight,
headerLeft,
arrowLeft,
onShow,
children,
}) => {
const controller = useSendVcScreen();
return (
<RNModal
{...testIDProps(props.testID)}
{...testIDProps(testID)}
animationType="slide"
style={props.modalStyle}
visible={props.isVisible}
onShow={props.onShow}
onRequestClose={props.onDismiss}>
<Column {...(props.showHeader ? {fill: true, safe: true} : {fill: true})}>
{props.showHeader ? (
<Row elevation={props.headerElevation}>
<View style={props.modalStyle}>
{props.headerRight && !props.arrowLeft ? (
style={modalStyle}
visible={isVisible}
onShow={onShow}
onRequestClose={onDismiss}>
<Column {...(showHeader ? {fill: true, safe: true} : {fill: true})}>
{showHeader ? (
<Row elevation={headerElevation}>
<View style={modalStyle}>
{headerRight && !arrowLeft ? (
<Icon
{...testIDProps('closeModal')}
name={I18nManager.isRTL ? 'chevron-right' : 'chevron-left'}
onPress={props.onDismiss}
onPress={onDismiss}
color={Theme.Colors.Icon}
/>
) : null}
{props.arrowLeft && props.onDismiss ? (
<BackButton onPress={props.onDismiss} />
{arrowLeft && onDismiss ? (
<BackButton onPress={onDismiss} />
) : null}
<Row
fill
align={props.headerLeft ? 'flex-start' : 'center'}
margin={props.arrowLeft ? '16 0 0 -15' : '16 0 0 10'}>
align={headerLeft ? 'flex-start' : 'center'}
margin={arrowLeft ? '16 0 0 -15' : '16 0 0 10'}>
<Column>
<Text testID={props.testID} style={Theme.TextStyles.header}>
{props.headerTitle || props.headerLeft}
<Text testID={testID} style={Theme.TextStyles.header}>
{headerTitle || headerLeft}
</Text>
{!props.requester ? (
{!requester ? (
<Text
weight="semibold"
style={Theme.TextStyles.small}
color={
props.headerLabelColor
? props.headerLabelColor
headerLabelColor
? headerLabelColor
: Theme.Colors.textLabel
}>
{props.headerLabel}
{headerLabel}
</Text>
) : (
<Text
@@ -63,33 +80,27 @@ export const Modal: React.FC<ModalProps> = props => {
)}
</Column>
</Row>
{props.headerRight != null ||
props.arrowLeft ||
(props.showClose && (
{headerRight != null ||
arrowLeft ||
(showClose && (
<Icon
{...testIDProps('close')}
name="close"
onPress={props.onDismiss}
onPress={onDismiss}
color={Theme.Colors.Details}
size={27}
/>
))}
{props.headerRight && props.headerRight}
{headerRight && headerRight}
</View>
</Row>
) : null}
{props.children}
{children}
</Column>
</RNModal>
);
};
Modal.defaultProps = {
modalStyle: Theme.ModalStyles.defaultModal,
showClose: true,
showHeader: true,
};
export interface ModalProps {
testID?: string;
isVisible: boolean;
@@ -107,4 +118,4 @@ export interface ModalProps {
arrowLeft?: boolean;
onShow?: () => void;
children?: React.ReactNode;
}
}

View File

@@ -5,18 +5,18 @@ import {Row} from './Layout';
import {Theme} from './styleUtils';
import {SvgImage} from './svg';
export const SearchBar = (props: SearchBarProps) => {
export const SearchBar = ({ isVcSearch = false, searchIconTestID, searchBarTestID, placeholder, search, onFocus, onChangeText, onLayout, editable = true }: SearchBarProps) => {
return (
<Row>
{props.isVcSearch ? (
{isVcSearch ? (
<View
testID={props.searchIconTestID}
testID={searchIconTestID}
style={Theme.SearchBarStyles.vcSearchIcon}>
{SvgImage.SearchIcon()}
</View>
) : (
<Icon
testID={props.searchIconTestID}
testID={searchIconTestID}
name="search"
color={Theme.Colors.Icon}
size={27}
@@ -24,23 +24,19 @@ export const SearchBar = (props: SearchBarProps) => {
/>
)}
<TextInput
testID={props.searchBarTestID}
testID={searchBarTestID}
style={Theme.SearchBarStyles.searchBar}
placeholder={props.placeholder}
value={props.search}
onFocus={props.onFocus}
onChangeText={searchText => props.onChangeText(searchText)}
onLayout={props.onLayout}
editable={props.editable ?? true}
placeholder={placeholder}
value={search}
onFocus={onFocus}
onChangeText={searchText => onChangeText(searchText)}
onLayout={onLayout}
editable={editable ?? true}
/>
</Row>
);
};
SearchBar.defaultProps = {
isVcSearch: false,
};
interface SearchBarProps {
isVcSearch: Boolean;
searchIconTestID: string;

View File

@@ -1270,7 +1270,31 @@ export const DefaultTheme = {
letterSpacing: 0,
lineHeight: 17,
minHeight: 50,
}
}),
SectionLayoutStyles: StyleSheet.create({
headerContainer: {
alignItems: 'center',
padding: 16,
backgroundColor: Colors.White,
borderTopLeftRadius: 6,
borderTopRightRadius: 6,
},
headerText: {
justifyContent: 'center',
paddingLeft: 12,
fontFamily: 'Inter_500Medium',
fontWeight: '600',
fontSize: 14,
letterSpacing: 0,
lineHeight: 17,
},
content: {
padding: 16,
backgroundColor: Colors.White,
borderBottomLeftRadius: 6,
borderBottomRightRadius: 6,
}
}),
TextEditOverlayStyles: StyleSheet.create({
overlay: {
@@ -1639,12 +1663,12 @@ export const DefaultTheme = {
biometricIntroOuterColumn: {
borderRadius: 30,
maxHeight: 600,
maxWidth:350,
maxWidth: 350,
minHeight: 600,
minWidth:350,
minWidth: 350,
borderColor: Colors.Black,
borderWidth: 12,
overflow: 'hidden',
overflow: 'hidden',
},
quickAccessIntroOuterView: {
borderRadius: 30,
@@ -1910,14 +1934,8 @@ export const DefaultTheme = {
ICON_SMALL_SIZE: 16,
ICON_MID_SIZE: 22,
ICON_LARGE_SIZE: 33,
CloseCard: require('../../../assets/Card_Bg1.png'),
OpenCard: require('../../../assets/Card_Bg1.png'),
IntroWelcome: require('../../../assets/biometricIntro.png'),
SecureSharing: require('../../../assets/secureSharing.png'),
DigitalWallet: require('../../../assets/trustedDigitalWallet.png'),
IntroShare: require('../../../assets/quickAccess.png'),
IntroBackup: require('../../../assets/backupRestoreIntro.png'),
IntroSliderbackground: require('../../../assets/IntroBg.png'),
CloseCard: require('../../../assets/images/png/Card_Bg1.png'),
OpenCard: require('../../../assets/images/png/Card_Bg1.png'),
HomeScreenLogo: HomeScreenLogo,
InjiLogoSmall: InjiLogoSmall,
elevation(level: ElevationLevel): ViewStyle {

View File

@@ -1277,6 +1277,30 @@ export const PurpleTheme = {
minHeight: 50,
},
}),
SectionLayoutStyles: StyleSheet.create({
headerContainer: {
alignItems: 'center',
padding: 16,
backgroundColor: Colors.White,
borderTopLeftRadius: 6,
borderTopRightRadius: 6,
},
headerText: {
justifyContent: 'center',
paddingLeft: 12,
fontFamily: 'Inter_500Medium',
fontWeight: '600',
fontSize: 14,
letterSpacing: 0,
lineHeight: 17,
},
content: {
padding: 16,
backgroundColor: Colors.White,
borderBottomLeftRadius: 6,
borderBottomRightRadius: 6,
}
}),
TextEditOverlayStyles: StyleSheet.create({
overlay: {
elevation: 5,
@@ -1645,12 +1669,12 @@ export const PurpleTheme = {
biometricIntroOuterColumn: {
borderRadius: 30,
maxHeight: 600,
maxWidth:350,
maxWidth: 350,
minHeight: 600,
minWidth:350,
minWidth: 350,
borderColor: Colors.Black,
borderWidth: 12,
overflow: 'hidden',
overflow: 'hidden',
},
quickAccessIntroOuterView: {
borderRadius: 30,
@@ -1914,14 +1938,8 @@ export const PurpleTheme = {
ICON_SMALL_SIZE: 16,
ICON_MID_SIZE: 22,
ICON_LARGE_SIZE: 33,
CloseCard: require('../../../assets/Card_Bg1.png'),
OpenCard: require('../../../assets/Card_Bg1.png'),
IntroWelcome: require('../../../assets/Intro_Unlock.png'),
SecureSharing: require('../../../assets/Intro_Secure_Sharing.png'),
DigitalWallet: require('../../../assets/Intro_Wallet.png'),
IntroShare: require('../../../assets/Intro_Share.png'),
IntroBackup: require('../../../assets/Intro_Backup.png'),
IntroSliderbackground: require('../../../assets/IntroSliderBackgroundPurple.png'),
CloseCard: require('../../../assets/images/png/Card_Bg1.png'),
OpenCard: require('../../../assets/images/png/Card_Bg1.png'),
HomeScreenLogo: HomeScreenLogo,
InjiLogoSmall: InjiLogoSmall,
elevation(level: ElevationLevel): ViewStyle {

View File

@@ -10,18 +10,18 @@
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
1E6875E92CA554E80086D870 /* OpenID4VP in Frameworks */ = {isa = PBXBuildFile; productRef = 1E6875E82CA554E80086D870 /* OpenID4VP */; };
1E6875EB2CA554FD0086D870 /* RNOpenID4VPModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */; };
1E6875ED2CA5550F0086D870 /* RNOpenID4VPModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */; };
1EC395242D50C89C0022D979 /* VCIClient in Frameworks */ = {isa = PBXBuildFile; productRef = 1EC395232D50C89C0022D979 /* VCIClient */; };
1EC3952A2D50C9470022D979 /* pixelpass in Frameworks */ = {isa = PBXBuildFile; productRef = 1EC395292D50C9470022D979 /* pixelpass */; };
1EC3952D2D50C9820022D979 /* ios-tuvali-library in Frameworks */ = {isa = PBXBuildFile; productRef = 1EC3952C2D50C9820022D979 /* ios-tuvali-library */; };
1EC395302D50C99E0022D979 /* securekeystore in Frameworks */ = {isa = PBXBuildFile; productRef = 1EC3952F2D50C99E0022D979 /* securekeystore */; };
34EC7A062D93F9D800F50036 /* OpenID4VP in Frameworks */ = {isa = PBXBuildFile; productRef = 3407B0FF2D706EE1003089E6 /* OpenID4VP */; };
34873E472CD8DAF3004DE734 /* VCIClient in Frameworks */ = {isa = PBXBuildFile; productRef = 34873E462CD8DAF3004DE734 /* VCIClient */; };
34873E4D2CD8DD11004DE734 /* pixelpass in Frameworks */ = {isa = PBXBuildFile; productRef = 34873E4C2CD8DD11004DE734 /* pixelpass */; };
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
717E6FEC33D6D8A2F9B01CBC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1D23B9CD47CFD7F3C87D202F /* PrivacyInfo.xcprivacy */; };
73295844242A4AD3AA52D0BE /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = D98B96A488E54CBDB286B26F /* noop-file.swift */; };
96905EF65AED1B983A6B3ABC /* libPods-Inji.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Inji.a */; };
9C0E86B52BEE357A00E9F9F6 /* RNPixelpassModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C0E86B42BEE357A00E9F9F6 /* RNPixelpassModule.swift */; };
9C0E86BB2BEE36C300E9F9F6 /* RNPixelpassModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C0E86BA2BEE36C300E9F9F6 /* RNPixelpassModule.m */; };
9C4850432C3E5873002ECBD5 /* ios-tuvali-library in Frameworks */ = {isa = PBXBuildFile; productRef = 9C4850422C3E5873002ECBD5 /* ios-tuvali-library */; };
9C48504B2C3E59B5002ECBD5 /* RNWalletModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4850442C3E59B5002ECBD5 /* RNWalletModule.swift */; };
9C48504D2C3E59B5002ECBD5 /* RNWalletModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C4850462C3E59B5002ECBD5 /* RNWalletModule.m */; };
9C48504E2C3E59B5002ECBD5 /* RNEventEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4850472C3E59B5002ECBD5 /* RNEventEmitter.swift */; };
@@ -31,6 +31,7 @@
9C4850532C3E59E2002ECBD5 /* RNEventEmitterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4850522C3E59E2002ECBD5 /* RNEventEmitterProtocol.swift */; };
9C7CDF3E2C7CBEDE00243A9A /* RNSecureKeystoreModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C7CDF3D2C7CBEDE00243A9A /* RNSecureKeystoreModule.swift */; };
9C7CDF432C7CC13500243A9A /* RNSecureKeystoreModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7CDF422C7CC13500243A9A /* RNSecureKeystoreModule.m */; };
9CCCA19E2CF87A8400D5A461 /* securekeystore in Frameworks */ = {isa = PBXBuildFile; productRef = 9CCCA19D2CF87A8400D5A461 /* securekeystore */; };
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
E86208152C0335C5007C3E24 /* RNVCIClientModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E86208142C0335C5007C3E24 /* RNVCIClientModule.swift */; };
@@ -64,6 +65,7 @@
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Inji/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Inji/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Inji/main.m; sourceTree = "<group>"; };
1D23B9CD47CFD7F3C87D202F /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Inji/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNOpenID4VPModule.m; sourceTree = "<group>"; };
1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNOpenID4VPModule.swift; sourceTree = "<group>"; };
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Inji.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Inji.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -113,12 +115,12 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
34EC7A062D93F9D800F50036 /* OpenID4VP in Frameworks */,
1EC395242D50C89C0022D979 /* VCIClient in Frameworks */,
1EC3952A2D50C9470022D979 /* pixelpass in Frameworks */,
1EC395302D50C99E0022D979 /* securekeystore in Frameworks */,
34873E472CD8DAF3004DE734 /* VCIClient in Frameworks */,
9C4850432C3E5873002ECBD5 /* ios-tuvali-library in Frameworks */,
1E6875E92CA554E80086D870 /* OpenID4VP in Frameworks */,
9CCCA19E2CF87A8400D5A461 /* securekeystore in Frameworks */,
34873E4D2CD8DD11004DE734 /* pixelpass in Frameworks */,
96905EF65AED1B983A6B3ABC /* libPods-Inji.a in Frameworks */,
1EC3952D2D50C9820022D979 /* ios-tuvali-library in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -152,6 +154,7 @@
E86208162C0335EC007C3E24 /* RNVCIClientModule.m */,
1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */,
1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */,
1D23B9CD47CFD7F3C87D202F /* PrivacyInfo.xcprivacy */,
);
name = Inji;
sourceTree = "<group>";
@@ -165,6 +168,13 @@
name = Frameworks;
sourceTree = "<group>";
};
462CE07025BF40E9952DCDA0 /* Resources */ = {
isa = PBXGroup;
children = (
);
name = Resources;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
@@ -182,6 +192,7 @@
2D16E6871FA4F8E400B85C8A /* Frameworks */,
D65327D7A22EEC0BE12398D9 /* Pods */,
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */,
462CE07025BF40E9952DCDA0 /* Resources */,
);
indentWidth = 2;
sourceTree = "<group>";
@@ -273,7 +284,7 @@
1E55884F2CC0EF2C00CF55B4 /* Copy FaceSDK Model */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
0F2FCBA5E4517C72775B53F7 /* [CP] Embed Pods Frameworks */,
D11A8C363B4A5B625DB10379 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -281,11 +292,11 @@
);
name = Inji;
packageProductDependencies = (
1EC395232D50C89C0022D979 /* VCIClient */,
1EC395292D50C9470022D979 /* pixelpass */,
1EC3952C2D50C9820022D979 /* ios-tuvali-library */,
1EC3952F2D50C99E0022D979 /* securekeystore */,
3407B0FF2D706EE1003089E6 /* OpenID4VP */,
9C4850422C3E5873002ECBD5 /* ios-tuvali-library */,
1E6875E82CA554E80086D870 /* OpenID4VP */,
34873E462CD8DAF3004DE734 /* VCIClient */,
34873E4C2CD8DD11004DE734 /* pixelpass */,
9CCCA19D2CF87A8400D5A461 /* securekeystore */,
);
productName = Inji;
productReference = 13B07F961A680F5B00A75B9A /* Inji.app */;
@@ -314,11 +325,11 @@
);
mainGroup = 83CBB9F61A601CBA00E9B192;
packageReferences = (
1EC395222D50C89C0022D979 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */,
1EC395282D50C9470022D979 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */,
1EC3952B2D50C9820022D979 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */,
1EC3952E2D50C99E0022D979 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */,
3407B0FE2D706EE1003089E6 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */,
34873E4B2CD8DD11004DE734 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */,
34873E452CD8DAF3004DE734 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */,
9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */,
1E6875E72CA554E80086D870 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */,
9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */,
);
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
@@ -356,6 +367,7 @@
FD8D20C92BBAACDF009AD01C /* SimpleLineIcons.ttf in Resources */,
FD8D20C62BBAACDF009AD01C /* Zocial.ttf in Resources */,
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
717E6FEC33D6D8A2F9B01CBC /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -398,24 +410,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
0F2FCBA5E4517C72775B53F7 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Inji/Pods-Inji-frameworks.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Inji/Pods-Inji-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
1E55884F2CC0EF2C00CF55B4 /* Copy FaceSDK Model */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 12;
@@ -460,28 +454,42 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Inji/Pods-Inji-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/AppAuth/AppAuthCore_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates/EXUpdates.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoLocalization/ExpoLocalization_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleSignIn/GoogleSignIn.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/MLKitFaceDetection/GoogleMVFaceDetectorResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/Protobuf/Protobuf_Privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo/RNDeviceInfoPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/ReachabilitySwift.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb_Privacy.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AppAuthCore_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXUpdates.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoLocalization_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleDataTransport_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleUtilities_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMVFaceDetectorResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FBLPromises_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Protobuf_Privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNDeviceInfoPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReachabilitySwift.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/nanopb_Privacy.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
@@ -489,6 +497,24 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Inji/Pods-Inji-resources.sh\"\n";
showEnvVarsInLog = 0;
};
D11A8C363B4A5B625DB10379 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Inji/Pods-Inji-frameworks.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Inji/Pods-Inji-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
FD10A7F022414F080027D42C /* Start Packager */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -591,10 +617,10 @@
CODE_SIGN_ENTITLEMENTS = Inji/InjiRelease.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = V2ABX7953Z;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = V2ABX7953Z;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
INFOPLIST_FILE = Inji/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@@ -612,7 +638,7 @@
PRODUCT_BUNDLE_IDENTIFIER = io.mosip.inji.wallet.mobileid;
PRODUCT_NAME = Inji;
PROVISIONING_PROFILE_SPECIFIER = "match AppStore io.mosip.inji.wallet.mobileid";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.mosip.inji.wallet.mobileid";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.mosip.inji.wallet.mobileid";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -624,8 +650,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CC = "";
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@@ -649,8 +676,9 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CXX = "";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
@@ -669,7 +697,9 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD = "";
LDPLUSPLUS = "";
LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
@@ -677,8 +707,10 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
};
name = Debug;
};
@@ -686,8 +718,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CC = "";
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@@ -714,6 +747,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = YES;
CXX = "";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
@@ -725,15 +759,19 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD = "";
LDPLUSPLUS = "";
LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -762,39 +800,7 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
1EC395222D50C89C0022D979 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/inji-vci-client-ios-swift.git";
requirement = {
branch = develop;
kind = branch;
};
};
1EC395282D50C9470022D979 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/pixelpass-ios-swift.git";
requirement = {
branch = "release-0.6.x";
kind = branch;
};
};
1EC3952B2D50C9820022D979 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/tuvali-ios-swift.git";
requirement = {
kind = exactVersion;
version = 0.5.0;
};
};
1EC3952E2D50C99E0022D979 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/secure-keystore-ios-swift.git";
requirement = {
kind = exactVersion;
version = 0.3.0;
};
};
3407B0FE2D706EE1003089E6 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */ = {
1E6875E72CA554E80086D870 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/inji-openid4vp-ios-swift";
requirement = {
@@ -802,35 +808,67 @@
kind = branch;
};
};
34873E452CD8DAF3004DE734 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/inji-vci-client-ios-swift";
requirement = {
branch = develop;
kind = branch;
};
};
34873E4B2CD8DD11004DE734 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/pixelpass-ios-swift";
requirement = {
branch = "release-0.6.x";
kind = branch;
};
};
9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/tuvali-ios-swift/";
requirement = {
kind = exactVersion;
version = 0.5.0;
};
};
9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/secure-keystore-ios-swift";
requirement = {
kind = exactVersion;
version = 0.3.0;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
1EC395232D50C89C0022D979 /* VCIClient */ = {
1E6875E82CA554E80086D870 /* OpenID4VP */ = {
isa = XCSwiftPackageProductDependency;
package = 1EC395222D50C89C0022D979 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */;
package = 1E6875E72CA554E80086D870 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */;
productName = OpenID4VP;
};
34873E462CD8DAF3004DE734 /* VCIClient */ = {
isa = XCSwiftPackageProductDependency;
package = 34873E452CD8DAF3004DE734 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */;
productName = VCIClient;
};
1EC395292D50C9470022D979 /* pixelpass */ = {
34873E4C2CD8DD11004DE734 /* pixelpass */ = {
isa = XCSwiftPackageProductDependency;
package = 1EC395282D50C9470022D979 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */;
package = 34873E4B2CD8DD11004DE734 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */;
productName = pixelpass;
};
1EC3952C2D50C9820022D979 /* ios-tuvali-library */ = {
9C4850422C3E5873002ECBD5 /* ios-tuvali-library */ = {
isa = XCSwiftPackageProductDependency;
package = 1EC3952B2D50C9820022D979 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */;
package = 9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */;
productName = "ios-tuvali-library";
};
1EC3952F2D50C99E0022D979 /* securekeystore */ = {
9CCCA19D2CF87A8400D5A461 /* securekeystore */ = {
isa = XCSwiftPackageProductDependency;
package = 1EC3952E2D50C99E0022D979 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */;
package = 9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */;
productName = securekeystore;
};
3407B0FF2D706EE1003089E6 /* OpenID4VP */ = {
isa = XCSwiftPackageProductDependency;
package = 3407B0FE2D706EE1003089E6 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */;
productName = OpenID4VP;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
}
}

View File

@@ -1,5 +1,5 @@
{
"originHash" : "89c09865ed302674a6eacbfdc15bccfb27aca83c6e960244a525461f6336a126",
"originHash" : "178f6c7c607eeb08b99a4966015d08339500de64791888a2e79d6b7afae53659",
"pins" : [
{
"identity" : "alamofire",
@@ -58,10 +58,10 @@
{
"identity" : "inji-vci-client-ios-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mosip/inji-vci-client-ios-swift.git",
"location" : "https://github.com/mosip/inji-vci-client-ios-swift",
"state" : {
"branch" : "develop",
"revision" : "d283c4f7951165328c6fd24b1c758baa766af74c"
"revision" : "02f367bd2527f249145393a533f5175918c1fc8a"
}
},
{
@@ -76,7 +76,7 @@
{
"identity" : "pixelpass-ios-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mosip/pixelpass-ios-swift.git",
"location" : "https://github.com/mosip/pixelpass-ios-swift",
"state" : {
"branch" : "release-0.6.x",
"revision" : "15249dc4eecb7c2b6e6074193d3928b3402c9d20"
@@ -94,7 +94,7 @@
{
"identity" : "secure-keystore-ios-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mosip/secure-keystore-ios-swift.git",
"location" : "https://github.com/mosip/secure-keystore-ios-swift",
"state" : {
"revision" : "1ea5182ca985302d11010b7a16ea496167969ab3",
"version" : "0.3.0"
@@ -112,7 +112,7 @@
{
"identity" : "tuvali-ios-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mosip/tuvali-ios-swift.git",
"location" : "https://github.com/mosip/tuvali-ios-swift/",
"state" : {
"revision" : "2d49e123f70dfc2179983a753d370cc2212385db",
"version" : "0.5.0"
@@ -129,4 +129,4 @@
}
],
"version" : 2
}
}

View File

@@ -17,9 +17,14 @@
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self bundleURL];
}
- (NSURL *)bundleURL
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif

View File

@@ -12,23 +12,6 @@
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>UIAppFonts</key>
<array>
<string>MaterialIcons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome6_Brands.ttf</string>
<string>FontAwesome6_Solid.ttf</string>
<string>FontAwesome5_Brands.ttf</string>
<string>FontAwesome5_Solid.ttf</string>
<string>FontAwesome6_Regular.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Entypo.ttf</string>
<string>Feather.ttf</string>
<string>AntDesign.ttf</string>
</array>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
@@ -78,7 +61,6 @@
<string>MaterialIcons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome6_Brands.ttf</string>
<string>FontAwesome6_Solid.ttf</string>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
<string>0A2A.1</string>
<string>3B52.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
<string>1C8F.1</string>
<string>C56D.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
<string>85F4.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>

View File

@@ -8,8 +8,8 @@ podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = '1' if podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR'] == 'true'
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
install! 'cocoapods',
platform :ios, podfile_properties['ios.deploymentTarget'] || '14'
install! 'cocoapods',
:deterministic_uuids => false
prepare_react_native_project!
@@ -25,18 +25,6 @@ prepare_react_native_project!
# }
# }
# ```
flipper_config = FlipperConfiguration.disabled
if ENV['NO_FLIPPER'] == '1' then
# Explicitly disabled through environment variables
flipper_config = FlipperConfiguration.disabled
elsif podfile_properties.key?('ios.flipper') then
# Configure Flipper in Podfile.properties.json
if podfile_properties['ios.flipper'] == 'true' then
flipper_config = FlipperConfiguration.enabled(["Debug", "Release"])
elsif podfile_properties['ios.flipper'] != 'false' then
flipper_config = FlipperConfiguration.enabled(["Debug", "Release"], { 'Flipper' => podfile_properties['ios.flipper'] })
end
end
target 'Inji' do
use_expo_modules!
@@ -55,7 +43,6 @@ target 'Inji' do
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/..",
# Note that if you have use_frameworks! enabled, Flipper will not work if enabled
:flipper_configuration => flipper_config
)
post_install do |installer|
@@ -75,7 +62,7 @@ target 'Inji' do
# necessary for Mac Catalyst builds
:mac_catalyst_enabled => false
)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
# This is necessary for Xcode 14, because it signs resource bundles by default
# when building for devices.
@@ -126,7 +113,7 @@ target 'Inji' do
end
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
end
@@ -150,7 +137,7 @@ target 'Inji' do
end
# https://github.com/CocoaPods/CocoaPods/issues/8122#issuecomment-428677119
# Workaround for removing the multiple Assets added to the project due to react native auto-linkage
# Workaround for removing the multiple Assets added to the project due to react native auto-linkage
project_path = './Inji.xcodeproj'
project = Xcodeproj::Project.open(project_path)
project.targets.each do |target|

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

View File

@@ -514,7 +514,7 @@ export interface displayType {
language: string;
logo: logoType;
background_color: string;
background_image: string;
background_image: { uri: string };
text_color: string;
title: string;
description: string;

View File

@@ -266,7 +266,7 @@ export const appMachine = model.createMachine(
resetLinkCode: assign({
linkCode: '',
}),
forwardToSerices: pure((context, event) =>
forwardToServices: pure((context, event) =>
Object.values(context.serviceRefs).map(serviceRef =>
send({...event, type: `APP_${event.type}`}, {to: serviceRef}),
),

View File

@@ -34,7 +34,7 @@ export interface Typegen0 {
resetQRLoginDeepLinkData: 'done.invoke.app.ready.focus.active:invocation[1]';
};
missingImplementations: {
actions: 'forwardToServices';
actions: never;
delays: never;
guards: never;
services: never;

View File

@@ -1,19 +1,19 @@
import {Camera, CameraCapturedPicture, PermissionResponse} from 'expo-camera';
import {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 {faceCompare} from '@iriscan/biometric-sdk-react-native';
import { ImageType } from '../components/FaceScanner/FaceScannerHelper';
const model = createModel(
{
cameraRef: {} as Camera,
cameraRef: {} as Camera | null,
faceBounds: {
minWidth: 280,
minHeight: 280,
},
capturedImage: {} as CameraCapturedPicture,
capturedImage: {} as CameraCapturedPicture | null,
captureError: '',
},
{
@@ -31,9 +31,9 @@ const model = createModel(
export const FaceScannerEvents = model.events;
export const createFaceScannerMachine = (vcImages: string[]) =>
/** @xstate-layout N4IgpgJg5mDOIC5QDMCGBjMBldqB2eYATgHQCWeZALiegBZjoDWFUACsQLZmyxkD2eAMQARAKIA5AJJiRiUAAd+fKgLzyQAD0QBaAIwAmAyQMBWAJwBmABzWADHoAslywfOOANCACeu0wHYANhJ-R389SzC3QJjLAF84rzRMHHxCUgpqWgZmVg4ibl41IQBxACUAQQkAFVkNJRU1DW0EHUc7YxtA6z09c2sza3NzQK9fVtdjO0s7fqHrAL1-U0CEpIxsXAJickoaBS4ePkERMEpIIQB5NkkAfSwxauqpCRKseuVqJqQtXW6Q6aGbrWGymIzWMa6AwzEiOCwrZwzbp6QL+NYgZKbNI7TL7Q5FE5nMgXCpsNi3ABilwAwgBVB5yH4NL6CZpQ-zGazhQKmUwdSIGVGQiZGEjTWahIYGOx2azOdGY1LbDJ7EhEMAARwArnBVHh2PjjsJylVaozFJ9VKyfi03I4TJFHI4YqYFkEucL9JY9LC9GDxX7zAYQQqNkr0rssurtbq8obiuJpHUmZbvqAWkt7Y5g45ek7A4EnZ7JmLvQ4ZbKrI5zGjEhiw1sI7ihGUxBURABND6Na3pvzBfwclzWQs80y9CE+RBTexcwWy8eFlyhlKNnawRusEiYin8LV4CBCCCCMC7ABu-CYp8Va9IG7SW53e4PCAoF9wVrwAG07ABdbssuoNq6JY5gkN6gSGCiIJ6HYoTLMKrrGMssH2P4lj+HYzp6CuWLKiQ94EI+Gy7vuh7EEQ-CkAoAA2qBUMgVGcNuDbYnem76ixmCkS+b78B+ag-v+KY9kBfYINKpgkCMrpOg42auIEljCu0PqymEMyyoEBi5qsdY3mxBEcVAQgUgAMlI5LUhUACyYiVABn5sggegLCE-gDCCBiDjWIL+MKM6yhygQLiiiK4eG67GaZFTUmItziLU1Jmo5aa-BMIUkNpMzOOYQUYaMU4SWY0lBiM3qWK6qKOAkdZ4PwEBwBoBn4bi2SMCw+r5IURqpb26VtHYwQYUOSlWEYNieiF1ghGEhg1g47jLvprGtaqBwFEcainOcEB9WJA3mD6fIVQYfozNKLjFsGJCmDMIxLTl47xCtq6GW1G09WoJREPgVCQPtzmDfaGEYQMvJOpYSmehE-jSX6rmQdM7gRNYEW3pGNDRjqsB6gam0EgdzJOcBLkeSE0odIO-go3B-lFTorqWCYc2RA4yxBAY6PvXsgOk20MIjdCY2TJNDPIrN4TBpB0puOY3P4YRlCcU+ZF8+JjMzbYjhcjW7TmHyQTCjYM2yehMojjpKIKxGSvEZgEj8FQPF7SJgFA5l2aonK4Rgk43mmAF2awmVmGVa5zpwjbUUPvq6sDTY9rZVhoH5UbRVOHYpXRNmZgebMXOvXhTacKgMDUqgChUFq6quxaolA+0YoxAjbgjrYRjCuhUlmO0Osophzq1usb3KvHLRtKYIODsLoGi5O4w6Ms9rwYYyxGL0ha1XEQA */
model.createMachine(
{
/** @xstate-layout N4IgpgJg5mDOIC5QDMCGBjMBldqB2eYATgHQCWeZALgMQBKAogIIAiAmgNoAMAuoqAAcA9rGpkhefiAAeiAIwAmAOxKSCgByKArFwCc6rVoAsANgUAaEAE9ERuavUBmLboUKuRrUvWatAXz9LNEwcfEJSCmoSdAALMHQAawooAAViAFsyWFEJGhYGADkASQYWbj4kEGFRKnFJStkER0c5EnUjR29mnxbHT0sbBCMuLjUjXV0lCZ0dNwCgjGxcAmJySipouMTktKJM7Lq8wpKyuQrBETEJKUbm1vbOp0ceuT6tAcQTE0cSJXHJ3wmORcEzzEDBJZhVaRDaxeJJPCpDJZHJ4GgAcToTAKABVSuUpNUrvVQLcWm0Ol1nk5Xv1rIgFFoTCR-vp2lxHApdCZ1GCIaEVhF1iQBMiDhIWGBKJAaAB5FKFAD6WAYOJxRQK6KwBMqRNq1wa8i4TN+Kk6emUcnUGg+Q1Mpqtjm5E3cSkcfMWAvCayior2KLqkulEBoTBSKUVADFZQBhACqKrKvEJl31JJkiB8RhZPKmmg0nl0jltxgUJAmEyUcnGKi4SlBgXBnuW3phJCIYAAjgBXOC1RG7faojFY3H45O61N1G6Z9o59R5xTtFzF+lNAzlivW+uaEZGD0hFvQ4Udnt9nZi4f5Yrj85VKcG0mz7OmBf6JeF1eDDrM1ncrjtOokyvAekKCiQsAtskNAxmGOJxowOoXDU06GggS6qBo2h6AYxhmLac6dP89gmNyRhuryjb8kepC4AIVDdkQ0EQBIYBrAAbkICRsdRUK0ag9GMckCAUJxuBpuUSH3ihj4ZuhyiYfmOj6IYpgWGuWjViy1bGppSguDycigV6qx0QxTGIjQxBEEIpACAANqgVDILZ6QkLx4FmUJiIiXgYlOXUkkTshxIzvJC5qEpOGqfha60m0+kjDo6gmEYaUAcZNEkOxxBkMgVjMaxHFcTxzZ8dluX5cJolCOJgW8FJeqoU+6EmEoZZKBycheEY7h7nItpAq0daaORii6CM9aZeVOVMVVlksYQxXce5ZXgbNeUFT5NV1RIklnCmMnpo0cg8h1XU9X1HgDRp3wkF4mjNAocgTZyCjTetlVbVAVlEDZdmOc5rmrYeM1fdVfm1QFe0NcF0mhWhp3Wr8F1-FddglqdJAjXIL2OHoxpKAEjZ4EIEBwFIHnhIdCMtQAtAoRi2nTzIjCM9iKJSbgTB9rbrDTaZhYztpI5uEw8mYaWjf4VFrXzURwtsA6Xs18OC2h7W2goJijNWW5pVh7qy6D4Ftn6Q6BlKZCQALqsncazLPXoZg6CMTolkY6gkH0lYaFyzxurzx6+irEjokQ+BUDbk5HWFwImk73KMmz7trtr2bJ1wuOGO49i6EHQpRKevawP2SL+uK6ZNbJjTfLoCU6FMng9bjtqdJhrI6ECpGaUbCwm96kFhMkts1-I5FexWkwguaTNxS42nDN0uhaO0jKUf3YHel5FlQKPx22OpgyaPdbNcNrxhpfjMubyZpAbfNe8x7TcnVqRbTOK4pHUhNSiY2WK9egeAmmlF6BdsqoHsmQCA+8hZsxRvjSYyVnSDQAm0Q27UAKKCJsbLex52KQOgbAxGAI2jaG+E4bkUwbqDC0M9FkugJ5IyzpyGWAQgA */
predictableActionArguments: true,
preserveActionOrder: true,
tsTypes: {} as import('./faceScanner.typegen').Typegen0,
@@ -69,9 +69,7 @@ export const createFaceScannerMachine = (vcImages: string[]) =>
target: 'permissionDenied',
},
],
GRANTED: {
target: 'permissionGranted',
},
GRANTED: 'permissionGranted',
},
},
permissionDenied: {
@@ -79,9 +77,7 @@ export const createFaceScannerMachine = (vcImages: string[]) =>
OPEN_SETTINGS: {
actions: 'openSettings',
},
APP_FOCUSED: {
target: 'checkingPermission',
},
APP_FOCUSED: 'checkingPermission',
},
},
permissionGranted: {},
@@ -90,12 +86,8 @@ export const createFaceScannerMachine = (vcImages: string[]) =>
src: 'requestPermission',
},
on: {
GRANTED: {
target: 'permissionGranted',
},
DENIED: {
target: 'permissionDenied',
},
GRANTED: 'permissionGranted',
DENIED: 'permissionDenied',
},
},
},
@@ -108,26 +100,20 @@ export const createFaceScannerMachine = (vcImages: string[]) =>
},
scanning: {
on: {
CAPTURE: {
target: 'capturing',
},
CAPTURE: 'capturing',
},
},
capturing: {
invoke: {
src: 'captureImage',
onDone: [
{
actions: 'setCapturedImage',
target: '#faceScanner.verifying',
},
],
onError: [
{
actions: 'setCaptureError',
target: 'scanning',
},
],
onDone: {
actions: 'setCapturedImage',
target: 'verifying',
},
onError: {
actions: 'setCaptureError',
target: 'scanning',
},
},
},
verifying: {
@@ -142,9 +128,7 @@ export const createFaceScannerMachine = (vcImages: string[]) =>
target: 'invalid',
},
],
onError: {
target: 'invalid',
},
onError: 'invalid',
},
},
valid: {
@@ -160,18 +144,14 @@ export const createFaceScannerMachine = (vcImages: string[]) =>
setCameraRef: model.assign({
cameraRef: (_context, event) => event.cameraRef,
}),
setCapturedImage: assign({
capturedImage: (_context, event) => event.data,
}),
setCaptureError: assign({
captureError: '',
captureError: (_, __) => 'Failed to capture image.',
}),
openSettings: () => Linking.openSettings(),
},
services: {
checkPermission: () => async callback => {
const result = await Camera.getCameraPermissionsAsync();
@@ -199,42 +179,32 @@ export const createFaceScannerMachine = (vcImages: string[]) =>
},
verifyImage: async context => {
context.cameraRef.pausePreview();
const {capturedImage} = context;
if (!capturedImage || !capturedImage.base64) {
throw new Error('No image captured');
}
const rxDataURI =
/data:(?<mime>[\w/\-.]+);(?<encoding>\w+),(?<data>.*)/;
let isMatchFound = false;
for (const vcImage of vcImages) {
const matches = rxDataURI.exec(vcImage).groups;
try {
isMatchFound = await faceCompare(
context.capturedImage.base64,
matches.data,
);
if (isMatchFound) {
break;
for (const vcImage of vcImages) {
const matches = rxDataURI.exec(vcImage)?.groups;
if (matches) {
const {data} = matches;
try {
isMatchFound = await faceCompare(capturedImage.base64, data);
if (isMatchFound) break;
} catch (error) {
throw error;
}
} catch (error) {
throw error;
}
}
return isMatchFound;
},
checkNetworkStatus: async () => {
const state = await NetInfo.fetch();
return state.isConnected;
},
},
guards: {
canRequestPermission: (_context, event) => {
return event.response.canAskAgain;
},
doesFaceMatch: (_context, event) => event.data,
canRequestPermission: (_context, event) => event.response.canAskAgain,
doesFaceMatch: (_context, event) => event.data === true,
},
},
);
@@ -275,4 +245,4 @@ export function selectIsValid(state: State) {
export function selectIsInvalid(state: State) {
return state.matches('invalid');
}
}

View File

@@ -8,11 +8,6 @@ export interface Typegen0 {
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]': {
type: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.OpenID4VP.checkKeyPair:invocation[0]': {
type: 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]';
data: unknown;
@@ -62,7 +57,6 @@ export interface Typegen0 {
getKeyPair: 'done.invoke.OpenID4VP.getKeyPairFromKeystore:invocation[0]';
getSelectedKey: 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]';
sendVP: 'done.invoke.OpenID4VP.sendingVP:invocation[0]';
shouldValidateClient: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]';
};
missingImplementations: {
actions:
@@ -102,7 +96,6 @@ export interface Typegen0 {
guards:
| 'hasKeyPair'
| 'isAnyVCHasImage'
| 'isClientValidationRequred'
| 'isFaceVerificationRetryAttempt'
| 'isSelectedVCMatchingRequest'
| 'isShareWithSelfie'
@@ -113,8 +106,7 @@ export interface Typegen0 {
| 'getAuthenticationResponse'
| 'getKeyPair'
| 'getSelectedKey'
| 'sendVP'
| 'shouldValidateClient';
| 'sendVP';
};
eventsCausingActions: {
compareAndStoreSelectedVC: 'SET_SELECTED_VC';
@@ -143,7 +135,7 @@ export interface Typegen0 {
setFlowType: 'AUTHENTICATE';
setIsFaceVerificationRetryAttempt: 'FACE_INVALID';
setIsShareWithSelfie: 'AUTHENTICATE';
setIsShowLoadingScreen: 'AUTHENTICATE';
setIsShowLoadingScreen: 'STORE_RESPONSE';
setMiniViewShareSelectedVC: 'AUTHENTICATE';
setSelectedVCs: 'ACCEPT_REQUEST' | 'VERIFY_AND_ACCEPT_REQUEST';
setSendVPShareError: 'error.platform.OpenID4VP.sendingVP:invocation[0]';
@@ -154,7 +146,7 @@ export interface Typegen0 {
shareDeclineStatus: 'CONFIRM';
storeShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT';
updateFaceCaptureBannerStatus: 'FACE_VALID';
updateShowFaceAuthConsent: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]';
updateShowFaceAuthConsent: 'STORE_RESPONSE';
};
eventsCausingDelays: {
SHARING_TIMEOUT: 'CONFIRM' | 'FACE_VALID' | 'RETRY';
@@ -164,7 +156,6 @@ export interface Typegen0 {
| 'FACE_VALID'
| 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]';
isAnyVCHasImage: 'CHECK_FOR_IMAGE';
isClientValidationRequred: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]';
isFaceVerificationRetryAttempt: 'FACE_INVALID';
isSelectedVCMatchingRequest: 'CHECK_SELECTED_VC';
isShareWithSelfie:
@@ -179,22 +170,18 @@ export interface Typegen0 {
showFaceAuthConsentScreen: 'CONFIRM';
};
eventsCausingServices: {
fetchTrustedVerifiers: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]';
fetchTrustedVerifiers: 'STORE_RESPONSE';
getAuthenticationResponse: 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]';
getKeyPair:
| 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]'
| 'done.invoke.OpenID4VP.getTrustedVerifiersList:invocation[0]';
getKeyPair: 'done.invoke.OpenID4VP.getTrustedVerifiersList:invocation[0]';
getSelectedKey:
| 'FACE_VALID'
| 'done.invoke.OpenID4VP.getKeyPairFromKeystore:invocation[0]';
sendVP: 'CONFIRM' | 'FACE_VALID' | 'RETRY';
shouldValidateClient: 'STORE_RESPONSE';
};
matchesStates:
| 'authenticateVerifier'
| 'checkFaceAuthConsent'
| 'checkIfAnySelectedVCHasImage'
| 'checkIfClientValidationIsRequired'
| 'checkIfMatchingVCsHasSelectedVC'
| 'checkKeyPair'
| 'faceVerificationConsent'

View File

@@ -1,19 +1,19 @@
// Learn more https://docs.expo.io/guides/customizing-metro
const {getDefaultConfig} = require('expo/metro-config');
// extra config is needed to enable `react-native-svg-transformer`
module.exports = (async () => {
const {
resolver: {sourceExts, assetExts},
} = await getDefaultConfig(__dirname);
module.exports = (() => {
const defaultConfig = getDefaultConfig(__dirname);
return {
...defaultConfig,
transformer: {
...defaultConfig.transformer,
babelTransformerPath: require.resolve('react-native-svg-transformer'),
assetPlugins: ['expo-asset/tools/hashAssetFiles'],
},
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
...defaultConfig.resolver,
assetExts: defaultConfig.resolver.assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...defaultConfig.resolver.sourceExts, 'svg'],
},
};
})();

22355
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"prepare": "husky install",
"jetify": "jetify",
"start": "react-native start",
"android:mosip": "react-native run-android --variant=residentappDebug",
"android:mosip": "react-native run-android --mode=residentappDebug",
"ios": "react-native run-ios",
"build:android:mosip": "cd android && ./gradlew :app:assembleResidentappRelease && cd ..",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
@@ -20,7 +20,7 @@
"@digitalbazaar/rsa-verification-key-2018": "digitalbazaar/rsa-verification-key-2018#initial",
"@digitalcredentials/vc": "^1.1.2",
"@expo-google-fonts/inter": "^0.2.3",
"@expo/metro-config": "~0.10.0",
"@expo/metro-config": "~0.18.11",
"@invertase/react-native-apple-authentication": "^2.3.0",
"@iriscan/biometric-sdk-react-native": "0.2.6",
"@noble/ed25519": "^2.1.0",
@@ -28,34 +28,34 @@
"@noble/secp256k1": "2.0.0",
"@react-native-clipboard/clipboard": "^1.10.0",
"@react-native-community/image-editor": "^4.2.0",
"@react-native-community/netinfo": "9.3.7",
"@react-native-community/netinfo": "11.3.1",
"@react-native-google-signin/google-signin": "^10.1.1",
"@react-native-picker/picker": "2.4.8",
"@react-native-picker/picker": "2.7.5",
"@react-navigation/bottom-tabs": "^6.0.7",
"@react-navigation/native": "^6.0.8",
"@react-navigation/native-stack": "^6.1.0",
"@react-navigation/native": "^6.1.6",
"@react-navigation/native-stack": "^6.2.0",
"@robinbobin/react-native-google-drive-api-wrapper": "^1.2.4",
"@xstate/react": "^3.0.1",
"asn1.js": "^5.4.1",
"babel-plugin-transform-remove-console": "^6.9.4",
"base45-web": "^1.0.2",
"base64url-universal": "^1.1.0",
"buffer": "^6.0.3",
"color-diff": "^1.4.0",
"date-fns": "^2.26.0",
"expo": "~49.0.23",
"expo-auth-session": "^5.2.0",
"expo-barcode-scanner": "~12.5.3",
"expo-camera": "~13.4.4",
"expo-constants": "^14.4.2",
"expo-face-detector": "~12.2.0",
"expo-font": "~11.1.1",
"expo-local-authentication": "~13.3.0",
"expo-localization": "~14.1.1",
"expo-modules-autolinking": "~1.5.0",
"expo-updates": "^0.18.17",
"expo-web-browser": "^12.5.0",
"date-fns": "2.28.0",
"expo": "^51.0.0",
"expo-auth-session": "~5.5.2",
"expo-camera": "~15.0.16",
"expo-constants": "~16.0.2",
"expo-face-detector": "~12.7.1",
"expo-font": "~12.0.5",
"expo-local-authentication": "~14.0.1",
"expo-localization": "~15.0.3",
"expo-modules-autolinking": "~1.11.0",
"expo-updates": "~0.25.27",
"expo-web-browser": "~13.0.3",
"hex-rgb": "^5.0.0",
"i18next": "^21.6.16",
"i18next": "^21.9.0",
"iso-639-3": "^3.0.1",
"jsonpath-plus": "^10.0.0",
"jwt-decode": "^3.1.2",
@@ -65,9 +65,9 @@
"postinstall-postinstall": "^2.1.0",
"react": "18.2.0",
"react-i18next": "^11.16.6",
"react-native": "0.71.8",
"react-native": "0.74.5",
"react-native-android-location-services-dialog-box": "^2.8.2",
"react-native-app-auth": "^7.0.0",
"react-native-app-auth": "^7.1.1",
"react-native-app-intro-slider": "^4.0.4",
"react-native-argon2": "^2.0.1",
"react-native-biometrics-changed": "^1.1.8",
@@ -75,30 +75,30 @@
"react-native-cli": "^2.0.1",
"react-native-cloud-storage": "^1.4.0",
"react-native-copilot": "^3.3.2",
"react-native-device-info": "^8.4.8",
"react-native-device-info": "^10.3.0",
"react-native-dotenv": "^3.3.1",
"react-native-draglist": "^3.6.2",
"react-native-elements": "3.4.3",
"react-native-fs": "^2.18.0",
"react-native-gesture-handler": "~2.9.0",
"react-native-get-random-values": "^1.11.0",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.16.1",
"react-native-get-random-values": "~1.11.0",
"react-native-image-colors": "^2.4.0",
"react-native-linear-gradient": "^2.8.0",
"react-native-localize": "^3.0.2",
"react-native-localize": "^3.3.0",
"react-native-location": "^2.5.0",
"react-native-mmkv-storage": "^0.9.1",
"react-native-permissions": "^3.8.0",
"react-native-popable": "^0.4.3",
"react-native-qrcode-svg": "^6.2.0",
"react-native-qrcode-svg": "^6.3.12",
"react-native-restart": "^0.0.24",
"react-native-rsa-native": "^2.0.5",
"react-native-safe-area-context": "4.5.0",
"react-native-screens": "~3.32.0",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"react-native-securerandom": "^1.0.1",
"react-native-shimmer-placeholder": "^2.0.9",
"react-native-spinkit": "^1.5.1",
"react-native-svg": "13.4.0",
"react-native-vector-icons": "^10.0.0",
"react-native-svg": "15.2.0",
"react-native-vector-icons": "^10.1.0",
"react-native-zip-archive": "^6.1.0",
"react-test-renderer": "^18.2.0",
"short-unique-id": "^4.4.4",
@@ -109,45 +109,47 @@
"xstate": "^4.35.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/core": "^7.23.0",
"@babel/plugin-transform-private-methods": "^7.25.9",
"@babel/preset-env": "^7.23.0",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@babel/runtime": "^7.20.0",
"@babel/runtime": "^7.23.0",
"@jest/globals": "^29.7.0",
"@react-native-community/cli": "latest",
"@react-native-community/eslint-config": "^3.2.0",
"@react-native/assets-registry": "^0.72.0",
"@react-native/assets-registry": "^0.76.1",
"@react-native/metro-config": "^0.76.5",
"@react-navigation/devtools": "^6.0.19",
"@testing-library/jest-native": "^5.4.3",
"@testing-library/react-native": "^12.4.3",
"@tsconfig/react-native": "^2.0.2",
"@tsconfig/react-native": "^2.0.3",
"@types/jest": "^29.5.11",
"@types/node-forge": "^1.3.9",
"@types/react": "^18.0.24",
"@typescript-eslint/eslint-plugin": "^5.17.0",
"@typescript-eslint/parser": "^5.17.0",
"babel-jest": "^29.2.1",
"@types/react": "~18.2.45",
"@types/react-native-dotenv": "^0.2.2",
"@typescript-eslint/eslint-plugin": "^5.30.5",
"@typescript-eslint/parser": "^5.30.5",
"babel-jest": "^29.7.0",
"babel-plugin-inline-import": "^3.0.0",
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"eslint": "^8.19.0",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-sonarjs": "^0.13.0",
"glob": "^8.0.1",
"eslint": "^8.53.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-sonarjs": "^0.18.0",
"husky": "^7.0.4",
"jest": "^29.2.1",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jetifier": "^2.0.0",
"lint-staged": "^12.3.7",
"prettier": "^2.6.1",
"react-native-flipper": "^0.212.0",
"react-native-flipper-xstate": "^1.0.5",
"lint-staged": "^13.2.3",
"metro": "^0.81.0",
"metro-config": "^0.81.0",
"metro-react-native-babel-preset": "^0.77.0",
"metro-react-native-babel-transformer": "^0.77.0",
"react-native-share": "^10.2.1",
"react-native-svg-transformer": "^1.1.0",
"react-native-url-polyfill": "^2.0.0",
"rn-mmkv-storage-flipper": "^1.1.1",
"ts-jest": "^29.1.1",
"typescript": "^4.9.5"
"typescript": "~5.3.3"
},
"private": true,
"name": "mosip-resident-app",
@@ -157,8 +159,9 @@
},
"overrides": {
"react": "18.2.0",
"react-native": "0.71.8",
"node-forge": "^1.3.1"
"react-native": "0.74.5",
"node-forge": "^1.3.1",
"@react-native/assets-registry": "^0.76.1"
},
"engines": {
"node": ">=16"

View File

@@ -1,198 +0,0 @@
diff --git a/node_modules/react-native/.DS_Store b/node_modules/react-native/.DS_Store
new file mode 100644
index 0000000..49cbdad
Binary files /dev/null and b/node_modules/react-native/.DS_Store differ
diff --git a/node_modules/react-native/sdks/hermes/hermes-engine.podspec b/node_modules/react-native/sdks/hermes/hermes-engine.podspec
new file mode 100644
index 0000000..b800547
--- /dev/null
+++ b/node_modules/react-native/sdks/hermes/hermes-engine.podspec
@@ -0,0 +1,143 @@
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+require "json"
+require_relative "./hermes-utils.rb"
+
+react_native_path = File.join(__dir__, "..", "..")
+
+# Whether Hermes is built for Release or Debug is determined by the PRODUCTION envvar.
+build_type = ENV['PRODUCTION'] == "1" ? :release : :debug
+
+# package.json
+package = JSON.parse(File.read(File.join(react_native_path, "package.json")))
+version = package['version']
+
+# sdks/.hermesversion
+hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
+isInCI = ENV['REACT_NATIVE_CI'] === 'true'
+
+source = {}
+git = "https://github.com/facebook/hermes.git"
+
+isInMain = version.include?('1000.0.0')
+isNightly = version.start_with?('0.0.0-')
+
+if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH')
+ if !File.exist?(ENV['HERMES_ENGINE_TARBALL_PATH'])
+ abort "[Hermes] HERMES_ENGINE_TARBALL_PATH is set, but points to a non-existing file: \"#{ENV['HERMES_ENGINE_TARBALL_PATH']}\"\nIf you don't want to use tarball, run `unset HERMES_ENGINE_TARBALL_PATH`"
+ end
+end
+
+if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH')
+ Pod::UI.puts "[Hermes] Using pre-built Hermes binaries from local path: #{ENV['HERMES_ENGINE_TARBALL_PATH']}".yellow if Object.const_defined?("Pod::UI")
+ source[:http] = "file://#{ENV['HERMES_ENGINE_TARBALL_PATH']}"
+elsif isInMain
+ Pod::UI.puts '[Hermes] Installing hermes-engine may take slightly longer, building Hermes compiler from source...'.yellow if Object.const_defined?("Pod::UI")
+ source[:git] = git
+ source[:commit] = `git ls-remote https://github.com/facebook/hermes main | cut -f 1`.strip
+elsif isNightly
+ Pod::UI.puts '[Hermes] Nightly version, download pre-built for Hermes'.yellow if Object.const_defined?("Pod::UI")
+ destination_path = download_nightly_hermes(react_native_path, version)
+ # set tarball as hermes engine
+ source[:http] = "file://#{destination_path}"
+elsif File.exist?(hermestag_file) && isInCI
+ Pod::UI.puts '[Hermes] Detected that you are on a React Native release branch, building Hermes from source but fetched from tag...'.yellow if Object.const_defined?("Pod::UI")
+ hermestag = File.read(hermestag_file).strip
+ source[:git] = git
+ source[:tag] = hermestag
+else
+ # Sample url from Maven:
+ # https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.71.0/react-native-artifacts-0.71.0-hermes-ios-debug.tar.gz
+ source[:http] = "https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/#{version}/react-native-artifacts-#{version}-hermes-ios-#{build_type.to_s}.tar.gz"
+end
+
+Pod::Spec.new do |spec|
+ spec.name = "hermes-engine"
+ spec.version = version
+ spec.summary = "Hermes is a small and lightweight JavaScript engine optimized for running React Native."
+ spec.description = "Hermes is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode."
+ spec.homepage = "https://hermesengine.dev"
+ spec.license = package['license']
+ spec.author = "Facebook"
+ spec.source = source
+ spec.platforms = { :osx => "10.13", :ios => "12.4" }
+
+ spec.preserve_paths = '**/*.*'
+ spec.source_files = ''
+
+ spec.xcconfig = {
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
+ "CLANG_CXX_LIBRARY" => "compiler-default"
+ }.merge!(build_type == :debug ? { "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1" } : {})
+
+ if source[:http] then
+
+ spec.subspec 'Pre-built' do |ss|
+ ss.preserve_paths = ["destroot/bin/*"].concat(build_type == :debug ? ["**/*.{h,c,cpp}"] : [])
+ ss.source_files = "destroot/include/**/*.h"
+ ss.exclude_files = ["destroot/include/jsi/jsi/JSIDynamic.{h,cpp}", "destroot/include/jsi/jsi/jsilib-*.{h,cpp}"]
+ ss.header_mappings_dir = "destroot/include"
+ ss.ios.vendored_frameworks = "destroot/Library/Frameworks/universal/hermes.xcframework"
+ ss.osx.vendored_frameworks = "destroot/Library/Frameworks/macosx/hermes.framework"
+ end
+
+ elsif source[:git] then
+
+ spec.subspec 'Hermes' do |ss|
+ ss.source_files = ''
+ ss.public_header_files = 'API/hermes/*.h'
+ ss.header_dir = 'hermes'
+ end
+
+ spec.subspec 'JSI' do |ss|
+ ss.source_files = ''
+ ss.public_header_files = 'API/jsi/jsi/*.h'
+ ss.header_dir = 'jsi'
+ end
+
+ spec.subspec 'Public' do |ss|
+ ss.source_files = ''
+ ss.public_header_files = 'public/hermes/Public/*.h'
+ ss.header_dir = 'hermes/Public'
+ end
+
+ hermesc_path = ""
+
+ if ENV.has_key?('HERMES_OVERRIDE_HERMESC_PATH') && File.exist?(ENV['HERMES_OVERRIDE_HERMESC_PATH']) then
+ hermesc_path = ENV['HERMES_OVERRIDE_HERMESC_PATH']
+ else
+ # Keep hermesc_path synchronized with .gitignore entry.
+ ENV['REACT_NATIVE_PATH'] = react_native_path
+ hermesc_path = "${REACT_NATIVE_PATH}/sdks/hermes-engine/build_host_hermesc"
+ # NOTE: Prepare command is not run if the pod is not downloaded.
+ spec.prepare_command = ". #{react_native_path}/sdks/hermes-engine/utils/build-hermesc-xcode.sh #{hermesc_path}"
+ end
+
+ spec.user_target_xcconfig = {
+ 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/iphoneos" ' +
+ '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/iphonesimulator" ' +
+ '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/macosx" ' +
+ '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/catalyst"',
+ 'OTHER_LDFLAGS' => '-framework "hermes"',
+ 'HERMES_CLI_PATH' => "#{hermesc_path}/bin/hermesc"
+ }
+
+ spec.script_phases = [
+ {
+ :name => 'Build Hermes',
+ :script => <<-EOS
+ . ${PODS_ROOT}/../.xcode.env
+ export CMAKE_BINARY=${CMAKE_BINARY:-#{%x(command -v cmake | tr -d '\n')}}
+ . ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermes-xcode.sh #{version} #{hermesc_path}/ImportHermesc.cmake
+ EOS
+ },
+ {
+ :name => 'Copy Hermes Framework',
+ :script => ". ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/copy-hermes-xcode.sh"
+ }
+ ]
+ end
+end
diff --git a/node_modules/react-native/sdks/hermes/hermes-utils.rb b/node_modules/react-native/sdks/hermes/hermes-utils.rb
new file mode 100644
index 0000000..0842496
--- /dev/null
+++ b/node_modules/react-native/sdks/hermes/hermes-utils.rb
@@ -0,0 +1,26 @@
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+require 'net/http'
+require 'rexml/document'
+
+# This function downloads the nightly prebuilt version of Hermes based on the passed version
+# and save it in the node_module/react_native/sdks/downloads folder
+# It then returns the path to the hermes tarball
+#
+# Parameters
+# - react_native_path: the path to the React Native folder in node modules. It is used as root path to store the Hermes tarball
+# - version: the version of React Native that requires the Hermes tarball
+# Returns: the path to the downloaded Hermes tarball
+def download_nightly_hermes(react_native_path, version)
+ params = "r=snapshots\&g=com.facebook.react\&a=react-native-artifacts\&c=hermes-ios-debug\&e=tar.gz\&v=#{version}-SNAPSHOT"
+ tarball_url = "http://oss.sonatype.org/service/local/artifact/maven/redirect\?#{params}"
+
+ destination_folder = "#{react_native_path}/sdks/downloads"
+ destination_path = "#{destination_folder}/hermes-ios.tar.gz"
+
+ `mkdir -p "#{destination_folder}" && curl "#{tarball_url}" -Lo "#{destination_path}"`
+ return destination_path
+end
diff --git a/node_modules/react-native/third-party-podspecs/boost.podspec b/node_modules/react-native/third-party-podspecs/boost.podspec
index 3d9331c..bbbb738 100644
--- a/node_modules/react-native/third-party-podspecs/boost.podspec
+++ b/node_modules/react-native/third-party-podspecs/boost.podspec
@@ -10,7 +10,7 @@ Pod::Spec.new do |spec|
spec.homepage = 'http://www.boost.org'
spec.summary = 'Boost provides free peer-reviewed portable C++ source libraries.'
spec.authors = 'Rene Rivera'
- spec.source = { :http => 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2',
+ spec.source = { :http => 'https://archives.boost.io/release/1.76.0/source/boost_1_76_0.tar.bz2',
:sha256 => 'f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41' }
# Pinning to the same version as React.podspec.

View File

@@ -5,10 +5,6 @@ module.exports = {
ios: null,
},
},
'react-native-flipper': {
platforms: {
ios: null,
},
},
},
assets: ['./assets/images'],
};

View File

@@ -10,12 +10,11 @@ import {
import {authRoutes, baseRoutes} from '../routes';
import {useAppLayout} from './AppLayoutController';
import {StatusBar} from 'react-native';
import {useFlipper} from '@react-navigation/devtools';
import {GestureHandlerRootView} from "react-native-gesture-handler";
const {Navigator, Screen} = createNativeStackNavigator();
export const AppLayout: React.FC = () => {
const navigationRef = useNavigationContainerRef();
useFlipper(navigationRef);
const controller = useAppLayout();
const options: NativeStackNavigationOptions = {
@@ -26,15 +25,17 @@ export const AppLayout: React.FC = () => {
};
return (
<NavigationContainer ref={navigationRef}>
<StatusBar animated={true} barStyle="dark-content" />
<Navigator initialRouteName={baseRoutes[0].name} screenOptions={options}>
{baseRoutes.map(route => (
<Screen key={route.name} {...route} />
))}
{controller.isAuthorized &&
authRoutes.map(route => <Screen key={route.name} {...route} />)}
</Navigator>
</NavigationContainer>
<GestureHandlerRootView>
<NavigationContainer ref={navigationRef}>
<StatusBar animated={true} barStyle="dark-content" />
<Navigator initialRouteName={baseRoutes[0].name} screenOptions={options}>
{baseRoutes.map(route => (
<Screen key={route.name} {...route} />
))}
{controller.isAuthorized &&
authRoutes.map(route => <Screen key={route.name} {...route} />)}
</Navigator>
</NavigationContainer>
</GestureHandlerRootView>
);
};

View File

@@ -12,7 +12,6 @@ import {
sendStartEvent,
} from '../shared/telemetry/TelemetryUtils';
import {TelemetryConstants} from '../shared/telemetry/TelemetryConstants';
import {Icon} from 'react-native-elements';
import {SvgImage} from '../components/ui/svg';
export const AuthScreen: React.FC<RootRouteProps> = props => {

View File

@@ -1,7 +1,6 @@
import React, {useEffect} from 'react';
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';

BIN
screens/Home/IntroBg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

View File

@@ -10,11 +10,11 @@ import LinearGradient from 'react-native-linear-gradient';
import {SvgImage} from '../../components/ui/svg';
import testIDProps from '../../shared/commonUtil';
import {INTRO_SLIDER_LOGO_MARGIN} from '../../shared/constants';
import { StaticAuthScreen } from '../IntroSliders/biometricIntro';
import { StaticScanScreen } from '../IntroSliders/quickAccessIntro';
import {StaticAuthScreen} from '../IntroSliders/biometricIntro';
import {StaticScanScreen} from '../IntroSliders/quickAccessIntro';
import StaticBackupAndRestoreScreen from '../IntroSliders/backupRestoreIntro';
import { StaticHomeScreen } from '../IntroSliders/trustedDigitalWalletIntro';
import { StaticSendVcScreen } from '../IntroSliders/secureShareIntro';
import {StaticHomeScreen} from '../IntroSliders/trustedDigitalWalletIntro';
import {StaticSendVcScreen} from '../IntroSliders/secureShareIntro';
export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
const slider = useRef<AppIntroSlider>();
@@ -28,31 +28,31 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
key: 'one',
title: t('stepOneTitle'),
text: t('stepOneText'),
component: <StaticAuthScreen />,
component: <StaticAuthScreen />,
},
{
key: 'two',
title: t('stepTwoTitle'),
text: t('stepTwoText'),
component: <StaticSendVcScreen />,
component: <StaticSendVcScreen />,
},
{
key: 'three',
title: t('stepThreeTitle'),
text: t('stepThreeText'),
component: <StaticHomeScreen />,
component: <StaticHomeScreen />,
},
{
key: 'four',
title: t('stepFourTitle'),
text: t('stepFourText'),
component: <StaticScanScreen />,
component: <StaticScanScreen />,
},
{
key: 'five',
title: t('stepFiveTitle'),
text: t('stepFiveText'),
component: <StaticBackupAndRestoreScreen />,
component: <StaticBackupAndRestoreScreen />,
},
];
@@ -60,7 +60,7 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
const renderItem = ({item}) => {
return (
<ImageBackground source={Theme.IntroSliderbackground}>
<ImageBackground source={require('./IntroBg.png')}>
<Centered>
<Row align="space-between" style={Theme.Styles.introSliderHeader}>
<Column style={{marginLeft: INTRO_SLIDER_LOGO_MARGIN}}>
@@ -81,7 +81,9 @@ export const IntroSlidersScreen: React.FC<RootRouteProps> = props => {
/>
)}
</Row>
<View style={{width:300, height:600}}><Centered fill>{item.component}</Centered></View>
<View style={{width: 300, height: 600}}>
<Centered fill>{item.component}</Centered>
</View>
<Column
testID={`introSlide-${item.key}`}
style={Theme.OnboardingOverlayStyles.bottomContainer}

View File

@@ -84,8 +84,8 @@ export const MyVcsTab: React.FC<HomeScreenTabProps> = props => {
const credentialSubject =
vc.verifiableCredential.credentialSubject ||
vc.verifiableCredential.credential.credentialSubject;
if(isStringAndContains(searchText,vc['vcMetadata'].credentialType))
isVcFound=true
if (isStringAndContains(searchText, vc['vcMetadata'].credentialType))
isVcFound = true;
else if (credentialSubject) {
isVcFound = searchNestedCredentialFields(
searchTextLower,

View File

@@ -1,15 +1,15 @@
import React, { useRef } from 'react';
import React, {useRef} from 'react';
import AppIntroSlider from 'react-native-app-intro-slider';
import { SafeAreaView, ScrollView, View } from 'react-native';
import { Icon, Overlay } from 'react-native-elements';
import { Button, Column, Text } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import { useTranslation } from 'react-i18next';
import {SafeAreaView, ScrollView, View} from 'react-native';
import {Icon, Overlay} from 'react-native-elements';
import {Button, Column, Text} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils';
import {useTranslation} from 'react-i18next';
export const OnboardingOverlay: React.FC<OnboardingProps> = (props) => {
export const OnboardingOverlay: React.FC<OnboardingProps> = props => {
const slider = useRef<AppIntroSlider>();
const { t } = useTranslation('OnboardingOverlay');
const {t} = useTranslation('OnboardingOverlay');
const slides = [
{
@@ -38,16 +38,16 @@ export const OnboardingOverlay: React.FC<OnboardingProps> = (props) => {
},
];
const renderItem = ({ item }) => {
const renderItem = ({item}) => {
return (
<View style={Theme.OnboardingOverlayStyles.slide}>
<ScrollView showsVerticalScrollIndicator={true}>
<Text style={Theme.OnboardingOverlayStyles.sliderTitle}>
{item.title}
</Text>
<Text style={Theme.OnboardingOverlayStyles.text}>{item.text}</Text>
{item.footer}
</ScrollView>
<ScrollView showsVerticalScrollIndicator={true}>
<Text style={Theme.OnboardingOverlayStyles.sliderTitle}>
{item.title}
</Text>
<Text style={Theme.OnboardingOverlayStyles.text}>{item.text}</Text>
{item.footer}
</ScrollView>
</View>
);
};
@@ -64,7 +64,7 @@ export const OnboardingOverlay: React.FC<OnboardingProps> = (props) => {
color={Theme.Colors.OnboardingCircleIcon}
size={10}
name="circle"
style={{ opacity: i === activeIndex ? 1 : 0.6, margin: 2 }}
style={{opacity: i === activeIndex ? 1 : 0.6, margin: 2}}
/>
))}
</View>

View File

@@ -10,9 +10,7 @@ import {BindingVcWarningOverlay} from './MyVcs/BindingVcWarningOverlay';
import {VcDetailsContainer} from '../../components/VC/VcDetailsContainer';
import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants';
import {BannerNotificationContainer} from '../../components/BannerNotificationContainer';
import {Icon, ThemeConsumer} from 'react-native-elements';
import {Theme} from '../../components/ui/styleUtils';
import testIDProps from '../../shared/commonUtil';
import {HelpScreen} from '../../components/HelpScreen';
import {Pressable, View} from 'react-native';
import {KebabPopUp} from '../../components/KebabPopUp';

View File

@@ -80,16 +80,24 @@ export const HomeScreenLayout: React.FC<RootRouteProps> = props => {
const [isRTL] = useState(I18nManager.isRTL);
var HomeScreenOptions = {
const HomeScreenOptions = {
headerLeft: () =>
isIOS() || !isRTL
? <View style={Theme.Styles.injiHomeLogo}>{SvgImage.InjiLogo(Theme.Styles.injiLogo)}</View>
: screenOptions,
isIOS() || !isRTL ? (
<View style={Theme.Styles.injiHomeLogo}>
{SvgImage.InjiLogo(Theme.Styles.injiLogo)}
</View>
) : (
screenOptions
),
headerTitle: '',
headerRight: () =>
isIOS() || !isRTL
? screenOptions
: <View style={Theme.Styles.injiHomeLogo}>{SvgImage.InjiLogo(Theme.Styles.injiLogo)}</View>,
isIOS() || !isRTL ? (
screenOptions
) : (
<View style={Theme.Styles.injiHomeLogo}>
{SvgImage.InjiLogo(Theme.Styles.injiLogo)}
</View>
),
};
return (

View File

@@ -4,7 +4,6 @@ import {Theme} from '../../components/ui/styleUtils';
import {useTranslation} from 'react-i18next';
import {useQrLogin} from './QrLoginController';
import {QrLoginRef} from '../../machines/QrLogin/QrLoginMachine';
import {Icon} from 'react-native-elements';
import {Modal} from '../../components/ui/Modal';
import {VcItemContainer} from '../../components/VC/VcItemContainer';
import {

View File

@@ -3,8 +3,8 @@ import {useTranslation} from 'react-i18next';
import {Button, Column, Row, Text} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils';
import {useQrLogin} from './QrLoginController';
import {Image, View} from 'react-native';
import {Icon, ListItem, Switch} from 'react-native-elements';
import {Image} from 'react-native';
import {ListItem, Switch} from 'react-native-elements';
import {Modal} from '../../components/ui/Modal';
import {QrLoginRef} from '../../machines/QrLogin/QrLoginMachine';
import {ScrollView} from 'react-native';
@@ -103,7 +103,10 @@ export const QrConsent: React.FC<QrConsentProps> = props => {
<Switch
value={controller.isShare[claim]}
onValueChange={() =>
controller.SELECT_CONSENT(controller.isShare[claim], claim)
controller.SELECT_CONSENT(
controller.isShare[claim],
claim,
)
}
color={Theme.Colors.Icon}
/>

View File

@@ -66,7 +66,10 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
<View style={Theme.Styles.sendVPHeaderContainer}>
<Text style={Theme.Styles.sendVPHeaderTitle}>{props.children}</Text>
{controller.vpVerifierName && (
<Text numLines={1} ellipsizeMode="tail" style={Theme.Styles.sendVPHeaderSubTitle}>
<Text
numLines={1}
ellipsizeMode="tail"
style={Theme.Styles.sendVPHeaderSubTitle}>
{controller.vpVerifierName}
</Text>
)}

View File

@@ -11,12 +11,11 @@ import {
import {Modal} from '../../components/ui/Modal';
import {Column, Row, Text} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils';
import {Icon, ListItem} from 'react-native-elements';
import {ListItem} from 'react-native-elements';
import getAllConfigurations from '../../shared/api';
import {CopyButton} from '../../components/CopyButton';
import testIDProps from '../../shared/commonUtil';
import {__InjiVersion, __TuvaliVersion} from '../../shared/GlobalVariables';
import i18next from '../../i18n';
import {BannerNotificationContainer} from '../../components/BannerNotificationContainer';
import {SvgImage} from '../../components/ui/svg';
import LinearGradient from 'react-native-linear-gradient';

View File

@@ -1,4 +1,4 @@
import React, {useState} from 'react';
import React from 'react';
import {Pressable} from 'react-native';
import {Icon, ListItem} from 'react-native-elements';
import {Text} from '../../components/ui';

View File

@@ -13,7 +13,6 @@ import BackupAndRestoreScreen from '../backupAndRestore/BackupAndRestoreScreen';
import testIDProps, {getDriveName} from '../../shared/commonUtil';
import {useOverlayVisibleAfterTimeout} from '../../shared/hooks/useOverlayVisibleAfterTimeout';
import {isAndroid, isIOS} from '../../shared/constants';
import LinearGradient from 'react-native-linear-gradient';
export const DataBackupAndRestore: React.FC = ({} = () => {
const controller = useBackupAndRestoreSetup();

View File

@@ -8,7 +8,6 @@ import {useSettingsScreen} from './SettingScreenController';
import {useTranslation} from 'react-i18next';
import {LanguageSelector} from '../../components/LanguageSelector';
import {ScrollView} from 'react-native-gesture-handler';
import {Modal} from '../../components/ui/Modal';
import {CREDENTIAL_REGISTRY_EDIT} from 'react-native-dotenv';
import {AboutInji} from './AboutInji';
import {EditableListItem} from '../../components/EditableListItem';
@@ -74,150 +73,150 @@ export const SettingScreen: React.FC<
};
return (
<React.Fragment>
<Pressable accessible={false} onPress={controller.TOGGLE_SETTINGS}>
{props.triggerComponent}
</Pressable>
<BannerNotificationContainer />
<ScrollView {...testIDProps('settingsScreen')}>
<Column
style={{display: Platform.OS !== 'ios' ? 'flex' : 'none'}}
backgroundColor={Theme.Colors.lightGreyBackgroundColor}>
<Text
style={{paddingTop: 3}}
testID="injiAsVerifierApp"
weight="semibold"
margin="10"
color={Theme.Colors.aboutVersion}>
{t('injiAsVerifierApp')}
</Text>
<Row
align="space-evenly"
backgroundColor={Theme.Colors.whiteBackgroundColor}>
<Pressable
{...testIDProps('receiveCardPressableArea')}
onPress={controller.RECEIVE_CARD}>
<Column align="center" style={Theme.Styles.receiveCardsContainer}>
{SvgImage.ReceiveCard()}
<Text
testID="receiveCard"
margin="6"
style={{paddingTop: 3}}
weight="semibold">
{t('receiveCard')}
</Text>
</Column>
</Pressable>
<React.Fragment>
<Pressable accessible={false} onPress={controller.TOGGLE_SETTINGS}>
{props.triggerComponent}
</Pressable>
<BannerNotificationContainer />
<ScrollView {...testIDProps('settingsScreen')}>
<Column
style={{display: Platform.OS !== 'ios' ? 'flex' : 'none'}}
backgroundColor={Theme.Colors.lightGreyBackgroundColor}>
<Text
style={{paddingTop: 3}}
testID="injiAsVerifierApp"
weight="semibold"
margin="10"
color={Theme.Colors.aboutVersion}>
{t('injiAsVerifierApp')}
</Text>
<Row
align="space-evenly"
backgroundColor={Theme.Colors.whiteBackgroundColor}>
<Pressable
{...testIDProps('receiveCardPressableArea')}
onPress={controller.RECEIVE_CARD}>
<Column align="center" style={Theme.Styles.receiveCardsContainer}>
{SvgImage.ReceiveCard()}
<Text
testID="receiveCard"
margin="6"
style={{paddingTop: 3}}
weight="semibold">
{t('receiveCard')}
</Text>
</Column>
</Pressable>
<ReceivedCards />
</Row>
<ReceivedCards />
</Row>
<Text
weight="semibold"
style={{paddingTop: 3}}
margin="10"
color={Theme.Colors.aboutVersion}>
{t('basicSettings')}
</Text>
</Column>
<Column fill>
<MessageOverlay
isVisible={controller.alertMsg != ''}
onBackdropPress={controller.hideAlert}
title={controller.alertMsg}
/>
<LanguageSetting />
<ListItem topDivider disabled={!controller.canUseBiometrics}>
{SvgImage.fingerprintIcon(24)}
<ListItem.Content>
<ListItem.Title
{...testIDProps('bioUnlock')}
style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('bioUnlock')}
</Text>
</ListItem.Title>
</ListItem.Content>
<Switch
{...testIDProps('biometricToggle')}
value={controller.isBiometricUnlockEnabled}
onValueChange={handleBiometricToggle}
trackColor={{
false: Theme.Colors.switchTrackFalse,
true:
Platform.OS == 'ios'
? Theme.Colors.switchHead
: Theme.Colors.switchTrackTrue,
}}
color={Theme.Colors.switchHead}
<Text
weight="semibold"
style={{paddingTop: 3}}
margin="10"
color={Theme.Colors.aboutVersion}>
{t('basicSettings')}
</Text>
</Column>
<Column fill>
<MessageOverlay
isVisible={controller.alertMsg != ''}
onBackdropPress={controller.hideAlert}
title={controller.alertMsg}
/>
</ListItem>
<AboutInji appId={controller.appId} />
<LanguageSetting />
<DataBackupAndRestore />
<SettingsKeyManagementScreen controller={controller} />
<ListItem topDivider disabled={!controller.canUseBiometrics}>
{SvgImage.fingerprintIcon(24)}
<ListItem.Content>
<ListItem.Title
{...testIDProps('bioUnlock')}
style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('bioUnlock')}
</Text>
</ListItem.Title>
</ListItem.Content>
<Switch
{...testIDProps('biometricToggle')}
value={controller.isBiometricUnlockEnabled}
onValueChange={handleBiometricToggle}
trackColor={{
false: Theme.Colors.switchTrackFalse,
true:
Platform.OS == 'ios'
? Theme.Colors.switchHead
: Theme.Colors.switchTrackTrue,
}}
color={Theme.Colors.switchHead}
/>
</ListItem>
{CREDENTIAL_REGISTRY_EDIT === 'true' && (
<EditableListItem
testID="credentialRegistry"
title={t('credentialRegistry')}
content={controller.credentialRegistry}
items={[
{
label: t('credentialRegistry'),
value: controller.credentialRegistry,
testID: 'credentialRegistry',
},
{
label: t('esignethosturl'),
value: controller.esignetHostUrl,
testID: 'esignetHost',
},
]}
response={controller.credentialRegistryResponse}
onCancel={controller.CANCEL}
onEdit={updateRegistry}
Icon="star"
errorMessage={t('errorMessage')}
progress={controller.isResetInjiProps}
titleColor={Theme.Colors.settingsLabel}
/>
)}
<AboutInji appId={controller.appId} />
<ListItem
topDivider
bottomDivider
onPress={() => controller.INJI_TOUR_GUIDE()}>
{SvgImage.coloredInfo()}
<ListItem.Content>
<ListItem.Title
{...testIDProps('injiTourGuide')}
style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('injiTourGuide')}
</Text>
</ListItem.Title>
</ListItem.Content>
</ListItem>
<DataBackupAndRestore />
<SettingsKeyManagementScreen controller={controller} />
<ListItem onPress={controller.LOGOUT}>
{SvgImage.logOutIcon()}
<ListItem.Content>
<ListItem.Title
{...testIDProps('logout')}
style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('logout')}
</Text>
</ListItem.Title>
</ListItem.Content>
</ListItem>
</Column>
</ScrollView>
</React.Fragment>
{CREDENTIAL_REGISTRY_EDIT === 'true' && (
<EditableListItem
testID="credentialRegistry"
title={t('credentialRegistry')}
content={controller.credentialRegistry}
items={[
{
label: t('credentialRegistry'),
value: controller.credentialRegistry,
testID: 'credentialRegistry',
},
{
label: t('esignethosturl'),
value: controller.esignetHostUrl,
testID: 'esignetHost',
},
]}
response={controller.credentialRegistryResponse}
onCancel={controller.CANCEL}
onEdit={updateRegistry}
Icon="star"
errorMessage={t('errorMessage')}
progress={controller.isResetInjiProps}
titleColor={Theme.Colors.settingsLabel}
/>
)}
<ListItem
topDivider
bottomDivider
onPress={() => controller.INJI_TOUR_GUIDE()}>
{SvgImage.coloredInfo()}
<ListItem.Content>
<ListItem.Title
{...testIDProps('injiTourGuide')}
style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('injiTourGuide')}
</Text>
</ListItem.Title>
</ListItem.Content>
</ListItem>
<ListItem onPress={controller.LOGOUT}>
{SvgImage.logOutIcon()}
<ListItem.Content>
<ListItem.Title
{...testIDProps('logout')}
style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('logout')}
</Text>
</ListItem.Title>
</ListItem.Content>
</ListItem>
</Column>
</ScrollView>
</React.Fragment>
);
};

View File

@@ -1,4 +1,4 @@
import React, {useTransition} from 'react';
import React from 'react';
import {Pressable} from 'react-native';
import {ListItem, Icon} from 'react-native-elements';
import {Row} from '../../components/ui';

View File

@@ -4,7 +4,6 @@ import {useTranslation} from 'react-i18next';
import {SetupPicker} from '../components/ui/SetupPicker';
import {Button, Column, Text} from '../components/ui';
import {Theme} from '../components/ui/styleUtils';
import {Icon} from 'react-native-elements';
import {RootRouteProps} from '../routes';
import {useWelcomeScreen} from './WelcomeScreenController';
import {changeLanguage} from '../components/LanguageSelector';

View File

@@ -1,6 +1,6 @@
import {Dimensions} from 'react-native';
import {RootRouteProps} from '../routes';
import {Image} from 'react-native-elements';
import {Image} from 'react-native';
import React, {useEffect} from 'react';
import {APPLICATION_THEME} from 'react-native-dotenv';
import {Column} from '../components/ui';
@@ -9,8 +9,8 @@ import {useAppLayout} from './AppLayoutController';
export const SplashScreen: React.FC<RootRouteProps> = props => {
const imageResource =
APPLICATION_THEME?.toLowerCase() === 'purple'
? require('../assets/purpleSplashScreen.png')
: require('../assets/SplashScreen.png');
? require('../assets/images/png/purpleSplashScreen.png')
: require('../assets/images/png/SplashScreen.png');
const controller = useAppLayout();
useEffect(() => {
setTimeout(() => {
@@ -21,7 +21,6 @@ export const SplashScreen: React.FC<RootRouteProps> = props => {
}
}, 3000);
}, [controller.isAuthorized || controller.isLanguagesetup]);
return (
<Column
crossAlign="center"

View File

@@ -1,6 +1,5 @@
import React from 'react';
import {useTranslation} from 'react-i18next';
import {Logo} from '../components/Logo';
import {Button, HorizontallyCentered, Column} from '../components/ui';
import {Theme} from '../components/ui/styleUtils';
import {RootRouteProps} from '../routes';

View File

@@ -13,15 +13,13 @@ import {ProfileInfo} from '../../shared/CloudBackupAndRestoreUtils';
import {useBackupScreen} from './BackupController';
import {BannerNotificationContainer} from '../../components/BannerNotificationContainer';
import {useBackupRestoreScreen} from '../Settings/BackupRestoreController';
import {Icon, colors} from 'react-native-elements';
import testIDProps, {
import {
getAccountType,
getDriveName,
} from '../../shared/commonUtil';
import {HelpScreen} from '../../components/HelpScreen';
import {isAndroid, isIOS} from '../../shared/constants';
import LinearGradient from 'react-native-linear-gradient';
import { HelpIcon } from '../../components/ui/HelpIcon';
import {isIOS} from '../../shared/constants';
import {HelpIcon} from '../../components/ui/HelpIcon';
const BackupAndRestoreScreen: React.FC<BackupAndRestoreProps> = props => {
const backupController = useBackupScreen();
@@ -210,10 +208,7 @@ const BackupAndRestoreScreen: React.FC<BackupAndRestoreProps> = props => {
headerElevation={2}
arrowLeft={true}
headerRight={
<HelpScreen
source={'BackUp'}
triggerComponent={HelpIcon()}
/>
<HelpScreen source={'BackUp'} triggerComponent={HelpIcon()} />
}
onDismiss={props.onBackPress}>
<BannerNotificationContainer />
@@ -227,11 +222,11 @@ const BackupAndRestoreScreen: React.FC<BackupAndRestoreProps> = props => {
<LoaderAnimation testID="backupAndRestoreScreen" />
</Column>
) : (
<ScrollView>
{LastBackupSection}
{AccountSection}
{RestoreSection}
</ScrollView>
<ScrollView>
{LastBackupSection}
{AccountSection}
{RestoreSection}
</ScrollView>
)}
</View>
</Modal>

View File

@@ -28,6 +28,11 @@ export enum VCItemContainerFlowType {
VP_SHARE = 'vp share',
}
export enum CameraPosition {
FRONT = 'front',
BACK = 'back',
}
export interface CommunicationDetails {
phoneNumber: string;
emailId: string;

View File

@@ -1,8 +0,0 @@
import mmkvFlipper from 'rn-mmkv-storage-flipper';
import {MMKV} from './storage';
import {inspect} from 'react-native-flipper-xstate';
if (__DEV__) {
mmkvFlipper(MMKV);
inspect();
}

View File

@@ -9,9 +9,9 @@ import {
export function useFont() {
const [hasFontsLoaded] = useFonts({
Inter_400Regular,
Inter_500Medium,
Inter_600SemiBold,
Inter_700Bold,
Inter_500Medium,
});
return hasFontsLoaded;