diff --git a/.env b/.env
index 6ed93c8c..6f09c5b5 100644
--- a/.env
+++ b/.env
@@ -1,3 +1,14 @@
-MIMOTO_HOST=https://api.qa-121.mosip.net/residentmobileapp
+# after making changes to the env file, ensure to start the bundler (or the project) with a --reset-cache
+# eg . npm build android:newlogic --reset-cache
+
+MIMOTO_HOST=https://api.qa-inji.mosip.net
#MIMOTO_HOST=http://mock.mimoto.newlogic.dev
GOOGLE_NEARBY_MESSAGES_API_KEY=
+#Application Theme can be ( orange | purple )
+APPLICATION_THEME=orange
+
+#environment can be changed if it is toggled
+CREDENTIAL_REGISTRY_EDIT=true
+
+#supported languages( en, fil, ar, hi, kn, ta)
+APPLICATION_LANGUAGE=en
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index a9d4c52c..36dfa14e 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,10 +1,10 @@
---
-
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug, triage
-assignees:
+assignees:
+---
**Describe the bug**
A clear and concise description of what the bug is.
@@ -20,18 +20,33 @@ Steps to reproduce the behavior:
**Expected behavior**
A clear and concise description of what you expected to happen.
+**Actual behavior**
+A clear and concise description of what factually occurred.
+
**Screenshots**
-If applicable, add screenshots to help explain your problem.
+If applicable, add screenshots to help explain your problem.
+
+**Add the screenshot of the profile page with commit id**
**Smartphone (please complete the following information):**
-- Device: [e.g. iPhone6]
-- OS: [e.g. iOS8.1]
+- Wallet Device: [e.g. iPhone6]
+ - Phone make/model: [e.g. :Vivo Y73]
+ - OS: [e.g. iOS8.1]
+ - BLE version : [e.g. 4.2]
+
+- Verifier Device: [e.g. iPhone6]
+ - Phone make/model: [e.g. :Vivo Y73]
+ - OS: [e.g. iOS8.1]
+ - BLE version : [e.g. 4.2]
+
- Inji app version: [e.g 0.3.0]
- Mimoto version: [e.g 1.2.x]
- MOSIP Version: [e.g. 1.2.1]
-- Mimoto server: [e.g. https://.....com]
-- MOSIP server: [e.g. https://...mosip.com]
+
+**Where does the issue occur: Wallet/Verifier?**
+
+**Logs of wallet and verifier:**
**Additional context**
Add any other context about the problem here.
diff --git a/.github/workflows/android-beta-build.yml b/.github/workflows/android-beta-build.yml
new file mode 100644
index 00000000..4747fcd6
--- /dev/null
+++ b/.github/workflows/android-beta-build.yml
@@ -0,0 +1,142 @@
+name: Android Beta Build
+
+env:
+ backendServiceDefaultUrl: https://api.sandbox.mosip.net
+
+on:
+ workflow_dispatch:
+ inputs:
+ tag:
+ description: 'Tag to be published'
+ required: true
+ default: 'v1.2.3'
+ type: string
+ body:
+ description: 'Release body message'
+ required: true
+ default: 'Changes in this Release'
+ type: string
+ pre-release:
+ description: 'Pre-release? True/False'
+ required: true
+ default: False
+ type: string
+ backendServiceUrl:
+ description: 'Backend service URL'
+ required: true
+ default: 'https://api.sandbox.mosip.net'
+ type: string
+ theme:
+ description: 'Application Theme'
+ required: true
+ default: 'orange'
+ type: choice
+ options:
+ - orange
+ - purple
+ buildDescription:
+ description: 'What to test'
+ required: true
+ default: 'QA-Triple environment'
+ type: string
+ registry_edit:
+ description: 'Edit Registry'
+ required: true
+ default: 'true'
+ type: choice
+ options:
+ - false
+ - true
+
+jobs:
+ build-android:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3.1.0
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '16.x'
+
+ - name: Create Release
+ id: create_release
+ uses: actions/create-release@v1
+ with:
+ tag_name: ${{ github.event.inputs.tag }}
+ release_name: ${{ github.event.inputs.tag }}
+ body: ${{ github.event.inputs.body }}
+ draft: false
+ prerelease: ${{fromJSON(github.event.inputs.pre-release)}}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Check for git tag
+ run: |
+ cd android/scripts
+ ./git-tag.sh
+
+ - name: Install npm dependencies
+ run: |
+ npm ci
+
+ - name: Create .env.local file
+ run: |
+ echo "${{ secrets.ENV_FILE }}" > .env.local > android/local.properties
+
+ - name: Setup branch and env
+ run: |
+ # Strip git ref prefix from version
+ echo "BRANCH_NAME=$(echo ${{ github.ref }} | sed -e 's,.*/\(.*\),\1,')" >> $GITHUB_ENV
+ echo "GPG_TTY=$(tty)" >> $GITHUB_ENV
+
+ - name: Setup branch and GPG public key
+ run: |
+ # Strip git ref prefix from version
+ echo ${{ env.BRANCH_NAME }}
+ echo ${{ env.GPG_TTY }}
+
+ sudo apt-get --yes install gnupg2
+ gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
+ gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
+
+ - name: Setup Firebase
+ run: |
+ cd android
+ if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];then rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;fi
+ env:
+ FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
+
+ - name: Generate keystore
+ run: |
+ echo "$ANDROID_KEYSTORE_FILE" > release.keystore.b64
+ base64 -d -i release.keystore.b64 > android/app/release.keystore
+ env:
+ ANDROID_KEYSTORE_FILE: ${{ secrets.INJI_ANDROID_RELEASE_KEYSTORE }}
+
+ - name: Export variables for keystore
+ run: |
+ cd android/app
+ export RELEASE_KEYSTORE_ALIAS=androidreleasekey
+ export RELEASE_KEYSTORE_PASSWORD=$RELEASE_KEYSTORE_PASSWORD
+ env:
+ RELEASE_KEYSTORE_PASSWORD: '${{secrets.INJI_ANDROID_RELEASE_STOREPASS}}'
+
+ - name: Create Google Play Config file
+ run : |
+ cd android
+ echo "$INJI_ANDROID_PLAY_STORE_CONFIG_JSON" > play_config.json.b64
+ base64 -d -i play_config.json.b64 > play_config.json
+ env:
+ INJI_ANDROID_PLAY_STORE_CONFIG_JSON: ${{ secrets.INJI_ANDROID_PLAY_STORE_CONFIG_JSON }}
+
+ - name: Run Build
+ run: |
+ cd android/scripts
+ ./beta-build.sh
+ env:
+ MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }}
+ APPLICATION_THEME: ${{ github.event.inputs.theme }}
+ RELEASE_KEYSTORE_ALIAS: androidreleasekey
+ RELEASE_KEYSTORE_PASSWORD: '${{secrets.INJI_ANDROID_RELEASE_STOREPASS}}'
+ SLACK_URL: '${{ secrets.SLACK_WEBHOOK_DEVOPS }}'
+ PLAY_CONSOLE_RELEASE_DESCRIPTION: ${{ github.event.inputs.buildDescription }}
+ CREDENTIAL_REGISTRY_EDIT: ${{ github.event.inputs.registry_edit }}
\ No newline at end of file
diff --git a/.github/workflows/android.yml b/.github/workflows/android-build-verify.yml
similarity index 51%
rename from .github/workflows/android.yml
rename to .github/workflows/android-build-verify.yml
index a1f4db45..6ca8c2b5 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android-build-verify.yml
@@ -1,4 +1,7 @@
-name: ID PASS - MOSIP Resident Application
+name: PR - Android build verification
+
+env:
+ backendServiceDefaultUrl: https://api.sandbox.mosip.net
on:
push:
@@ -7,16 +10,26 @@ on:
- develop
- demobranch
- qa-develop
+ - 0.9
tags:
- '*'
+ pull_request:
+ types: [ opened, synchronize ]
+ branches:
+ - develop
+ - 'release-**'
+ tags:
+ - '*'
jobs:
build-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
-
- # Cache stuff for faster build
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '16.x'
+
- name: Cache local npm repository
uses: actions/cache@v3.0.11
with:
@@ -30,7 +43,7 @@ jobs:
path: |
~/.gradle/caches
~/.gradle/wrapper
-
+
- name: Install npm dependencies
run: |
npm ci
@@ -39,33 +52,63 @@ jobs:
run: |
echo "${{ secrets.ENV_FILE }}" > .env.local > android/local.properties
- - name: Setup branch and env
+ - name: Setup branch and env
run: |
# Strip git ref prefix from version
echo "BRANCH_NAME=$(echo ${{ github.ref }} | sed -e 's,.*/\(.*\),\1,')" >> $GITHUB_ENV
echo "GPG_TTY=$(tty)" >> $GITHUB_ENV
- - name: Setup branch and GPG public key
+
+ - name: Setup branch and GPG public key
run: |
# Strip git ref prefix from version
-
echo ${{ env.BRANCH_NAME }}
-
echo ${{ env.GPG_TTY }}
+
sudo apt-get --yes install gnupg2
gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
- gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
+ gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
- - name: Build App Newlogic Release
+ - name: Setup Firebase
run: |
cd android
if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];then rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;fi
- ./gradlew :app:assembleNewlogicRelease
env:
FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
+
+ - name: Generate keystore
+ run: |
+ keytool \
+ -genkey -v \
+ -storetype PKCS12 \
+ -keyalg RSA \
+ -keysize 2048 \
+ -validity 10000 \
+ -storepass $DEBUG_KEYSTORE_PASSWORD \
+ -keypass $DEBUG_KEYSTORE_PASSWORD \
+ -alias androiddebugkey \
+ -keystore android/app/debug.keystore \
+ -dname "CN=io.mosip.residentapp,OU=,O=,L=,S=,C=US"
+ env:
+ DEBUG_KEYSTORE_PASSWORD: '${{secrets.INJI_ANDROID_DEBUG_STOREPASS}}'
- - name: Upload Artifact
- uses: actions/upload-artifact@v3.1.1
+ - name: Export variables for keystore
+ run: |
+ cd android/app
+ export DEBUG_KEYSTORE_ALIAS=androiddebugkey
+ export DEBUG_KEYSTORE_PASSWORD=$DEBUG_KEYSTORE_PASSWORD
+ env:
+ DEBUG_KEYSTORE_PASSWORD: '${{secrets.INJI_ANDROID_DEBUG_STOREPASS}}'
+
+ - name: Bump version code
+ uses: chkfung/android-version-actions@v1.2.1
with:
- name: output
- path: android/app/build/outputs/apk/newlogic/release/
- retention-days: 1
+ gradlePath: android/app/build.gradle
+ versionCode: ${{github.run_number}}
+
+ - name: Run Build using Fastlane
+ run: |
+ cd android/scripts
+ ./verify-build.sh
+ env:
+ DEBUG_KEYSTORE_ALIAS: androiddebugkey
+ DEBUG_KEYSTORE_PASSWORD: '${{secrets.INJI_ANDROID_DEBUG_STOREPASS}}'
\ No newline at end of file
diff --git a/.github/workflows/android-custom-build.yml b/.github/workflows/android-custom-build.yml
deleted file mode 100644
index 653938b8..00000000
--- a/.github/workflows/android-custom-build.yml
+++ /dev/null
@@ -1,74 +0,0 @@
-name: ID PASS - MOSIP Resident Application Custom build
-
-env:
- backendServiceDefaultUrl: https://api.qa-121.mosip.net/residentmobileapp
-
-on:
- workflow_dispatch:
- inputs:
- backendServiceUrl:
- description: 'Backend service URL'
- required: true
- default: 'https://api.qa-121.mosip.net/residentmobileapp'
- type: string
-
-jobs:
- build-android:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3.1.0
-
- # Cache stuff for faster build
- - name: Cache local npm repository
- uses: actions/cache@v3.0.11
- with:
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- path: ~/.npm
-
- - name: Cache local gradle repository
- uses: actions/cache@v3.0.11
- with:
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
-
- - name: Install npm dependencies
- run: |
- npm install
-
- - name: Create .env.local file
- run: |
- echo "${{ secrets.ENV_FILE }}" > .env.local > android/local.properties
-
- - name: Setup branch and env
- run: |
- # Strip git ref prefix from version
- echo "BRANCH_NAME=$(echo ${{ github.ref }} | sed -e 's,.*/\(.*\),\1,')" >> $GITHUB_ENV
- echo "GPG_TTY=$(tty)" >> $GITHUB_ENV
-
- - name: Setup branch and GPG public key
- run: |
- # Strip git ref prefix from version
-
- echo ${{ env.BRANCH_NAME }}
-
- echo ${{ env.GPG_TTY }}
- sudo apt-get --yes install gnupg2
- gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
- gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
-
- - name: Build App Newlogic Release
- run: |
- cd android
- if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];then rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;fi
- ./gradlew :app:assembleNewlogicRelease
- env:
- MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }}
- FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
- - name: Upload Artifact
- uses: actions/upload-artifact@v3.1.1
- with:
- name: apk-output
- path: android/app/build/outputs/apk/newlogic/release/
- retention-days: 10
diff --git a/.github/workflows/android-internal-build.yml b/.github/workflows/android-internal-build.yml
new file mode 100644
index 00000000..9e0622e8
--- /dev/null
+++ b/.github/workflows/android-internal-build.yml
@@ -0,0 +1,124 @@
+name: Android Internal Build
+
+env:
+ backendServiceDefaultUrl: https://api.sandbox.mosip.net
+
+on:
+ workflow_dispatch:
+ inputs:
+ backendServiceUrl:
+ description: 'Backend service URL'
+ required: true
+ default: 'https://api.sandbox.mosip.net'
+ type: string
+ theme:
+ description: 'Application Theme'
+ required: true
+ default: 'orange'
+ type: choice
+ options:
+ - orange
+ - purple
+ buildDescription:
+ description: 'What to test'
+ required: true
+ default: 'QA-Triple environment'
+ type: string
+ registry_edit:
+ description: 'Edit Registry'
+ required: true
+ default: 'true'
+ type: choice
+ options:
+ - false
+ - true
+
+jobs:
+ build-android:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3.1.0
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '16.x'
+
+ - name: Cache local npm repository
+ uses: actions/cache@v3.0.11
+ with:
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
+ path: ~/.npm
+
+ - name: Cache local gradle repository
+ uses: actions/cache@v3.0.11
+ with:
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
+
+ - name: Install npm dependencies
+ run: |
+ npm ci
+
+ - name: Create .env.local file
+ run: |
+ echo "${{ secrets.ENV_FILE }}" > .env.local > android/local.properties
+
+ - name: Setup branch and env
+ run: |
+ # Strip git ref prefix from version
+ echo "BRANCH_NAME=$(echo ${{ github.ref }} | sed -e 's,.*/\(.*\),\1,')" >> $GITHUB_ENV
+ echo "GPG_TTY=$(tty)" >> $GITHUB_ENV
+
+ - name: Setup branch and GPG public key
+ run: |
+ # Strip git ref prefix from version
+ echo ${{ env.BRANCH_NAME }}
+ echo ${{ env.GPG_TTY }}
+
+ sudo apt-get --yes install gnupg2
+ gpg2 --import ./.github/keys/mosipgpgkey_pub.gpg
+ gpg2 --quiet --batch --passphrase=${{secrets.gpg_secret}} --allow-secret-key-import --import ./.github/keys/mosipgpgkey_sec.gpg
+
+ - name: Setup Firebase
+ run: |
+ cd android
+ if [ ! -z "$FIREBASE_SECRET" ] && [ -f app/google-services.json.gpg ];then rm -f app/google-services.json;gpg2 --quiet --batch --passphrase=$FIREBASE_SECRET --pinentry-mode loopback --decrypt --output app/google-services.json app/mosip-google-services.json.gpg;fi
+ env:
+ FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
+
+ - name: Generate keystore
+ run: |
+ echo "$ANDROID_KEYSTORE_FILE" > release.keystore.b64
+ base64 -d -i release.keystore.b64 > android/app/release.keystore
+ env:
+ ANDROID_KEYSTORE_FILE: ${{ secrets.INJI_ANDROID_RELEASE_KEYSTORE }}
+
+ - name: Export variables for keystore
+ run: |
+ cd android/app
+ export RELEASE_KEYSTORE_ALIAS=androidreleasekey
+ export RELEASE_KEYSTORE_PASSWORD=$RELEASE_KEYSTORE_PASSWORD
+ env:
+ RELEASE_KEYSTORE_PASSWORD: '${{secrets.INJI_ANDROID_RELEASE_STOREPASS}}'
+
+ - name: Create Google Play Config file
+ run : |
+ cd android
+ echo "$INJI_ANDROID_PLAY_STORE_CONFIG_JSON" > play_config.json.b64
+ base64 -d -i play_config.json.b64 > play_config.json
+ env:
+ INJI_ANDROID_PLAY_STORE_CONFIG_JSON: ${{ secrets.INJI_ANDROID_PLAY_STORE_CONFIG_JSON }}
+
+ - name: Run Build
+ run: |
+ cd android/scripts
+ ./internal-build.sh
+ env:
+ MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }}
+ APPLICATION_THEME: ${{ github.event.inputs.theme }}
+ RELEASE_KEYSTORE_ALIAS: androidreleasekey
+ RELEASE_KEYSTORE_PASSWORD: '${{secrets.INJI_ANDROID_RELEASE_STOREPASS}}'
+ SLACK_URL: '${{ secrets.SLACK_WEBHOOK_DEVOPS }}'
+ PLAY_CONSOLE_RELEASE_DESCRIPTION: ${{ github.event.inputs.buildDescription }}
+ CREDENTIAL_REGISTRY_EDIT: ${{ github.event.inputs.registry_edit }}
\ No newline at end of file
diff --git a/.github/workflows/clear_artifacts.yml b/.github/workflows/clear_artifacts.yml
index 0af8038e..d880e16c 100644
--- a/.github/workflows/clear_artifacts.yml
+++ b/.github/workflows/clear_artifacts.yml
@@ -1,4 +1,7 @@
name: 'Delete old artifacts'
+on:
+ workflow_dispatch:
+name: 'Delete old artifacts'
on:
workflow_dispatch:
@@ -8,5 +11,5 @@ jobs:
steps:
- uses: kolpav/purge-artifacts-action@v1
with:
- token: ${{ secrets. access_token }}
+ token: ${{ secrets.ACTION_PAT }}
expire-in: 2days # Setting this to 0 will delete all artifacts
\ No newline at end of file
diff --git a/.github/workflows/ios-build-verify.yml b/.github/workflows/ios-build-verify.yml
new file mode 100644
index 00000000..b61f464c
--- /dev/null
+++ b/.github/workflows/ios-build-verify.yml
@@ -0,0 +1,59 @@
+name: PR - IOS build verification
+
+on:
+ push:
+ branches:
+ - main
+ - develop
+ - demobranch
+ - qa-develop
+ - 0.9
+ tags:
+ - '*'
+ pull_request:
+ types: [ opened, synchronize ]
+ branches:
+ - develop
+ - 'release-**'
+ tags:
+ - '*'
+
+jobs:
+ build_ios:
+ name: Building the IPA
+ runs-on: macos-13
+
+ steps:
+ - uses: actions/checkout@v3.1.0
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '16.x'
+
+ - name: Install npm dependencies
+ run: |
+ npm install
+
+ - name: Install Pod
+ run: |
+ cd ios
+ pod install
+
+ - name: Building the IPA
+ run: |
+ cd ios
+ fastlane build_verify
+ env:
+ APP_STORE_CONNECT_TEAM_ID: '${{ secrets.APP_STORE_CONNECT_TEAM_ID }}'
+ DEVELOPER_APP_ID: '${{ secrets.IOS_INJI_DEVELOPER_APP_ID }}'
+ INJI_IOS_DEVELOPER_APP_IDENTIFIER: '${{ secrets.INJI_IOS_DEVELOPER_APP_IDENTIFIER }}'
+ INJI_IOS_DEVELOPER_PORTAL_TEAM_ID: '${{ secrets.INJI_IOS_DEVELOPER_PORTAL_TEAM_ID }}'
+ INJI_IOS_FASTLANE_APPLE_ID: '${{ secrets.INJI_IOS_FASTLANE_APPLE_ID }}'
+ INJI_IOS_FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: '${{ secrets.INJI_IOS_FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}'
+ GIT_AUTHORIZATION: '${{ secrets.GIT_AUTHORIZATION }}'
+ INJI_IOS_PROVISIONING_PROFILE_SPECIFIER: '${{ secrets.INJI_IOS_PROVISIONING_PROFILE_SPECIFIER }}'
+ INJI_IOS_TEMP_KEYCHAIN_PASSWORD: '${{ secrets.INJI_IOS_TEMP_KEYCHAIN_PASSWORD }}'
+ INJI_IOS_TEMP_KEYCHAIN_USER: '${{ secrets.INJI_IOS_TEMP_KEYCHAIN_USER }}'
+ APPLE_KEY_ID: '${{ secrets.APPLE_KEY_ID }}'
+ APPLE_ISSUER_ID: '${{ secrets.APPLE_ISSUER_ID }}'
+ APPLE_KEY_CONTENT: '${{ secrets.APPLE_KEY_CONTENT }}'
+ MATCH_PASSWORD: '${{ secrets.INJI_IOS_MATCH_PASSWORD }}'
\ No newline at end of file
diff --git a/.github/workflows/ios-build.yml b/.github/workflows/ios-build.yml
new file mode 100644
index 00000000..2a955c5d
--- /dev/null
+++ b/.github/workflows/ios-build.yml
@@ -0,0 +1,88 @@
+name: Inji iOS build
+
+on:
+ workflow_dispatch:
+ inputs:
+ backendServiceUrl:
+ description: 'Backend service URL'
+ required: true
+ default: 'https://api.sandbox.mosip.net'
+ type: string
+ theme:
+ description: 'Application Theme'
+ required: true
+ default: 'orange'
+ type: choice
+ options:
+ - orange
+ - purple
+ registry_edit:
+ description: 'Edit Registry'
+ required: true
+ default: 'true'
+ type: choice
+ options:
+ - false
+ - true
+ internal-testers:
+ description: 'Internal Testers Group'
+ required: true
+ default: 'QA-Triple'
+ type: choice
+ options:
+ - Dev-testing
+ - MEC
+ - QA
+ - MOSIP-Collab
+ - MOSIP-Dev-testing
+ buildDescription:
+ description: 'What to test'
+ required: true
+ default: 'QA-Triple environment build'
+ type: string
+
+jobs:
+ build_ios:
+ name: Deploying to Testflight
+ runs-on: macos-13
+
+ steps:
+ - uses: actions/checkout@v3.1.0
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '16.x'
+
+ - name: Install npm dependencies
+ run: |
+ npm install
+
+ - name: Install Pod
+ run: |
+ cd ios
+ pod install
+
+ - name: Deploy iOS Beta to TestFlight
+ run: |
+ cd ios
+ fastlane beta
+ env:
+ APP_STORE_CONNECT_TEAM_ID: '${{ secrets.APP_STORE_CONNECT_TEAM_ID }}'
+ DEVELOPER_APP_ID: '${{ secrets.IOS_INJI_DEVELOPER_APP_ID }}'
+ INJI_IOS_DEVELOPER_APP_IDENTIFIER: '${{ secrets.INJI_IOS_DEVELOPER_APP_IDENTIFIER }}'
+ INJI_IOS_DEVELOPER_PORTAL_TEAM_ID: '${{ secrets.INJI_IOS_DEVELOPER_PORTAL_TEAM_ID }}'
+ INJI_IOS_FASTLANE_APPLE_ID: '${{ secrets.INJI_IOS_FASTLANE_APPLE_ID }}'
+ INJI_IOS_FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: '${{ secrets.INJI_IOS_FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }}'
+ GIT_AUTHORIZATION: '${{ secrets.GIT_AUTHORIZATION }}'
+ INJI_IOS_PROVISIONING_PROFILE_SPECIFIER: '${{ secrets.INJI_IOS_PROVISIONING_PROFILE_SPECIFIER }}'
+ INJI_IOS_TEMP_KEYCHAIN_PASSWORD: '${{ secrets.INJI_IOS_TEMP_KEYCHAIN_PASSWORD }}'
+ INJI_IOS_TEMP_KEYCHAIN_USER: '${{ secrets.INJI_IOS_TEMP_KEYCHAIN_USER }}'
+ APPLE_KEY_ID: '${{ secrets.APPLE_KEY_ID }}'
+ APPLE_ISSUER_ID: '${{ secrets.APPLE_ISSUER_ID }}'
+ APPLE_KEY_CONTENT: '${{ secrets.APPLE_KEY_CONTENT }}'
+ SLACK_URL: '${{ secrets.SLACK_WEBHOOK_DEVOPS }}'
+ MATCH_PASSWORD: '${{ secrets.INJI_IOS_MATCH_PASSWORD }}'
+ APPLICATION_THEME: ${{ github.event.inputs.theme }}
+ CREDENTIAL_REGISTRY_EDIT: ${{ github.event.inputs.registry_edit }}
+ MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }}
+ TESTFLIGHT_INTERNAL_TESTERS_GROUP: ${{ github.event.inputs.internal-testers }}
+ TESTFLIGHT_BETA_APP_DESCRIPTION: ${{ github.event.inputs.buildDescription }}
diff --git a/.github/workflows/tag.yaml b/.github/workflows/tag.yaml
deleted file mode 100644
index c216c4b2..00000000
--- a/.github/workflows/tag.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-name: Tagging of repos
-
-env:
- tag: v1.2.3
-
-on:
- workflow_dispatch:
- inputs:
- tag:
- description: 'Tag to be published'
- required: true
- default: 'v1.2.3'
- type: string
- body:
- description: 'Release body message'
- required: true
- default: 'Changes in this Release'
- type: string
- pre-release:
- description: 'Pre-release? True/False'
- required: true
- default: False
- type: string
-
-jobs:
- build:
- name: Create Release
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v3.1.0
- - name: Create Release
- id: create_release
- uses: actions/create-release@v1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
- with:
- tag_name: ${{ github.event.inputs.tag }}
- release_name: ${{ github.event.inputs.tag }}
- body: |
- ${{ github.event.inputs.body }}
- draft: false
- prerelease: ${{fromJSON(github.event.inputs.pre-release)}}
diff --git a/.gitignore b/.gitignore
index 9427ae30..dc099a79 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,8 +60,6 @@ yarn-error.log
# BUCK
buck-out/
\.buckd/
-*.keystore
-!debug.keystore
# Bundle artifacts
*.jsbundle
@@ -90,4 +88,9 @@ dist/
.vscode/
temp/
.eslintcache
-.env.local
\ No newline at end of file
+.env.local
+
+.yalc/
+yalc.lock
+
+android/app/debug.keystore
diff --git a/App.tsx b/App.tsx
index 6b94c86e..8f9f5799 100644
--- a/App.tsx
+++ b/App.tsx
@@ -1,20 +1,105 @@
-import React, { useContext } from 'react';
+import React, { useContext, useEffect } from 'react';
import AppLoading from 'expo-app-loading';
import { AppLayout } from './screens/AppLayout';
import { useFont } from './shared/hooks/useFont';
import { GlobalContextProvider } from './components/GlobalContextProvider';
import { GlobalContext } from './shared/GlobalContext';
import { useSelector } from '@xstate/react';
-import { selectIsReady } from './machines/app';
+import { useTranslation } from 'react-i18next';
+import {
+ selectIsDecryptError,
+ selectIsKeyInvalidateError,
+ selectIsReadError,
+ selectIsReady,
+} from './machines/app';
+import { DualMessageOverlay } from './components/DualMessageOverlay';
+import { useApp } from './screens/AppController';
+import { Alert } from 'react-native';
+import { ErrorMessageOverlay } from './components/MessageOverlay';
+import SecureKeystore from 'react-native-secure-keystore';
+import { isCustomSecureKeystore } from './shared/cryptoutil/cryptoUtil';
+import i18n from './i18n';
-import './i18n';
+// kludge: this is a bad practice but has been done temporarily to surface
+// an occurance of a bug with minimal residual code changes, this should
+// be removed once the bug cause is determined & fixed, ref: INJI-222
+const DecryptErrorAlert = (controller, t) => {
+ const heading = t('errors.decryptionFailed');
+ const desc = t('errors.decryptionFailed');
+ const ignoreBtnTxt = t('ignore');
+ Alert.alert(heading, desc, [
+ {
+ text: ignoreBtnTxt,
+ onPress: () => controller.ignoreDecrypt(),
+ style: 'cancel',
+ },
+ ]);
+};
+
+const AppLayoutWrapper: React.FC = () => {
+ const { appService } = useContext(GlobalContext);
+ const isDecryptError = useSelector(appService, selectIsDecryptError);
+ const controller = useApp();
+ const { t } = useTranslation('WelcomeScreen');
+ if (isDecryptError) {
+ DecryptErrorAlert(controller, t);
+ }
+ return ;
+};
+
+const AppLoadingWrapper: React.FC = () => {
+ const { appService } = useContext(GlobalContext);
+ const isReadError = useSelector(appService, selectIsReadError);
+ const isKeyInvalidateError = useSelector(
+ appService,
+ selectIsKeyInvalidateError
+ );
+ const controller = useApp();
+ const { t } = useTranslation('WelcomeScreen');
+ return (
+ <>
+
+
+
+
+ {isReadError ? (
+
+ ) : null}
+ >
+ );
+};
const AppInitialization: React.FC = () => {
const { appService } = useContext(GlobalContext);
- const hasFontsLoaded = useFont();
const isReady = useSelector(appService, selectIsReady);
+ const hasFontsLoaded = useFont();
+ const { t } = useTranslation('common');
- return isReady && hasFontsLoaded ? : ;
+ useEffect(() => {
+ if (isCustomSecureKeystore()) {
+ SecureKeystore.updatePopup(
+ t('biometricPopup.title'),
+ t('biometricPopup.description')
+ );
+ }
+ }, [i18n.language]);
+
+ return isReady && hasFontsLoaded ? (
+
+ ) : (
+
+ );
};
export default function App() {
diff --git a/AppMetaData.md b/AppMetaData.md
new file mode 100644
index 00000000..63a9751a
--- /dev/null
+++ b/AppMetaData.md
@@ -0,0 +1 @@
+Inji is a mobile app that can be used as a digital wallet to store credentials. It also allows verification of identity in both offline and online modes, at any place and time.
diff --git a/README.md b/README.md
index 6593015a..ef19c1bb 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ Be sure to have the following build tools installed before proceeding:
## Generate keystore for APK signing
```shell
+ # Generate and use Debug keystore for development and testing purposes
keytool \
-genkey -v \
-storetype PKCS12 \
@@ -23,6 +24,21 @@ keytool \
-validity 10000 \
-storepass 'android' \
-keypass 'android' \
+ -alias androiddebugkey \
+ -keystore android/app/debug.keystore \
+ -dname "CN=io.mosip.residentapp,OU=,O=,L=,S=,C=US"
+```
+
+```shell
+ # Generate and use Release keystore for Publishing to Play store
+ keytool \
+ -genkey -v \
+ -storetype PKCS12 \
+ -keyalg RSA \
+ -keysize 2048 \
+ -validity 10000 \
+ -storepass '' \
+ -keypass '' \
-alias androidreleasekey \
-keystore android/app/release.keystore \
-dname "CN=io.mosip.residentapp,OU=,O=,L=,S=,C=US"
@@ -93,15 +109,19 @@ You need Android SDK CLI to build APK.
# 1. Install dependencies
npm install
-# Setup the environment variable for keystore
-export RELEASE_KEYSTORE=release.keystore
+# 2. Setup the environment variables for the keystore
+
+# Debug keystore
+export DEBUG_KEYSTORE_ALIAS=androiddebugkey
+export DEBUG_KEYSTORE_PASSWORD=android
+
+# Release keystore
export RELEASE_KEYSTORE_ALIAS=androidreleasekey
-export RELEASE_KEYSTORE_PASSWORD=android
+export RELEASE_KEYSTORE_PASSWORD=
+
# https://hostname/residentmobileapp is the Mimoto service url
export BACKEND_SERVICE_URL=https://hostname/residentmobileapp
-# Use DEBUG_KEYSTORE, DEBUG_KEYSTORE_ALIAS, DEBUG_KEYSTORE_PASSWORD for debug build
-
# Use one of following command to build the flavor you need.
# Build for Mosip Philippines test
npm run build:android:ph
@@ -143,6 +163,14 @@ 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)
+## View the complete DB :
+
+1. Connect your phone to the laptop and open Android Studio.
+2. On the bottom right vertical tab you will find a `Device File Explorer` button. Click on it and select you phone.
+3. Navigate to `data -> data -> io.mosip.residentapp ->databases`. You will find a file named `RKStorage` in it. Download it.
+4. Download [DB Browser for SQLite](https://sqlitebrowser.org/dl/) .
+5. Open the file in this application. Click on `Browse Data` button and select `catalystLocalStorage` table. Now you should be able to view the entire DB of Inji.
+
## Credits
Credits listed [here](/Credits.md)
diff --git a/android/.project b/android/.project
index 03a28c13..69649cfb 100644
--- a/android/.project
+++ b/android/.project
@@ -1,6 +1,6 @@
- MOSIP Resident App
+ Inji
Project android created by Buildship.
diff --git a/android/Gemfile b/android/Gemfile
new file mode 100644
index 00000000..cdd3a6b3
--- /dev/null
+++ b/android/Gemfile
@@ -0,0 +1,6 @@
+source "https://rubygems.org"
+
+gem "fastlane"
+
+plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
+eval_gemfile(plugins_path) if File.exist?(plugins_path)
diff --git a/android/Gemfile.lock b/android/Gemfile.lock
new file mode 100644
index 00000000..8e33dcae
--- /dev/null
+++ b/android/Gemfile.lock
@@ -0,0 +1,220 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ CFPropertyList (3.0.6)
+ rexml
+ addressable (2.8.4)
+ public_suffix (>= 2.0.2, < 6.0)
+ artifactory (3.0.15)
+ atomos (0.1.3)
+ aws-eventstream (1.2.0)
+ aws-partitions (1.765.0)
+ aws-sdk-core (3.172.0)
+ aws-eventstream (~> 1, >= 1.0.2)
+ aws-partitions (~> 1, >= 1.651.0)
+ aws-sigv4 (~> 1.5)
+ jmespath (~> 1, >= 1.6.1)
+ aws-sdk-kms (1.64.0)
+ aws-sdk-core (~> 3, >= 3.165.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-s3 (1.122.0)
+ aws-sdk-core (~> 3, >= 3.165.0)
+ aws-sdk-kms (~> 1)
+ aws-sigv4 (~> 1.4)
+ aws-sigv4 (1.5.2)
+ aws-eventstream (~> 1, >= 1.0.2)
+ babosa (1.0.4)
+ claide (1.1.0)
+ colored (1.2)
+ colored2 (3.1.2)
+ commander (4.6.0)
+ highline (~> 2.0.0)
+ declarative (0.0.20)
+ digest-crc (0.6.4)
+ rake (>= 12.0.0, < 14.0.0)
+ domain_name (0.5.20190701)
+ unf (>= 0.0.5, < 1.0.0)
+ dotenv (2.8.1)
+ emoji_regex (3.2.3)
+ excon (0.99.0)
+ faraday (1.10.3)
+ faraday-em_http (~> 1.0)
+ faraday-em_synchrony (~> 1.0)
+ faraday-excon (~> 1.1)
+ faraday-httpclient (~> 1.0)
+ faraday-multipart (~> 1.0)
+ faraday-net_http (~> 1.0)
+ faraday-net_http_persistent (~> 1.0)
+ faraday-patron (~> 1.0)
+ faraday-rack (~> 1.0)
+ faraday-retry (~> 1.0)
+ ruby2_keywords (>= 0.0.4)
+ faraday-cookie_jar (0.0.7)
+ faraday (>= 0.8.0)
+ http-cookie (~> 1.0.0)
+ faraday-em_http (1.0.0)
+ faraday-em_synchrony (1.0.0)
+ faraday-excon (1.1.0)
+ faraday-httpclient (1.0.1)
+ faraday-multipart (1.0.4)
+ multipart-post (~> 2)
+ faraday-net_http (1.0.1)
+ faraday-net_http_persistent (1.2.0)
+ faraday-patron (1.0.0)
+ faraday-rack (1.0.0)
+ faraday-retry (1.0.3)
+ faraday_middleware (1.2.0)
+ faraday (~> 1.0)
+ fastimage (2.2.6)
+ fastlane (2.212.2)
+ CFPropertyList (>= 2.3, < 4.0.0)
+ addressable (>= 2.8, < 3.0.0)
+ artifactory (~> 3.0)
+ aws-sdk-s3 (~> 1.0)
+ babosa (>= 1.0.3, < 2.0.0)
+ bundler (>= 1.12.0, < 3.0.0)
+ colored
+ commander (~> 4.6)
+ dotenv (>= 2.1.1, < 3.0.0)
+ emoji_regex (>= 0.1, < 4.0)
+ excon (>= 0.71.0, < 1.0.0)
+ faraday (~> 1.0)
+ faraday-cookie_jar (~> 0.0.6)
+ faraday_middleware (~> 1.0)
+ fastimage (>= 2.1.0, < 3.0.0)
+ gh_inspector (>= 1.1.2, < 2.0.0)
+ google-apis-androidpublisher_v3 (~> 0.3)
+ google-apis-playcustomapp_v1 (~> 0.1)
+ google-cloud-storage (~> 1.31)
+ highline (~> 2.0)
+ json (< 3.0.0)
+ jwt (>= 2.1.0, < 3)
+ mini_magick (>= 4.9.4, < 5.0.0)
+ multipart-post (~> 2.0.0)
+ naturally (~> 2.2)
+ optparse (~> 0.1.1)
+ plist (>= 3.1.0, < 4.0.0)
+ rubyzip (>= 2.0.0, < 3.0.0)
+ security (= 0.1.3)
+ simctl (~> 1.6.3)
+ terminal-notifier (>= 2.0.0, < 3.0.0)
+ terminal-table (>= 1.4.5, < 2.0.0)
+ tty-screen (>= 0.6.3, < 1.0.0)
+ tty-spinner (>= 0.8.0, < 1.0.0)
+ word_wrap (~> 1.0.0)
+ xcodeproj (>= 1.13.0, < 2.0.0)
+ xcpretty (~> 0.3.0)
+ xcpretty-travis-formatter (>= 0.0.3)
+ fastlane-plugin-increment_version_code (0.4.3)
+ gh_inspector (1.1.3)
+ google-apis-androidpublisher_v3 (0.42.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-core (0.11.0)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (>= 0.16.2, < 2.a)
+ httpclient (>= 2.8.1, < 3.a)
+ mini_mime (~> 1.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.a)
+ rexml
+ webrick
+ google-apis-iamcredentials_v1 (0.17.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-playcustomapp_v1 (0.13.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-storage_v1 (0.19.0)
+ google-apis-core (>= 0.9.0, < 2.a)
+ google-cloud-core (1.6.0)
+ google-cloud-env (~> 1.0)
+ google-cloud-errors (~> 1.0)
+ google-cloud-env (1.6.0)
+ faraday (>= 0.17.3, < 3.0)
+ google-cloud-errors (1.3.1)
+ google-cloud-storage (1.44.0)
+ addressable (~> 2.8)
+ digest-crc (~> 0.4)
+ google-apis-iamcredentials_v1 (~> 0.1)
+ google-apis-storage_v1 (~> 0.19.0)
+ google-cloud-core (~> 1.6)
+ googleauth (>= 0.16.2, < 2.a)
+ mini_mime (~> 1.0)
+ googleauth (1.5.2)
+ faraday (>= 0.17.3, < 3.a)
+ jwt (>= 1.4, < 3.0)
+ memoist (~> 0.16)
+ multi_json (~> 1.11)
+ os (>= 0.9, < 2.0)
+ signet (>= 0.16, < 2.a)
+ highline (2.0.3)
+ http-cookie (1.0.5)
+ domain_name (~> 0.5)
+ httpclient (2.8.3)
+ jmespath (1.6.2)
+ json (2.6.3)
+ jwt (2.7.0)
+ memoist (0.16.2)
+ mini_magick (4.12.0)
+ mini_mime (1.1.2)
+ multi_json (1.15.0)
+ multipart-post (2.0.0)
+ nanaimo (0.3.0)
+ naturally (2.2.1)
+ optparse (0.1.1)
+ os (1.1.4)
+ plist (3.7.0)
+ public_suffix (5.0.1)
+ rake (13.0.6)
+ representable (3.2.0)
+ declarative (< 0.1.0)
+ trailblazer-option (>= 0.1.1, < 0.2.0)
+ uber (< 0.2.0)
+ retriable (3.1.2)
+ rexml (3.2.5)
+ rouge (2.0.7)
+ ruby2_keywords (0.0.5)
+ rubyzip (2.3.2)
+ security (0.1.3)
+ signet (0.17.0)
+ addressable (~> 2.8)
+ faraday (>= 0.17.5, < 3.a)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
+ simctl (1.6.10)
+ CFPropertyList
+ naturally
+ terminal-notifier (2.0.0)
+ terminal-table (1.8.0)
+ unicode-display_width (~> 1.1, >= 1.1.1)
+ trailblazer-option (0.1.2)
+ tty-cursor (0.7.1)
+ tty-screen (0.8.1)
+ tty-spinner (0.9.3)
+ tty-cursor (~> 0.7)
+ uber (0.1.0)
+ unf (0.1.4)
+ unf_ext
+ unf_ext (0.0.8.2)
+ unicode-display_width (1.8.0)
+ webrick (1.8.1)
+ word_wrap (1.0.0)
+ xcodeproj (1.22.0)
+ CFPropertyList (>= 2.3.3, < 4.0)
+ atomos (~> 0.1.3)
+ claide (>= 1.0.2, < 2.0)
+ colored2 (~> 3.1)
+ nanaimo (~> 0.3.0)
+ rexml (~> 3.2.4)
+ xcpretty (0.3.0)
+ rouge (~> 2.0.7)
+ xcpretty-travis-formatter (1.0.1)
+ xcpretty (~> 0.2, >= 0.0.7)
+
+PLATFORMS
+ arm64-darwin-21
+
+DEPENDENCIES
+ fastlane
+ fastlane-plugin-increment_version_code
+
+BUNDLED WITH
+ 2.4.10
diff --git a/android/app/build.gradle b/android/app/build.gradle
index cbebac64..d689d91a 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,4 +1,4 @@
-plugins {
+plugins {
id 'com.gladed.androidgitversion' version '0.4.14'
}
@@ -132,7 +132,9 @@ def jscFlavor = 'org.webkit:android-jsc:+'
def enableHermes = project.ext.react.get("enableHermes", false);
androidGitVersion {
- baseCode 1
+ baseCode 0
+ codeFormat 'MXXNXXPXX'
+ format '% tag %%commit_%%branch%'
}
android {
@@ -142,7 +144,7 @@ android {
APP_NAME_RELEASE = "@string/app_name"
APP_NAME_PH = "@string/app_name_ph"
APP_NAME_MOSIP = "@string/app_name_mosip"
- APP_NAME_NEWLOGIC = "@string/app_name_newlogic"
+ APP_NAME_BETA = "@string/app_name_beta"
}
compileOptions {
@@ -154,11 +156,8 @@ android {
applicationId 'io.mosip.residentapp'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- // Update versionName and/or versionCode via git tag
- // More info here:
- // https://github.com/gladed/gradle-android-git-version#3-use-a-git-tag-to-specify-your-version-number-see-semantic-versioning
versionName androidGitVersion.name()
- versionCode androidGitVersion.code()
+ versionCode 1
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
@@ -178,9 +177,9 @@ android {
}
signingConfigs {
release {
- def keystore = System.getenv("RELEASE_KEYSTORE") ?: "debug.keystore"
- def keystoreAlias = System.getenv("RELEASE_KEYSTORE_ALIAS") ?: "androiddebugkey"
- def keystorePass = System.getenv("RELEASE_KEYSTORE_PASSWORD") ?: "android"
+ def keystore = file('release.keystore')
+ def keystoreAlias = System.getenv("RELEASE_KEYSTORE_ALIAS")
+ def keystorePass = System.getenv("RELEASE_KEYSTORE_PASSWORD")
storeFile file("$keystore")
storePassword "$keystorePass"
keyAlias "$keystoreAlias"
@@ -189,9 +188,9 @@ android {
v1SigningEnabled false
}
debug {
- def keystore = System.getenv("DEBUG_KEYSTORE") ?: "debug.keystore"
- def keystoreAlias = System.getenv("DEBUG_KEYSTORE_ALIAS") ?: "androiddebugkey"
- def keystorePass = System.getenv("DEBUG_KEYSTORE_PASSWORD") ?: "android"
+ def keystore = file('debug.keystore')
+ def keystoreAlias = System.getenv("DEBUG_KEYSTORE_ALIAS")
+ def keystorePass = System.getenv("DEBUG_KEYSTORE_PASSWORD")
storeFile file("$keystore")
storePassword "$keystorePass"
keyAlias "$keystoreAlias"
@@ -205,6 +204,10 @@ android {
signingConfig signingConfigs.debug
}
release {
+ lintOptions {
+ checkReleaseBuilds false
+ abortOnError false
+ }
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.release
@@ -217,16 +220,16 @@ android {
productFlavors {
mosip {
- versionName defaultConfig.versionName + "-mosip"
+ versionName defaultConfig.versionName
manifestPlaceholders = [
APP_NAME: APP_NAME_MOSIP
]
dimension "inji"
}
- newlogic {
- versionName defaultConfig.versionName + "-newlogic"
+ beta {
+ versionName defaultConfig.versionName
manifestPlaceholders = [
- APP_NAME: APP_NAME_NEWLOGIC
+ APP_NAME: APP_NAME_BETA
]
dimension "inji"
}
@@ -252,6 +255,7 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"// From node_modules
+ implementation 'com.facebook.soloader:soloader:0.10.1+'
def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
@@ -320,4 +324,4 @@ try {
}
} catch(Exception e) {
logger.warn("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
-}
+}
\ No newline at end of file
diff --git a/android/app/debug.keystore b/android/app/debug.keystore
deleted file mode 100644
index 364e105e..00000000
Binary files a/android/app/debug.keystore and /dev/null differ
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 50a047e6..a1bdc91d 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -2,6 +2,15 @@
xmlns:tools="http://schemas.android.com/tools">
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 775353ea..047aeb58 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,10 +1,15 @@
-
-
+
+
+
+
+
+
@@ -31,7 +36,8 @@
-
+
+
@@ -45,4 +51,4 @@
-
\ No newline at end of file
+
diff --git a/android/app/src/main/java/io/mosip/residentapp/MainActivity.java b/android/app/src/main/java/io/mosip/residentapp/MainActivity.java
index ef1e17f8..9add08ff 100644
--- a/android/app/src/main/java/io/mosip/residentapp/MainActivity.java
+++ b/android/app/src/main/java/io/mosip/residentapp/MainActivity.java
@@ -29,9 +29,7 @@ public class MainActivity extends ReactActivity {
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.CHANGE_WIFI_STATE,
- Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
- Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.CHANGE_WIFI_MULTICAST_STATE
};
private static final int REQUEST_CODE_REQUIRED_PERMISSIONS = 1;
diff --git a/android/app/src/main/res/drawable-hdpi/splashscreen_image.png b/android/app/src/main/res/drawable-hdpi/splashscreen_image.png
index 7855a1f2..74f09d47 100644
Binary files a/android/app/src/main/res/drawable-hdpi/splashscreen_image.png and b/android/app/src/main/res/drawable-hdpi/splashscreen_image.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/splashscreen_image.png b/android/app/src/main/res/drawable-mdpi/splashscreen_image.png
index 7855a1f2..b3c779cd 100644
Binary files a/android/app/src/main/res/drawable-mdpi/splashscreen_image.png and b/android/app/src/main/res/drawable-mdpi/splashscreen_image.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png
index 7855a1f2..f0bc985d 100644
Binary files a/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png and b/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png
index 7855a1f2..8b9628b1 100644
Binary files a/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png and b/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png
index 7855a1f2..11c27057 100644
Binary files a/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png and b/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png differ
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
index 85f04e2e..a2e76939 100644
--- a/android/app/src/main/res/values/colors.xml
+++ b/android/app/src/main/res/values/colors.xml
@@ -1,6 +1,6 @@
- #ffffff
+ #FFFFFF
#FFFFFF
#023c69
#ffffff
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 4bf71150..ff10a980 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -1,9 +1,9 @@
- MOSIP Resident App
+ Inji
MOSIP Resident App - Mosip/Inji
MOSIP Resident App - Newlogic
MOSIP Resident App - PH
- contain
+ cover
false
\ No newline at end of file
diff --git a/android/build.gradle b/android/build.gradle
index 902d3dbb..423b7179 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -4,8 +4,8 @@ buildscript {
ext {
buildToolsVersion = "29.0.3"
minSdkVersion = 23
- compileSdkVersion = 30
- targetSdkVersion = 30
+ compileSdkVersion = 31
+ targetSdkVersion = 31
}
repositories {
google()
@@ -34,6 +34,11 @@ allprojects {
// Android JSC is installed from npm
url(new File(["node", "--print", "require.resolve('jsc-android/package.json')"].execute(null, rootDir).text.trim(), "../dist"))
}
+ configurations.all {
+ resolutionStrategy {
+ force "com.facebook.soloader:soloader:0.10.1"
+ }
+ }
google()
gradlePluginPortal()
diff --git a/android/fastlane/Appfile b/android/fastlane/Appfile
new file mode 100644
index 00000000..f1cb5278
--- /dev/null
+++ b/android/fastlane/Appfile
@@ -0,0 +1,2 @@
+json_key_file("play_config.json")
+package_name("io.mosip.residentapp")
diff --git a/android/fastlane/Fastfile b/android/fastlane/Fastfile
new file mode 100644
index 00000000..6b3ebfad
--- /dev/null
+++ b/android/fastlane/Fastfile
@@ -0,0 +1,86 @@
+default_platform(:android)
+
+MIMOTO_HOST = ENV["MIMOTO_HOST"]
+APPLICATION_THEME = ENV["APPLICATION_THEME"]
+RELEASE_KEYSTORE_ALIAS = ENV["RELEASE_KEYSTORE_ALIAS"]
+RELEASE_KEYSTORE_PASSWORD = ENV["RELEASE_KEYSTORE_PASSWORD"]
+PLAY_CONSOLE_RELEASE_DESCRIPTION = ENV["PLAY_CONSOLE_RELEASE_DESCRIPTION"]
+SLACK_URL = ENV["SLACK_URL"]
+CREDENTIAL_REGISTRY_EDIT = ENV["CREDENTIAL_REGISTRY_EDIT"]
+
+desc "Verify Build for Android"
+lane :android_build_verify do
+ gradle(
+ task: "assembleMosipDebug",
+ )
+end
+
+desc "Deploy an Internal testing version to the Google Play"
+lane :android_build_internal do
+ previous_build_number = google_play_track_version_codes(
+ package_name: "io.mosip.residentapp",
+ track: "internal",
+ json_key: "play_config.json",
+ )[0]
+
+ current_build_number = previous_build_number + 1
+
+ increment_version_code(
+ gradle_file_path: "app/build.gradle",
+ version_code: current_build_number
+ )
+
+ git_commit = sh('git rev-parse --short HEAD').strip
+ git_branch = sh('git rev-parse --abbrev-ref HEAD').strip
+
+ versionName = "#{git_commit}-#{git_branch}"
+
+ gradle(task: "clean bundleMosipRelease")
+ upload_to_play_store(
+ track: 'internal',
+ release_status: 'completed',
+ version_name: versionName,
+ )
+
+ slack(
+ message: "Inji - #{versionName} (#{current_build_number}) is uploaded to Play store. Description : #{PLAY_CONSOLE_RELEASE_DESCRIPTION}.",
+ success: true,
+ slack_url: "#{SLACK_URL}",
+ default_payloads: [:git_branch, :last_git_commit]
+ )
+end
+
+desc "Deploy an Beta version to the Google Play"
+lane :android_build_beta do
+
+ git_tag = sh('git describe --abbrev=0 --tags --exact-match HEAD').strip
+
+ def convert_tag_to_code(version)
+ parts = version.split('.')
+ version_code = parts[0].to_i * 1000000 + parts[1].to_i * 1000 + parts[2].to_i
+ return version_code
+ end
+
+ versionCode = convert_tag_to_code(git_tag)
+
+ increment_version_code(
+ gradle_file_path: "app/build.gradle",
+ version_code: versionCode
+ )
+
+ versionName = "Inji #{git_tag}"
+
+ gradle(task: "clean bundleBetaRelease")
+ upload_to_play_store(
+ track: 'alpha',
+ release_status: 'completed',
+ version_name: versionName,
+ )
+
+ slack(
+ message: "Inji [Beta]- #{versionName} is uploaded to Play store. Description : #{PLAY_CONSOLE_RELEASE_DESCRIPTION}.",
+ success: true,
+ slack_url: "#{SLACK_URL}",
+ default_payloads: [:git_branch, :last_git_commit]
+ )
+end
\ No newline at end of file
diff --git a/android/fastlane/Pluginfile b/android/fastlane/Pluginfile
new file mode 100644
index 00000000..412c2ff9
--- /dev/null
+++ b/android/fastlane/Pluginfile
@@ -0,0 +1,5 @@
+# Autogenerated by fastlane
+#
+# Ensure this file is checked in to source control!
+
+gem 'fastlane-plugin-increment_version_code'
diff --git a/android/fastlane/README.md b/android/fastlane/README.md
new file mode 100644
index 00000000..4421f86d
--- /dev/null
+++ b/android/fastlane/README.md
@@ -0,0 +1,45 @@
+## fastlane documentation
+
+# Installation
+
+Make sure you have the latest version of the Xcode command line tools installed:
+
+```sh
+xcode-select --install
+```
+
+For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
+
+# Available Actions
+
+### android_build_verify
+
+```sh
+[bundle exec] fastlane android_build_verify
+```
+
+Verify Build for Android
+
+### android_build_internal
+
+```sh
+[bundle exec] fastlane android_build_internal
+```
+
+Deploy an Internal testing version to the Google Play
+
+### android_build_beta
+
+```sh
+[bundle exec] fastlane android_build_beta
+```
+
+Deploy an Beta version to the Google Play
+
+---
+
+This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
+
+More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
+
+The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
diff --git a/android/gradle.properties b/android/gradle.properties
index 16bffe90..099c1dd0 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -38,4 +38,7 @@ expo.gif.enabled=true
expo.webp.enabled=true
# Enable animated webp support (~3.4 MB increase)
# Disabled by default because iOS doesn't support animated webp
-expo.webp.animated=false
\ No newline at end of file
+expo.webp.animated=false
+
+# If the AsyncStorage_db_size_in_MB is not configured, Default DB_MAX_SIZE is 6MB in Android
+AsyncStorage_db_size_in_MB=30
diff --git a/android/scripts/beta-build.sh b/android/scripts/beta-build.sh
new file mode 100755
index 00000000..48d2f687
--- /dev/null
+++ b/android/scripts/beta-build.sh
@@ -0,0 +1,10 @@
+#As react-native/location npm package is old, We need to run this to map androidX source code
+(cd ../../ && npx jetify)
+
+cd ..
+
+yes | sudo gem install bundler
+
+yes | sudo fastlane install_plugins
+
+bundle exec fastlane android_build_beta
diff --git a/android/scripts/git-tag.sh b/android/scripts/git-tag.sh
new file mode 100755
index 00000000..cd4a5f19
--- /dev/null
+++ b/android/scripts/git-tag.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+TAG=$(git describe --abbrev=0 --tags --exact-match HEAD 2>/dev/null)
+
+if [[ -z "$TAG" ]]; then
+ echo "No tag found for the current commit. Please provide a Tag to proceed with the Build."
+ exit 1
+else
+ echo "Tag for the current commit: $TAG"
+fi
\ No newline at end of file
diff --git a/android/scripts/internal-build.sh b/android/scripts/internal-build.sh
new file mode 100755
index 00000000..cde4e745
--- /dev/null
+++ b/android/scripts/internal-build.sh
@@ -0,0 +1,10 @@
+#As react-native/location npm package is old, We need to run this to map androidX source code
+(cd ../../ && npx jetify)
+
+cd ..
+
+yes | sudo gem install bundler
+
+yes | sudo fastlane install_plugins
+
+bundle exec fastlane android_build_internal
diff --git a/android/scripts/verify-build.sh b/android/scripts/verify-build.sh
new file mode 100755
index 00000000..48fab851
--- /dev/null
+++ b/android/scripts/verify-build.sh
@@ -0,0 +1,10 @@
+#As react-native/location npm package is old, We need to run this to map androidX source code
+(cd ../../ && npx jetify)
+
+cd ..
+
+yes | sudo gem install bundler
+
+yes | sudo fastlane install_plugins
+
+bundle exec fastlane android_build_verify
diff --git a/android/settings.gradle b/android/settings.gradle
index ee5198af..e02da8a7 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,4 +1,4 @@
-rootProject.name = 'MOSIP Resident App'
+rootProject.name = 'Inji'
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
useExpoModules()
diff --git a/app.config.ts b/app.config.ts
index a06abec8..92da0424 100644
--- a/app.config.ts
+++ b/app.config.ts
@@ -1,12 +1,12 @@
export default {
- name: 'MOSIP Resident App',
- slug: 'mosip-resident-app',
+ name: 'Inji',
+ slug: 'inji',
version: '1.0.0',
orientation: 'portrait',
icon: './assets/icon.png',
splash: {
image: './assets/splash.png',
- resizeMode: 'contain',
+ resizeMode: 'cover',
backgroundColor: '#ffffff',
},
updates: {
diff --git a/assets/Secure-Sharing.png b/assets/Secure-Sharing.png
new file mode 100644
index 00000000..f635f8da
Binary files /dev/null and b/assets/Secure-Sharing.png differ
diff --git a/assets/Secure-Sharing2.png b/assets/Secure-Sharing2.png
new file mode 100644
index 00000000..ae2d449d
Binary files /dev/null and b/assets/Secure-Sharing2.png differ
diff --git a/assets/biometric-unlock-icon.png b/assets/biometric-unlock-icon.png
new file mode 100644
index 00000000..1a6f1077
Binary files /dev/null and b/assets/biometric-unlock-icon.png differ
diff --git a/assets/camera-flip-icon.png b/assets/camera-flip-icon.png
new file mode 100644
index 00000000..de7a69df
Binary files /dev/null and b/assets/camera-flip-icon.png differ
diff --git a/assets/digital-identity-icon.png b/assets/digital-identity-icon.png
new file mode 100644
index 00000000..5a678a4d
Binary files /dev/null and b/assets/digital-identity-icon.png differ
diff --git a/assets/features-walkaround-icon.png b/assets/features-walkaround-icon.png
new file mode 100644
index 00000000..b6a36310
Binary files /dev/null and b/assets/features-walkaround-icon.png differ
diff --git a/assets/help-icon.png b/assets/help-icon.png
new file mode 100644
index 00000000..3346d8fc
Binary files /dev/null and b/assets/help-icon.png differ
diff --git a/assets/icon.png b/assets/icon.png
index 48c75eb7..ce339f7d 100644
Binary files a/assets/icon.png and b/assets/icon.png differ
diff --git a/assets/inji-home-logo.png b/assets/inji-home-logo.png
new file mode 100644
index 00000000..f8c59595
Binary files /dev/null and b/assets/inji-home-logo.png differ
diff --git a/assets/inji-logo-white.png b/assets/inji-logo-white.png
new file mode 100644
index 00000000..85505a13
Binary files /dev/null and b/assets/inji-logo-white.png differ
diff --git a/assets/inji_small_logo.png b/assets/inji_small_logo.png
new file mode 100644
index 00000000..f7009186
Binary files /dev/null and b/assets/inji_small_logo.png differ
diff --git a/assets/intro-scanner.png b/assets/intro-scanner.png
new file mode 100644
index 00000000..fd8876e3
Binary files /dev/null and b/assets/intro-scanner.png differ
diff --git a/assets/intro-wallet-binding.png b/assets/intro-wallet-binding.png
new file mode 100644
index 00000000..fa59b5de
Binary files /dev/null and b/assets/intro-wallet-binding.png differ
diff --git a/assets/legal-notices-icon.png b/assets/legal-notices-icon.png
new file mode 100644
index 00000000..69884e7c
Binary files /dev/null and b/assets/legal-notices-icon.png differ
diff --git a/assets/lock-icon.png b/assets/lock-icon.png
new file mode 100644
index 00000000..147780f8
Binary files /dev/null and b/assets/lock-icon.png differ
diff --git a/assets/magnifier-zoom.png b/assets/magnifier-zoom.png
new file mode 100644
index 00000000..cbbc2153
Binary files /dev/null and b/assets/magnifier-zoom.png differ
diff --git a/assets/mosip-logo.png b/assets/mosip-logo.png
index 48c75eb7..e065ff5c 100644
Binary files a/assets/mosip-logo.png and b/assets/mosip-logo.png differ
diff --git a/assets/otp-mobile-logo.png b/assets/otp-mobile-logo.png
index 4e6eaa73..8a8a4a52 100644
Binary files a/assets/otp-mobile-logo.png and b/assets/otp-mobile-logo.png differ
diff --git a/assets/phone_mockup_1.png b/assets/phone_mockup_1.png
new file mode 100644
index 00000000..5e52fdc8
Binary files /dev/null and b/assets/phone_mockup_1.png differ
diff --git a/assets/progressing-logo.png b/assets/progressing-logo.png
new file mode 100644
index 00000000..dc8d0b74
Binary files /dev/null and b/assets/progressing-logo.png differ
diff --git a/assets/receive-card-icon.png b/assets/receive-card-icon.png
new file mode 100644
index 00000000..b0db01a0
Binary files /dev/null and b/assets/receive-card-icon.png differ
diff --git a/assets/received-cards-icon.png b/assets/received-cards-icon.png
new file mode 100644
index 00000000..52afc034
Binary files /dev/null and b/assets/received-cards-icon.png differ
diff --git a/assets/splash.png b/assets/splash.png
index 48c75eb7..df0075df 100644
Binary files a/assets/splash.png and b/assets/splash.png differ
diff --git a/components/ActivityLogText.strings.json b/components/ActivityLogText.strings.json
index 22e5d29e..13c6d906 100644
--- a/components/ActivityLogText.strings.json
+++ b/components/ActivityLogText.strings.json
@@ -10,5 +10,8 @@
"VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "received. Presence verification failed",
"PRESENCE_VERIFIED_AND_VC_SHARED": "verified and shared",
"PRESENCE_VERIFICATION_FAILED": "verification failed",
- "QRLOGIN_SUCCESFULL": "QRLogin sucessfull"
+ "QRLOGIN_SUCCESFULL": "QRLogin successful",
+ "WALLET_BINDING_SUCCESSFULL": "Activation successful",
+ "WALLET_BINDING_FAILURE": "Activation failed",
+ "VC_REMOVED":"Removed from wallet"
}
\ No newline at end of file
diff --git a/components/ActivityLogText.tsx b/components/ActivityLogText.tsx
index 524cad8f..937873c8 100644
--- a/components/ActivityLogText.tsx
+++ b/components/ActivityLogText.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { formatDistanceToNow } from 'date-fns';
import { useTranslation } from 'react-i18next';
-import * as DateFnsLocale from '../lib/date-fns/locale';
+import * as DateFnsLocale from 'date-fns/locale';
import { ActivityLog } from '../machines/activityLog';
import { TextItem } from './ui/TextItem';
@@ -14,6 +14,7 @@ export const ActivityLogText: React.FC<{ activity: ActivityLog }> = (props) => {
);
};
@@ -26,6 +27,6 @@ function getActionLabel(activity: ActivityLog, language: string) {
locale: DateFnsLocale[language],
}),
]
- .filter((label) => label.trim() !== '')
+ .filter((label) => label?.trim() !== '')
.join(' · ');
}
diff --git a/components/CopyButton.tsx b/components/CopyButton.tsx
new file mode 100644
index 00000000..1d4f97a9
--- /dev/null
+++ b/components/CopyButton.tsx
@@ -0,0 +1,35 @@
+import React, { useState } from 'react';
+import { Pressable } from 'react-native';
+import { Theme } from './ui/styleUtils';
+import Clipboard from '@react-native-clipboard/clipboard';
+import { Icon } from 'react-native-elements';
+import { Text } from './ui';
+import { useTranslation } from 'react-i18next';
+
+export const CopyButton: React.FC = ({ content }) => {
+ const { t } = useTranslation('common');
+ const [buttonText, setButtonText] = useState(t('clipboard.copy'));
+
+ return (
+ {
+ setButtonText(t('clipboard.copied'));
+ setTimeout(() => setButtonText(t('clipboard.copy')), 3000);
+ Clipboard.setString(content);
+ }}>
+
+ {buttonText}
+
+ );
+};
+
+interface CopyButtonProps {
+ content: string;
+}
diff --git a/components/DeviceInfoList.tsx b/components/DeviceInfoList.tsx
index 2ea52905..954dd4ec 100644
--- a/components/DeviceInfoList.tsx
+++ b/components/DeviceInfoList.tsx
@@ -10,15 +10,15 @@ export const DeviceInfoList: React.FC = (props) => {
);
};
interface DeviceInfoProps {
- of: 'sender' | 'receiver';
deviceInfo: DeviceInfo;
+ of?: string;
}
export interface DeviceInfo {
diff --git a/components/DualMessageOverlay.tsx b/components/DualMessageOverlay.tsx
new file mode 100644
index 00000000..645df54c
--- /dev/null
+++ b/components/DualMessageOverlay.tsx
@@ -0,0 +1,106 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { Dimensions, View } from 'react-native';
+import { Overlay } from 'react-native-elements';
+import { Column, Row, Text } from './ui';
+import { Button } from './ui/Button';
+import { Theme } from './ui/styleUtils';
+
+/**
+ * DualMessageOverlay is like MessageOverlay but with two buttons
+ *
+ * NOTE: This has been added for surfacing bugs and needs to be refactored
+ * before use.
+ */
+export const DualMessageOverlay: React.FC = (
+ props
+) => {
+ const { t } = useTranslation('common');
+ return (
+
+
+
+ {props.title && (
+
+ {props.title}
+
+ )}
+ {props.message && (
+
+ {props.message}
+
+ )}
+ {props.hint && (
+
+ {props.hint}
+
+ )}
+ {props.children}
+
+
+
+ {!props.children && props.onTryAgain ? (
+
+ ) : null}
+ {!props.children && props.onIgnore ? (
+
+ ) : null}
+
+
+
+
+ );
+};
+
+export interface DualMessageOverlayProps {
+ isVisible: boolean;
+ title?: string;
+ message?: string;
+ progress?: boolean | number;
+ requester?: boolean;
+ hint?: string;
+ onIgnore?: () => void;
+ onBackdropPress?: () => void;
+ onShow?: () => void;
+ onTryAgain?: () => void;
+}
diff --git a/components/EditableListItem.tsx b/components/EditableListItem.tsx
index e50b628a..2d79acf4 100644
--- a/components/EditableListItem.tsx
+++ b/components/EditableListItem.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { Dimensions, I18nManager } from 'react-native';
import { Icon, ListItem, Overlay, Input } from 'react-native-elements';
import { Text, Column, Row, Button } from './ui';
@@ -9,22 +9,36 @@ export const EditableListItem: React.FC = (props) => {
const { t } = useTranslation('common');
const [isEditing, setIsEditing] = useState(false);
const [newValue, setNewValue] = useState(props.value);
+ const [overlayOpened, setOverlayOpened] = useState(true);
+
+ useEffect(() => {
+ if (props.credentialRegistryResponse === 'success') {
+ closePopup();
+ }
+ }, [props.credentialRegistryResponse]);
return (
- setIsEditing(true)}>
+ setIsEditing(true)}>
- {props.label}
+
+ {props.label}
+
+ {props.value}
- {props.value}
+
= (props) => {
autoFocus
value={newValue}
onChangeText={setNewValue}
+ selectionColor={Theme.Colors.Cursor}
inputStyle={{
textAlign: I18nManager.isRTL ? 'right' : 'left',
}}
/>
+ {props.credentialRegistryResponse === 'error' && (
+ {props.errorMessage}
+ )}
+ {props.credentialRegistryResponse === 'success' &&
+ overlayOpened &&
+ closePopup()}
-
+
@@ -50,12 +76,20 @@ export const EditableListItem: React.FC = (props) => {
function edit() {
props.onEdit(newValue);
- setIsEditing(false);
+ if (props.credentialRegistryResponse === undefined) {
+ setIsEditing(false);
+ }
}
function dismiss() {
setNewValue(props.value);
setIsEditing(false);
+ props.onCancel();
+ }
+
+ function closePopup() {
+ setIsEditing(false);
+ setOverlayOpened(false);
}
};
@@ -63,5 +97,11 @@ interface EditableListItemProps {
label: string;
value: string;
Icon: string;
+ IconType?: string;
onEdit: (newValue: string) => void;
+ display?: 'none' | 'flex';
+ credentialRegistryResponse: string;
+ onCancel: () => void;
+ progress?: boolean;
+ errorMessage?: string;
}
diff --git a/components/HelpScreen.tsx b/components/HelpScreen.tsx
new file mode 100644
index 00000000..ee71fc7f
--- /dev/null
+++ b/components/HelpScreen.tsx
@@ -0,0 +1,79 @@
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Pressable } from 'react-native';
+import { Modal } from './ui/Modal';
+import { ScrollView } from 'react-native-gesture-handler';
+import { MainRouteProps } from '../routes/main';
+import { Column, Text } from './ui';
+import { Theme } from './ui/styleUtils';
+
+export const HelpScreen: React.FC = (
+ props
+) => {
+ const { t } = useTranslation('HelpScreen');
+
+ const [showHelpPage, setShowHelpPage] = useState(false);
+
+ return (
+
+ {
+ setShowHelpPage(!showHelpPage);
+ }}>
+ {props.triggerComponent}
+
+ {
+ setShowHelpPage(!showHelpPage);
+ }}>
+
+
+
+ {t('whatIsDigitalCredential?')}
+
+ {t('detail-1')}
+
+ {t('whatCanDoWithDigitalCredential?')}
+
+ {t('detail-2')}
+
+ {t('howToAddCard?')}
+
+ {t('detail-3')}
+
+ {t('howToRemoveCardFromWallet?')}
+
+ {t('detail-4')}
+
+ {t('canWeAddMultipleCards?')}
+
+ {t('detail-5')}
+
+ {t('howToShareCard?')}
+
+ {t('detail-6')}
+
+ {t('howToActivateCardForOnlineLogin?')}
+
+ {t('detail-7')}
+
+ {t('howToViewActivity?')}
+
+ {t('detail-8')}
+
+ {t('whatCanDoBiometricsChanged?')}
+
+ {t('detail-9')}
+
+
+
+
+ );
+};
+
+interface HelpScreenProps {
+ triggerComponent: React.ReactElement;
+}
diff --git a/components/KebabPopUp.tsx b/components/KebabPopUp.tsx
new file mode 100644
index 00000000..0c2193f9
--- /dev/null
+++ b/components/KebabPopUp.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import { Icon, ListItem, Overlay } from 'react-native-elements';
+import { Theme } from '../components/ui/styleUtils';
+import { Column, Row, Text } from '../components/ui';
+import { WalletBinding } from '../screens/Home/MyVcs/WalletBinding';
+import { Pressable } from 'react-native';
+import { useKebabPopUp } from './KebabPopUpController';
+import { ActorRefFrom } from 'xstate';
+import { vcItemMachine } from '../machines/vcItem';
+import { useTranslation } from 'react-i18next';
+import { HistoryTab } from '../screens/Home/MyVcs/HistoryTab';
+import { RemoveVcWarningOverlay } from '../screens/Home/MyVcs/RemoveVcWarningOverlay';
+
+export const KebabPopUp: React.FC = (props) => {
+ const controller = useKebabPopUp(props);
+ const { t } = useTranslation('HomeScreenKebabPopUp');
+ return (
+
+
+
+
+ {t('title')}
+
+
+
+
+
+
+
+
+ {props.vcKey.split(':')[4] == 'true'
+ ? t('unPinCard')
+ : t('pinCard')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ controller.REMOVE(props.vcKey)}>
+
+ {t('removeFromWallet')}
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export interface KebabPopUpProps {
+ iconName: string;
+ iconType?: string;
+ vcKey: string;
+ isVisible: boolean;
+ onDismiss: () => void;
+ service: ActorRefFrom;
+}
diff --git a/components/KebabPopUpController.tsx b/components/KebabPopUpController.tsx
new file mode 100644
index 00000000..29241534
--- /dev/null
+++ b/components/KebabPopUpController.tsx
@@ -0,0 +1,80 @@
+import { useSelector } from '@xstate/react';
+import { ActorRefFrom } from 'xstate';
+import {
+ selectKebabPopUpWalletBindingInProgress,
+ selectKebabPopUp,
+ selectKebabPopUpAcceptingBindingOtp,
+ selectKebabPopUpBindingWarning,
+ selectRemoveWalletWarning,
+ selectEmptyWalletBindingId,
+ selectIsPinned,
+ selectOtpError,
+ selectShowWalletBindingError,
+ selectWalletBindingError,
+ VcItemEvents,
+ vcItemMachine,
+ selectShowActivities,
+} from '../machines/vcItem';
+import { selectActivities } from '../machines/activityLog';
+import { GlobalContext } from '../shared/GlobalContext';
+import { useContext } from 'react';
+
+export function useKebabPopUp(props) {
+ const service = props.service as ActorRefFrom;
+ const PIN_CARD = () => service.send(VcItemEvents.PIN_CARD());
+ const KEBAB_POPUP = () => service.send(VcItemEvents.KEBAB_POPUP());
+ const ADD_WALLET_BINDING_ID = () =>
+ service.send(VcItemEvents.ADD_WALLET_BINDING_ID());
+ const CONFIRM = () => service.send(VcItemEvents.CONFIRM());
+ const REMOVE = (vcKey: string) => service.send(VcItemEvents.REMOVE(vcKey));
+ const DISMISS = () => service.send(VcItemEvents.DISMISS());
+ const CANCEL = () => service.send(VcItemEvents.CANCEL());
+ const SHOW_ACTIVITY = () => service.send(VcItemEvents.SHOW_ACTIVITY());
+ const INPUT_OTP = (otp: string) => service.send(VcItemEvents.INPUT_OTP(otp));
+ const isPinned = useSelector(service, selectIsPinned);
+ const isBindingWarning = useSelector(service, selectKebabPopUpBindingWarning);
+ const isRemoveWalletWarning = useSelector(service, selectRemoveWalletWarning);
+ const isAcceptingOtpInput = useSelector(
+ service,
+ selectKebabPopUpAcceptingBindingOtp
+ );
+ const isWalletBindingError = useSelector(
+ service,
+ selectShowWalletBindingError
+ );
+ const otpError = useSelector(service, selectOtpError);
+ const walletBindingError = useSelector(service, selectWalletBindingError);
+ const WalletBindingInProgress = useSelector(
+ service,
+ selectKebabPopUpWalletBindingInProgress
+ );
+ const emptyWalletBindingId = useSelector(service, selectEmptyWalletBindingId);
+ const isKebabPopUp = useSelector(service, selectKebabPopUp);
+ const isShowActivities = useSelector(service, selectShowActivities);
+ const { appService } = useContext(GlobalContext);
+ const activityLogService = appService.children.get('activityLog');
+
+ return {
+ isPinned,
+ PIN_CARD,
+ KEBAB_POPUP,
+ ADD_WALLET_BINDING_ID,
+ CONFIRM,
+ DISMISS,
+ REMOVE,
+ CANCEL,
+ INPUT_OTP,
+ SHOW_ACTIVITY,
+ isBindingWarning,
+ isAcceptingOtpInput,
+ isWalletBindingError,
+ walletBindingError,
+ otpError,
+ WalletBindingInProgress,
+ emptyWalletBindingId,
+ isKebabPopUp,
+ isShowActivities,
+ isRemoveWalletWarning,
+ activities: useSelector(activityLogService, selectActivities),
+ };
+}
diff --git a/components/LanguageSelector.tsx b/components/LanguageSelector.tsx
index 3a232875..33ff3dc3 100644
--- a/components/LanguageSelector.tsx
+++ b/components/LanguageSelector.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { SUPPORTED_LANGUAGES } from '../i18n';
import { I18nManager, View } from 'react-native';
import { Picker } from './ui/Picker';
-import AsyncStorage from '@react-native-async-storage/async-storage';
+import Storage from '../shared/storage';
import { useTranslation } from 'react-i18next';
import i18next from 'i18next';
import RNRestart from 'react-native-restart';
@@ -16,7 +16,7 @@ export const LanguageSelector: React.FC = (props) => {
const changeLanguage = async (language: string) => {
if (language !== i18n.language) {
await i18n.changeLanguage(language).then(async () => {
- await AsyncStorage.setItem('language', i18n.language);
+ await Storage.setItem('language', i18n.language);
const isRTL = i18next.dir(language) === 'rtl' ? true : false;
if (isRTL !== I18nManager.isRTL) {
try {
diff --git a/components/Logo.tsx b/components/Logo.tsx
index cd50fa53..e59ca86f 100644
--- a/components/Logo.tsx
+++ b/components/Logo.tsx
@@ -7,7 +7,7 @@ export const Logo: React.FC = (props) => {
);
diff --git a/components/MessageOverlay.tsx b/components/MessageOverlay.tsx
index c629b430..1b7aec30 100644
--- a/components/MessageOverlay.tsx
+++ b/components/MessageOverlay.tsx
@@ -14,14 +14,33 @@ export const MessageOverlay: React.FC = (props) => {
overlayStyle={Theme.MessageOverlayStyles.overlay}
onShow={props.onShow}
onBackdropPress={props.onBackdropPress}>
-
-
+
+
{props.title && (
-
+
{props.title}
)}
- {props.message && {props.message}}
+ {props.message && (
+
+ {props.message}
+
+ )}
{props.progress && }
{props.hint && (
= (props) => {
{!props.children && props.onCancel ? (
@@ -39,6 +40,7 @@ interface PasscodeProps {
message?: string;
error: string;
storedPasscode: string;
+ salt: string;
onSuccess: () => void;
onError: (value: string) => void;
onDismiss: () => void;
diff --git a/components/PasscodeVerify.tsx b/components/PasscodeVerify.tsx
index 0b5bbd0c..2eb2de94 100644
--- a/components/PasscodeVerify.tsx
+++ b/components/PasscodeVerify.tsx
@@ -1,6 +1,8 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PinInput } from './PinInput';
+import { hashData } from '../shared/commonUtil';
+import { argon2iConfig } from '../shared/constants';
export const MAX_PIN = 6;
@@ -16,8 +18,9 @@ export const PasscodeVerify: React.FC = (props) => {
return ;
- function verify(value: string) {
- if (props.passcode === value) {
+ async function verify(value: string) {
+ const hashedPasscode = await hashData(value, props.salt, argon2iConfig);
+ if (props.passcode === hashedPasscode) {
setIsVerified(true);
} else {
props.onError(t('passcodeMismatchError'));
@@ -29,4 +32,5 @@ interface PasscodeVerifyProps {
passcode: string;
onSuccess: () => void;
onError?: (error: string) => void;
+ salt: string;
}
diff --git a/components/PinInput.tsx b/components/PinInput.tsx
index fc2daead..04c958b1 100644
--- a/components/PinInput.tsx
+++ b/components/PinInput.tsx
@@ -22,6 +22,7 @@ export const PinInput: React.FC = (props) => {
selectTextOnFocus
keyboardType="numeric"
maxLength={1}
+ secureTextEntry
selectionColor={Theme.Colors.inputSelection}
style={Theme.PinInputStyle.input}
key={index}
diff --git a/components/ProgressingModal.tsx b/components/ProgressingModal.tsx
new file mode 100644
index 00000000..747dc720
--- /dev/null
+++ b/components/ProgressingModal.tsx
@@ -0,0 +1,75 @@
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Button, Centered, Column, Text } from './ui';
+import { Modal } from './ui/Modal';
+import { Image } from 'react-native';
+import { Theme } from './ui/styleUtils';
+import PaginationDot from 'react-native-animated-pagination-dot';
+
+export const ProgressingModal: React.FC = (props) => {
+ const { t } = useTranslation('ScanScreen');
+
+ let n = 0;
+ const [curPage, setCurPage] = useState(n);
+
+ const highLightDot = () => setCurPage(n + 1);
+
+ return (
+
+
+
+
+
+ {props.progress && (
+
+ )}
+
+
+
+
+
+ {props.hint}
+
+ {props.onCancel && (
+
+ )}
+
+
+
+
+
+ );
+};
+
+export interface ProgressingModalProps {
+ isVisible: boolean;
+ title?: string;
+ label?: string;
+ hint?: string;
+ onCancel?: () => void;
+ requester?: boolean;
+ progress?: boolean | number;
+ onBackdropPress?: () => void;
+}
diff --git a/components/QrCodeOverlay.tsx b/components/QrCodeOverlay.tsx
new file mode 100644
index 00000000..7037586d
--- /dev/null
+++ b/components/QrCodeOverlay.tsx
@@ -0,0 +1,64 @@
+import React, { useEffect, useState } from 'react';
+import { Dimensions, Pressable } from 'react-native';
+import { Icon, Overlay } from 'react-native-elements';
+import { Centered, Column, Row, Text } from './ui';
+import QRCode from 'react-native-qrcode-svg';
+import { Theme } from './ui/styleUtils';
+import { Image } from 'react-native';
+import { useTranslation } from 'react-i18next';
+
+export const QrCodeOverlay: React.FC = (props) => {
+ const { t } = useTranslation('VcDetails');
+
+ const [isQrOverlayVisible, setIsQrOverlayVisible] = useState(false);
+
+ const toggleQrOverlay = () => setIsQrOverlayVisible(!isQrOverlayVisible);
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {t('qrCodeHeader')}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+interface QrCodeOverlayProps {
+ qrCodeDetailes: string;
+}
diff --git a/components/QrScanner.tsx b/components/QrScanner.tsx
index e13be213..7f6f7003 100644
--- a/components/QrScanner.tsx
+++ b/components/QrScanner.tsx
@@ -2,20 +2,28 @@ 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 } from 'react-native';
+import {
+ Linking,
+ TouchableOpacity,
+ View,
+ Image,
+ Pressable,
+} from 'react-native';
import { Theme } from './ui/styleUtils';
-import { Column, Button, Text } from './ui';
+import { Column, Button, Text, Centered, Row } from './ui';
import { GlobalContext } from '../shared/GlobalContext';
import { useSelector } from '@xstate/react';
import { selectIsActive } from '../machines/app';
import { useTranslation } from 'react-i18next';
+import { useScanLayout } from '../screens/Scan/ScanLayoutController';
export const QrScanner: React.FC = (props) => {
const { t } = useTranslation('QrScanner');
const { appService } = useContext(GlobalContext);
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
- const [type, setType] = useState(Camera.Constants.Type.back);
+ const [cameraType, setCameraType] = useState(Camera.Constants.Type.back);
+ const controller = useScanLayout();
const isActive = useSelector(appService, selectIsActive);
@@ -43,24 +51,36 @@ export const QrScanner: React.FC = (props) => {
return ;
}
- if (hasPermission === false) {
+ const CameraDisabledPopUp: React.FC = () => {
return (
-
-
- {t('missingPermissionText')}
-
-
-
+
+
+
+
+ {t('cameraAccessDisabled')}
+
+
+ {t('cameraPermissionGuideLabel')}
+
+
+
+
+
+
+
);
- }
-
+ };
return (
- {props.title && (
-
- {props.title}
-
- )}
+ {hasPermission == false && }
= (props) => {
barcodeTypes: [BarCodeScanner.Constants.BarCodeType.qr],
}}
onBarCodeScanned={scanned ? undefined : onBarcodeScanned}
- type={type}
+ type={cameraType}
/>
-
+ {props.title && (
+
+ {props.title}
+
+ )}
+
{
- setType(
- type === Camera.Constants.Type.back
+ setCameraType(
+ cameraType === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
}}>
-
+
+
+ {t('flipCamera')}
+
);
diff --git a/components/SingleVcItem.tsx b/components/SingleVcItem.tsx
deleted file mode 100644
index fcc607c6..00000000
--- a/components/SingleVcItem.tsx
+++ /dev/null
@@ -1,208 +0,0 @@
-import React, { useContext, useRef } from 'react';
-import { useInterpret, useSelector } from '@xstate/react';
-import { Image, ImageBackground, Pressable } from 'react-native';
-import { CheckBox, Icon } from 'react-native-elements';
-import { ActorRefFrom } from 'xstate';
-import {
- createVcItemMachine,
- selectVerifiableCredential,
- selectGeneratedOn,
- selectId,
- vcItemMachine,
- selectContext,
-} from '../machines/vcItem';
-import { Column, Row, Text } from './ui';
-import { Theme } from './ui/styleUtils';
-import { GlobalContext } from '../shared/GlobalContext';
-import { RotatingIcon } from './RotatingIcon';
-import { useTranslation } from 'react-i18next';
-
-const VerifiedIcon: React.FC = () => {
- return (
-
- );
-};
-
-const getDetails = (arg1, arg2, verifiableCredential) => {
- if (arg1 === 'Full Name') {
- return (
-
-
- {arg1}
-
-
- {!verifiableCredential ? '' : arg2}
-
-
- );
- }
- if (arg1 === 'Status') {
- return (
-
-
- {arg1}
-
-
-
- {!verifiableCredential ? '' : arg2}
-
- {!verifiableCredential ? null : }
-
-
- );
- }
- return (
-
-
- {arg1}
-
-
- {!verifiableCredential ? '' : arg2}
-
-
- );
-};
-
-export const SingleVcItem: React.FC = (props) => {
- const { appService } = useContext(GlobalContext);
- const { t } = useTranslation('VcDetails');
-
- const machine = useRef(
- createVcItemMachine(
- appService.getSnapshot().context.serviceRefs,
- props.vcKey
- )
- );
-
- const service = useInterpret(machine.current);
- const context = useSelector(service, selectContext);
- const verifiableCredential = useSelector(service, selectVerifiableCredential);
- const uin = useSelector(service, selectId);
- const generatedOn = useSelector(service, selectGeneratedOn);
- const fullName = !verifiableCredential
- ? ''
- : getLocalizedField(verifiableCredential.credentialSubject.fullName);
-
- const selectableOrCheck = props.selectable ? (
- }
- uncheckedIcon={}
- onPress={() => props.onPress(service)}
- />
- ) : null;
-
- return (
- props.onPress(service)}>
-
-
-
-
-
-
-
-
-
- {getDetails(t('fullName'), fullName, verifiableCredential)}
- {getDetails(t('uin'), uin, verifiableCredential)}
- {getDetails(t('generatedOn'), generatedOn, verifiableCredential)}
- {getDetails(t('status'), t('valid'), verifiableCredential)}
-
-
-
- {verifiableCredential ? (
- selectableOrCheck
- ) : (
-
- )}
-
-
-
- );
-};
-
-interface VcItemProps {
- vcKey: string;
- margin?: string;
- selectable?: boolean;
- selected?: boolean;
- onPress?: (vcRef?: ActorRefFrom) => void;
- onShow?: (vcRef?: ActorRefFrom) => void;
-}
-
-interface LocalizedField {
- language: string;
- value: string;
-}
-
-function getLocalizedField(rawField: string | LocalizedField) {
- if (typeof rawField === 'string') {
- return rawField;
- }
- try {
- const locales: LocalizedField[] = JSON.parse(JSON.stringify(rawField));
- return locales[0].value;
- } catch (e) {
- return '';
- }
-}
diff --git a/components/TextEditOverlay.tsx b/components/TextEditOverlay.tsx
index b305384b..a8bbfbb7 100644
--- a/components/TextEditOverlay.tsx
+++ b/components/TextEditOverlay.tsx
@@ -18,7 +18,13 @@ export const TextEditOverlay: React.FC = (props) => {
{props.label}
-
+
);
};
@@ -37,5 +38,6 @@ interface TextItemProps {
text: string;
label?: string;
divider?: boolean;
+ topDivider?: boolean;
margin?: string;
}
diff --git a/components/ui/index.ts b/components/ui/index.ts
index a441c7dd..c5d3a139 100644
--- a/components/ui/index.ts
+++ b/components/ui/index.ts
@@ -1,3 +1,3 @@
export { Text } from './Text';
export { Button } from './Button';
-export { Row, Column, Centered } from './Layout';
+export { Row, Column, Centered, HorizontallyCentered } from './Layout';
diff --git a/components/ui/styleUtils.ts b/components/ui/styleUtils.ts
index e158134c..391a8f70 100644
--- a/components/ui/styleUtils.ts
+++ b/components/ui/styleUtils.ts
@@ -1,8 +1,10 @@
import { DefaultTheme } from './themes/DefaultTheme';
+import { PurpleTheme } from './themes/PurpleTheme';
+import { APPLICATION_THEME } from 'react-native-dotenv';
// To change the theme, CSS theme file has to import and assign it to Theme in line no 6
-
-export const Theme = DefaultTheme;
+export const Theme =
+ APPLICATION_THEME.toLowerCase() === 'purple' ? PurpleTheme : DefaultTheme;
type SpacingXY = [number, number];
type SpacingFull = [number, number, number, number];
diff --git a/components/ui/themes/DefaultTheme.ts b/components/ui/themes/DefaultTheme.ts
index c1390c2a..4e5f868e 100644
--- a/components/ui/themes/DefaultTheme.ts
+++ b/components/ui/themes/DefaultTheme.ts
@@ -3,21 +3,36 @@ import { Dimensions, StyleSheet, ViewStyle } from 'react-native';
import { Spacing } from '../styleUtils';
const Colors = {
- Black: '#231F20',
- Grey: '#B0B0B0',
+ Black: '#000000',
+ Zambezi: '#5F5F5F',
+ Grey: '#C7C7C7',
Grey5: '#E0E0E0',
Grey6: '#F2F2F2',
+ Gray40: '#666666',
+ Gray44: '#707070',
+ Gray9: '#171717',
+ DimGray: '#737373',
Orange: '#F2811D',
- LightGrey: '#f7f5f0',
+ LightGrey: '#F5F5F5',
+ ShadeOfGrey: '#6F6F6F',
White: '#FFFFFF',
- Red: '#EB5757',
- Green: '#219653',
+ Red: '#D52929',
+ Green: '#4B9D20',
Transparent: 'transparent',
Warning: '#f0ad4e',
- LightOrange: '#fce7e3',
+ GrayText: '#6F6F6F',
+ dorColor: '#CBCBCB',
+ plainText: '#FFD6A7',
+ walletbindingLabel: '#000000',
+ LightOrange: '#FDF1E6',
+ GradientColors: ['#F59B4B', '#E86E04'],
+ DisabledColors: ['#C7C7C7', '#C7C7C7'],
+ TimeoutHintBoxColor: '#FFF7E5',
+ TimoutText: '#8B6105',
+ resendCodeTimer: '#555555',
};
-export type ElevationLevel = 0 | 1 | 2 | 3 | 4 | 5;
+export type ElevationLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6;
export const DefaultTheme = {
Colors: {
@@ -27,25 +42,32 @@ export const DefaultTheme = {
LoadingDetailsLabel: Colors.Orange,
AddIdBtnBg: Colors.Orange,
AddIdBtnTxt: Colors.Orange,
- ClearAddIdBtnBg: Colors.Transparent,
+ DownloadIdBtnTxt: Colors.White,
Loading: Colors.Orange,
+ Cursor: Colors.Orange,
noUinText: Colors.Orange,
IconBg: Colors.Orange,
+ popUp: Colors.Green,
Icon: Colors.Orange,
GrayIcon: Colors.Grey,
+ helpText: Colors.Gray44,
borderBottomColor: Colors.Grey6,
whiteBackgroundColor: Colors.White,
lightGreyBackgroundColor: Colors.LightGrey,
profileLanguageValue: Colors.Grey,
- profileVersion: Colors.Grey,
+ aboutVersion: Colors.Gray40,
profileAuthFactorUnlock: Colors.Grey,
profileLabel: Colors.Black,
profileValue: Colors.Grey,
+ switchHead: Colors.Orange,
+ switchTrackTrue: Colors.LightOrange,
+ switchTrackFalse: Colors.Grey,
overlayBackgroundColor: Colors.White,
rotatingIcon: Colors.Grey5,
loadingLabel: Colors.Grey6,
textLabel: Colors.Grey,
textValue: Colors.Black,
+ requesterName: Colors.Red,
errorMessage: Colors.Red,
QRCodeBackgroundColor: Colors.LightGrey,
ReceiveVcModalBackgroundColor: Colors.LightGrey,
@@ -54,12 +76,28 @@ export const DefaultTheme = {
whiteText: Colors.White,
flipCameraIcon: Colors.Black,
IdInputModalBorder: Colors.Grey,
+ RetrieveIdLabel: Colors.ShadeOfGrey,
inputSelection: Colors.Orange,
checkCircleIcon: Colors.White,
OnboardingCircleIcon: Colors.White,
OnboardingCloseIcon: Colors.White,
WarningIcon: Colors.Warning,
+ DefaultToggle: Colors.LightOrange,
ProfileIconBg: Colors.LightOrange,
+ GrayText: Colors.GrayText,
+ gradientBtn: ['#F59B4B', '#E86E04'],
+ dotColor: Colors.dorColor,
+ plainText: Colors.plainText,
+ IconBackground: Colors.LightOrange,
+ GradientColors: Colors.GradientColors,
+ DisabledColors: Colors.DisabledColors,
+ getVidColor: Colors.Zambezi,
+ TimeoutHintBoxColor: Colors.TimeoutHintBoxColor,
+ TimoutText: Colors.TimoutText,
+ walletbindingLabel: Colors.Black,
+ walletbindingContent: Colors.Gray40,
+ resendCodeTimer: Colors.resendCodeTimer,
+ statusLabel: Colors.Black,
},
Styles: StyleSheet.create({
title: {
@@ -78,6 +116,19 @@ export const DefaultTheme = {
backgroundColor: Colors.Grey,
borderRadius: 4,
},
+ statusLabel: {
+ color: Colors.Black,
+ },
+ verifiedIconContainer: {
+ marginLeft: 5,
+ },
+ verifiedIconInner: {
+ backgroundColor: 'white',
+ borderRadius: 10,
+ },
+ vcItemLabelHeader: {
+ color: Colors.Orange,
+ },
closeDetails: {
flex: 1,
flexDirection: 'row',
@@ -89,6 +140,38 @@ export const DefaultTheme = {
backgroundColor: Colors.Grey6,
borderRadius: 4,
},
+ loadingCardDetailsContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ backgroundColor: Colors.Grey6,
+ borderRadius: 4,
+ },
+ cardDetailsContainer: {},
+ bottomTabIconStyle: {
+ padding: 4,
+ width: 36,
+ height: 36,
+ borderRadius: 6,
+ backgroundColor: Colors.LightOrange,
+ },
+ downloadingVcPopUp: {
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ backgroundColor: Colors.Green,
+ height: 39,
+ position: 'relative',
+ paddingHorizontal: 12,
+ },
+ homeScreenContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 10,
+ backgroundColor: '#fff',
+ shadowColor: '#000',
+ shadowOpacity: 0.4,
+ elevation: 5,
+ padding: 10,
+ },
vertloadingContainer: {
flex: 1,
backgroundColor: Colors.Grey6,
@@ -99,10 +182,11 @@ export const DefaultTheme = {
flex: 1,
justifyContent: 'flex-start',
},
- logoContainer: {
+ closecardMosipLogo: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
+ alignSelf: 'flex-end',
marginLeft: 300,
},
closeCardBgContainer: {
@@ -116,6 +200,12 @@ export const DefaultTheme = {
elevation: 4,
},
selectedBindedVc: {
+ borderRadius: 15,
+ margin: 5,
+ borderWidth: 3,
+ borderColor: Colors.Green,
+ },
+ selectedVc: {
borderRadius: 10,
margin: 5,
borderWidth: 2,
@@ -138,7 +228,7 @@ export const DefaultTheme = {
width: 100,
},
bottomButtonsContainer: {
- height: 120,
+ height: 'auto',
borderTopLeftRadius: 27,
borderTopRightRadius: 27,
padding: 6,
@@ -175,8 +265,6 @@ export const DefaultTheme = {
backgroundImageContainer: {
flex: 1,
padding: 10,
- borderBottomColor: Colors.Grey,
- borderBottomWidth: 1,
},
successTag: {
backgroundColor: Colors.Green,
@@ -198,13 +286,17 @@ export const DefaultTheme = {
justifyContent: 'space-between',
},
logo: {
- height: 36,
- width: 30,
+ height: 35,
+ width: 90,
},
homeCloseCardDetailsHeader: {
flex: 1,
+ },
+ cardDetailsHeader: {
+ flex: 1,
justifyContent: 'space-between',
},
+ mosipLogoContainer: {},
details: {
width: 290,
marginLeft: 110,
@@ -221,6 +313,38 @@ export const DefaultTheme = {
borderRadius: 6,
backgroundColor: Colors.LightOrange,
},
+ IconContainer: {
+ padding: 6,
+ width: 36,
+ marginRight: 4,
+ marginLeft: 10,
+ height: 36,
+ borderRadius: 10,
+ backgroundColor: Colors.LightOrange,
+ },
+ settingsIconBg: {
+ padding: 6,
+ width: 36,
+ marginRight: 4,
+ height: 36,
+ backgroundColor: Colors.Transparent,
+ },
+ backArrowContainer: {
+ padding: 6,
+ width: 36,
+ height: 36,
+ borderRadius: 10,
+ backgroundColor: Colors.LightOrange,
+ },
+ receiveCardsContainer: {
+ height: Dimensions.get('window').height * 0.12,
+ width: Dimensions.get('window').width * 0.45,
+ alignItems: 'center',
+ borderBottomRightRadius: 0,
+ padding: 15,
+ marginVertical: 18,
+ elevation: 1,
+ },
domainVerifiyIcon: {
padding: 20,
marginLeft: 120,
@@ -241,24 +365,46 @@ export const DefaultTheme = {
height: 135,
borderRadius: 5,
},
+ versionContainer: {
+ backgroundColor: Colors.Grey6,
+ margin: 4,
+ borderRadius: 14,
+ },
+ primaryRow: {
+ backgroundColor: Colors.LightOrange,
+ paddingHorizontal: 18,
+ paddingVertical: 9,
+ justifyContent: 'space-between',
+ },
+ iconContainer: {
+ flexDirection: 'row',
+ alignItems: 'flex-end',
+ },
scannerContainer: {
- borderWidth: 4,
- borderColor: Colors.Black,
- borderRadius: 32,
- justifyContent: 'center',
- height: 300,
- width: 300,
+ borderRadius: 24,
+ alignSelf: 'center',
+ height: 350,
+ width: 320,
overflow: 'hidden',
- marginLeft: 18,
},
scanner: {
height: 400,
width: '100%',
margin: 'auto',
},
- flipIconButton: {
- alignSelf: 'center',
+ cameraDisabledPopUp: {
alignItems: 'center',
+ justifyContent: 'space-between',
+ backgroundColor: Colors.Red,
+ height: 75,
+ position: 'relative',
+ paddingHorizontal: 15,
+ marginTop: -36,
+ },
+ photoConsentLabel: {
+ backgroundColor: Colors.White,
+ padding: 0,
+ borderWidth: 0,
},
tabIndicator: {
backgroundColor: Colors.Orange,
@@ -273,55 +419,134 @@ export const DefaultTheme = {
detailsText: {
fontWeight: 'bold',
fontSize: 15,
- fontFamily: 'Poppins_700Bold',
+ fontFamily: 'Inter_700Bold',
},
getId: {
justifyContent: 'center',
alignItems: 'center',
- marginTop: 10,
+ marginVertical: 6,
},
placeholder: {
- fontFamily: 'Poppins_400Regular',
+ fontFamily: 'Inter_600SemiBold',
+ },
+ hrLine: {
+ borderBottomColor: 'black',
+ borderBottomWidth: 1,
+ marginTop: 10,
+ },
+ }),
+ QrCodeStyles: StyleSheet.create({
+ magnifierZoom: {
+ backgroundColor: Colors.White,
+ width: 30,
+ height: 30,
+ alignItems: 'center',
+ padding: 5,
+ borderTopLeftRadius: 11,
+ elevation: 4,
+ },
+ expandedQrCode: {
+ backgroundColor: Colors.White,
+ width: 350,
+ borderRadius: 21,
+ },
+ QrCodeHeader: {
+ backgroundColor: Colors.White,
+ borderTopLeftRadius: 21,
+ borderTopRightRadius: 21,
+ justifyContent: 'space-between',
+ fontFamily: 'Inter_700Bold',
+ paddingBottom: 10,
+ paddingRight: 15,
+ paddingLeft: 130,
+ elevation: 2,
+ },
+ warningText: {
+ color: Colors.Red,
+ fontSize: 18,
},
}),
PinInputStyle: StyleSheet.create({
input: {
- borderBottomWidth: 1,
+ borderBottomWidth: 3,
borderColor: Colors.Grey,
color: Colors.Black,
flex: 1,
- fontFamily: 'Poppins_600SemiBold',
- fontSize: 18,
- fontWeight: '600',
- height: 40,
+ fontSize: 33,
+ fontFamily: 'Inter_600SemiBold',
+ height: 60,
lineHeight: 28,
margin: 8,
textAlign: 'center',
},
+ onEnteringPin: {
+ borderBottomWidth: 3,
+ borderColor: Colors.Orange,
+ color: Colors.Black,
+ flex: 1,
+ fontFamily: 'Inter_700Bold',
+ fontSize: 29,
+ height: 40,
+ margin: 8,
+ textAlign: 'center',
+ },
}),
TextStyles: StyleSheet.create({
- base: {
+ header: {
+ color: Colors.Black,
+ fontFamily: 'Inter_700Bold',
+ fontSize: 18,
+ lineHeight: 22,
+ paddingTop: 4,
+ },
+ retrieveIdLabel: {
+ color: Colors.ShadeOfGrey,
+ fontFamily: 'Inter_600SemiBold',
+ lineHeight: 18,
+ },
+ helpDetailes: {
+ margin: 5,
+ color: Colors.Gray44,
+ fontFamily: 'Inter_600SemiBold',
+ },
+ aboutDetailes: {
color: Colors.Black,
fontSize: 18,
- lineHeight: 28,
+ margin: 7,
+ lineHeight: 18,
+ },
+ error: {
+ color: Colors.Red,
+ fontFamily: 'Inter_600SemiBold',
+ fontSize: 12,
+ },
+ base: {
+ color: Colors.Black,
+ fontSize: 16,
+ lineHeight: 18,
},
regular: {
- fontFamily: 'Poppins_400Regular',
+ fontFamily: 'Inter_400Regular',
+ fontSize: 14,
},
semibold: {
- fontFamily: 'Poppins_600SemiBold',
+ fontFamily: 'Inter_600SemiBold',
+ fontSize: 15,
},
bold: {
- fontFamily: 'Poppins_700Bold',
+ fontFamily: 'Inter_700Bold',
},
small: {
- fontSize: 14,
+ fontSize: 13,
lineHeight: 21,
},
smaller: {
- fontSize: 12,
+ fontSize: 11,
lineHeight: 18,
},
+ large: {
+ fontSize: 18,
+ },
}),
VcItemStyles: StyleSheet.create({
title: {
@@ -376,15 +601,29 @@ export const DefaultTheme = {
borderColor: Colors.Orange,
},
container: {
- minHeight: 48,
+ height: 45,
flexDirection: 'row',
},
disabled: {
- opacity: 0.5,
+ backgroundColor: Colors.Grey,
},
addId: {
backgroundColor: Colors.Orange,
},
+ gradient: {
+ borderRadius: 9,
+ width: Dimensions.get('window').width * 0.72,
+ alignSelf: 'center',
+ margin: 4,
+ },
+ float: {
+ borderRadius: 9,
+ alignSelf: 'center',
+ fontSize: 10,
+ elevation: 5,
+ position: 'absolute',
+ bottom: 24,
+ },
clearAddIdBtnBg: {
backgroundColor: Colors.Transparent,
},
@@ -404,14 +643,35 @@ export const DefaultTheme = {
padding: 32,
},
}),
+ QRCodeOverlay: StyleSheet.create({
+ header: {},
+ }),
SelectVcOverlayStyles: StyleSheet.create({
overlay: {
elevation: 5,
backgroundColor: Colors.White,
padding: 0,
},
+ consentCheckContainer: {
+ backgroundColor: Colors.White,
+ borderWidth: 0,
+ marginTop: -15,
+ fontFamily: 'Inter_600SemiBold',
+ padding: 0,
+ },
+ timeoutHintContainer: {
+ backgroundColor: Colors.TimeoutHintBoxColor,
+ margin: 21,
+ paddingHorizontal: 14,
+ paddingVertical: 12,
+ borderRadius: 12,
+ },
+ sharedSuccessfully: {
+ flex: 1,
+ backgroundColor: Colors.White,
+ },
}),
- CreditsStyles: StyleSheet.create({
+ AppMetaDataStyles: StyleSheet.create({
buttonContainer: {
position: 'absolute',
left: 0,
@@ -421,9 +681,23 @@ export const DefaultTheme = {
flex: 1,
width: Dimensions.get('screen').width,
},
- markdownView: {
+ contentView: {
+ flex: 1,
padding: 20,
},
+ header: {
+ fontSize: 20,
+ fontWeight: 'normal',
+ color: 'rgb(28,28,30)',
+ },
+ }),
+ FooterStyles: StyleSheet.create({
+ bottom: {
+ justifyContent: 'flex-end',
+ backgroundColor: Colors.Grey6,
+ borderRadius: 15,
+ padding: 10,
+ },
}),
ModalStyles: StyleSheet.create({
modal: {
@@ -464,16 +738,44 @@ export const DefaultTheme = {
height: Dimensions.get('screen').height,
},
}),
+ KebabPopUpStyles: StyleSheet.create({
+ kebabPopUp: {
+ borderTopLeftRadius: 15,
+ borderTopRightRadius: 15,
+ width: Dimensions.get('screen').width,
+ marginTop: Dimensions.get('screen').height * 0.55,
+ },
+ kebabHeaderStyle: {
+ justifyContent: 'space-between',
+ fontFamily: 'Inter_700Bold',
+ paddingRight: 15,
+ paddingLeft: 130,
+ paddingTop: 18,
+ },
+ }),
MessageOverlayStyles: StyleSheet.create({
overlay: {
elevation: 5,
backgroundColor: Colors.White,
- padding: 0,
+ padding: 5,
+ borderRadius: 10,
+ },
+ buttonContainer: {
+ justifyContent: 'center',
+ marginBottom: 75,
+ },
+ popupOverLay: {
+ height: 150,
+ backgroundColor: Colors.White,
},
button: {
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
},
+ halfButton: {
+ borderRadius: 8,
+ margin: '0.5%',
+ },
}),
BindingVcWarningOverlay: StyleSheet.create({
overlay: {
@@ -631,7 +933,7 @@ export const DefaultTheme = {
sliderTitle: {
color: Colors.White,
marginBottom: 20,
- fontFamily: 'Poppins_700Bold',
+ fontFamily: 'Inter_700Bold',
},
text: {
color: Colors.White,
@@ -651,20 +953,43 @@ export const DefaultTheme = {
top: 40,
zIndex: 1,
},
+ bottomContainer: {
+ padding: 20,
+ borderTopLeftRadius: 30,
+ borderTopRightRadius: 30,
+ marginTop: -185,
+ paddingBottom: 100,
+ },
}),
claimsContainer: StyleSheet.create({
container: {
backgroundColor: Colors.Transparent,
},
}),
- OpenCard: require('../../../assets/ID-open.png'),
- CloseCard: require('../../../assets/ID-closed.png'),
+ OpenCard: '',
+ CloseCard: '',
ProfileIcon: require('../../../assets/placeholder-photo.png'),
+ MosipSplashLogo: require('../../../assets/icon.png'),
MosipLogo: require('../../../assets/mosip-logo.png'),
+ CameraFlipIcon: require('../../../assets/camera-flip-icon.png'),
DomainWarningLogo: require('../../../assets/domain-warning.png'),
WarningLogo: require('../../../assets/warningLogo.png'),
OtpLogo: require('../../../assets/otp-mobile-logo.png'),
SuccessLogo: require('../../../assets/success-logo.png'),
+ ReceiveCardIcon: require('../../../assets/receive-card-icon.png'),
+ ReceivedCardsIcon: require('../../../assets/received-cards-icon.png'),
+ DigitalIdentityLogo: require('../../../assets/digital-identity-icon.png'),
+ InjiLogoWhite: require('../../../assets/inji-logo-white.png'),
+ InjiProgressingLogo: require('../../../assets/progressing-logo.png'),
+ LockIcon: require('../../../assets/lock-icon.png'),
+ InjiHomeLogo: require('../../../assets/inji-home-logo.png'),
+ MagnifierZoom: require('../../../assets/magnifier-zoom.png'),
+ HelpIcon: require('../../../assets/help-icon.png'),
+ sharingIntro: require('../../../assets/Secure-Sharing.png'),
+ walletIntro: require('../../../assets/intro-wallet-binding.png'),
+ IntroScanner: require('../../../assets/intro-scanner.png'),
+ injiSmallLogo: require('../../../assets/inji_small_logo.png'),
+ protectPrivacy: require('../../../assets/phone_mockup_1.png'),
elevation(level: ElevationLevel): ViewStyle {
// https://ethercreative.github.io/react-native-shadow-generator/
diff --git a/components/ui/themes/PurpleTheme.ts b/components/ui/themes/PurpleTheme.ts
index 23d23e9a..ed252cb4 100644
--- a/components/ui/themes/PurpleTheme.ts
+++ b/components/ui/themes/PurpleTheme.ts
@@ -4,48 +4,72 @@ import { Spacing } from '../styleUtils';
const Colors = {
Black: '#231F20',
+ Zambezi: '#5F5F5F',
Grey: '#B0B0B0',
Grey5: '#E0E0E0',
Grey6: '#F2F2F2',
+ Gray40: '#666666',
+ Gray44: '#707070',
+ Gray9: '#171717',
+ DimGray: '#737373',
Orange: '#F2811D',
+ LightOrange: '#FDF1E6',
LightGrey: '#FAF9FF',
+ ShadeOfGrey: '#6F6F6F',
White: '#FFFFFF',
Red: '#EB5757',
Green: '#219653',
- Purple: '#70308C',
Transparent: 'transparent',
Warning: '#f0ad4e',
+ GrayText: '#6F6F6F',
+ dorColor: '#CBCBCB',
+ plainText: '#FFD6A7',
+ walletbindingLabel: '#000000',
+ GradientColors: ['#373086', '#70308C'],
+ DisabledColors: ['#C7C7C7', '#C7C7C7'],
+ Purple: '#70308C',
+ LightPurple: '#AEA7FF',
+ TimeoutHintBoxColor: '#FFF7E5',
+ TimoutText: '#8B6105',
+ resendCodeTimer: '#555555',
};
-export type ElevationLevel = 0 | 1 | 2 | 3 | 4 | 5;
+export type ElevationLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6;
export const PurpleTheme = {
Colors: {
TabItemText: Colors.Purple,
- Details: Colors.White,
- DetailsLabel: Colors.White,
- LoadingDetailsLabel: Colors.Black,
+ Details: Colors.Black,
+ DetailsLabel: Colors.Purple,
+ LoadingDetailsLabel: Colors.Purple,
AddIdBtnBg: Colors.Purple,
AddIdBtnTxt: Colors.Purple,
- ClearAddIdBtnBg: 'transparent',
+ DownloadIdBtnTxt: Colors.White,
+ Loading: Colors.Purple,
+ Cursor: Colors.Purple,
noUinText: Colors.Purple,
IconBg: Colors.Purple,
+ popUp: Colors.Green,
Icon: Colors.Purple,
GrayIcon: Colors.Grey,
- Loading: Colors.Purple,
+ helpText: Colors.Gray44,
borderBottomColor: Colors.Grey6,
whiteBackgroundColor: Colors.White,
lightGreyBackgroundColor: Colors.LightGrey,
profileLanguageValue: Colors.Grey,
- profileVersion: Colors.Grey,
+ aboutVersion: Colors.Gray40,
profileAuthFactorUnlock: Colors.Grey,
profileLabel: Colors.Black,
profileValue: Colors.Grey,
+ switchHead: Colors.Purple,
+ switchTrackTrue: Colors.LightPurple,
+ switchTrackFalse: Colors.Grey,
overlayBackgroundColor: Colors.White,
rotatingIcon: Colors.Grey5,
loadingLabel: Colors.Grey6,
textLabel: Colors.Grey,
textValue: Colors.Black,
+ requesterName: Colors.Red,
errorMessage: Colors.Red,
QRCodeBackgroundColor: Colors.LightGrey,
ReceiveVcModalBackgroundColor: Colors.LightGrey,
@@ -54,11 +78,28 @@ export const PurpleTheme = {
whiteText: Colors.White,
flipCameraIcon: Colors.Black,
IdInputModalBorder: Colors.Grey,
- inputSelection: Colors.Orange,
+ RetrieveIdLabel: Colors.ShadeOfGrey,
+ inputSelection: Colors.Purple,
checkCircleIcon: Colors.White,
OnboardingCircleIcon: Colors.White,
OnboardingCloseIcon: Colors.White,
WarningIcon: Colors.Warning,
+ DefaultToggle: Colors.LightPurple,
+ ProfileIconBg: Colors.LightPurple,
+ GrayText: Colors.GrayText,
+ gradientBtn: Colors.GradientColors,
+ dotColor: Colors.dorColor,
+ plainText: Colors.plainText,
+ IconBackground: Colors.LightPurple,
+ GradientColors: Colors.GradientColors,
+ DisabledColors: Colors.DisabledColors,
+ getVidColor: Colors.Zambezi,
+ TimeoutHintBoxColor: Colors.TimeoutHintBoxColor,
+ TimoutText: Colors.TimoutText,
+ walletbindingLabel: Colors.Black,
+ walletbindingContent: Colors.Gray40,
+ resendCodeTimer: Colors.resendCodeTimer,
+ statusLabel: Colors.Black,
},
Styles: StyleSheet.create({
title: {
@@ -77,6 +118,19 @@ export const PurpleTheme = {
backgroundColor: Colors.Grey,
borderRadius: 4,
},
+ statusLabel: {
+ color: Colors.Black,
+ },
+ verifiedIconContainer: {
+ marginLeft: 5,
+ },
+ verifiedIconInner: {
+ backgroundColor: 'white',
+ borderRadius: 10,
+ },
+ vcItemLabelHeader: {
+ color: Colors.Purple,
+ },
closeDetails: {
flex: 1,
flexDirection: 'row',
@@ -88,6 +142,38 @@ export const PurpleTheme = {
backgroundColor: Colors.Grey6,
borderRadius: 4,
},
+ loadingCardDetailsContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ backgroundColor: Colors.Grey6,
+ borderRadius: 4,
+ },
+ cardDetailsContainer: {},
+ bottomTabIconStyle: {
+ padding: 4,
+ width: 36,
+ height: 36,
+ borderRadius: 6,
+ backgroundColor: Colors.LightPurple,
+ },
+ downloadingVcPopUp: {
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ backgroundColor: Colors.Green,
+ height: 39,
+ position: 'relative',
+ paddingHorizontal: 12,
+ },
+ homeScreenContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 10,
+ backgroundColor: '#fff',
+ shadowColor: '#000',
+ shadowOpacity: 0.4,
+ elevation: 5,
+ padding: 10,
+ },
vertloadingContainer: {
flex: 1,
backgroundColor: Colors.Grey6,
@@ -98,10 +184,11 @@ export const PurpleTheme = {
flex: 1,
justifyContent: 'flex-start',
},
- logoContainer: {
+ closecardMosipLogo: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
+ alignSelf: 'flex-end',
marginLeft: 300,
},
closeCardBgContainer: {
@@ -114,10 +201,54 @@ export const PurpleTheme = {
shadowRadius: 3,
elevation: 4,
},
+ selectedBindedVc: {
+ borderRadius: 15,
+ margin: 5,
+ borderWidth: 3,
+ borderColor: Colors.Green,
+ },
+ selectedVc: {
+ borderRadius: 10,
+ margin: 5,
+ borderWidth: 2,
+ borderColor: Colors.Purple,
+ },
labelPartContainer: {
marginLeft: 16,
flex: 1,
},
+ urlContainer: {
+ backgroundColor: Colors.White,
+ padding: 10,
+ borderRadius: 12,
+ fontSize: 12,
+ },
+ lockDomainContainer: {
+ backgroundColor: Colors.White,
+ alignSelf: 'center',
+ borderRadius: 15,
+ width: 100,
+ },
+ bottomButtonsContainer: {
+ height: 'auto',
+ borderTopLeftRadius: 27,
+ borderTopRightRadius: 27,
+ padding: 6,
+ backgroundColor: Colors.White,
+ },
+ consentPageTop: {
+ backgroundColor: Colors.White,
+ height: 160,
+ borderRadius: 6,
+ },
+ consentDottedLine: {
+ width: 182,
+ borderWidth: 2,
+ margin: 5,
+ borderStyle: 'dashed',
+ borderRadius: 1,
+ borderColor: 'grey',
+ },
labelPart: {
marginTop: 10,
alignItems: 'flex-start',
@@ -136,8 +267,6 @@ export const PurpleTheme = {
backgroundImageContainer: {
flex: 1,
padding: 10,
- borderBottomColor: Colors.Grey,
- borderBottomWidth: 1,
},
successTag: {
backgroundColor: Colors.Green,
@@ -159,13 +288,17 @@ export const PurpleTheme = {
justifyContent: 'space-between',
},
logo: {
- height: 36,
- width: 36,
+ height: 35,
+ width: 90,
},
homeCloseCardDetailsHeader: {
flex: 1,
+ },
+ cardDetailsHeader: {
+ flex: 1,
justifyContent: 'space-between',
},
+ mosipLogoContainer: {},
details: {
width: 290,
marginLeft: 110,
@@ -175,6 +308,55 @@ export const PurpleTheme = {
flex: 1,
padding: 10,
},
+ profileIconBg: {
+ padding: 8,
+ width: 40,
+ height: 40,
+ borderRadius: 6,
+ backgroundColor: Colors.LightPurple,
+ },
+ IconContainer: {
+ padding: 6,
+ width: 36,
+ marginRight: 4,
+ marginLeft: 10,
+ height: 36,
+ borderRadius: 10,
+ backgroundColor: Colors.LightPurple,
+ },
+ settingsIconBg: {
+ padding: 6,
+ width: 36,
+ marginRight: 4,
+ height: 36,
+ backgroundColor: Colors.Transparent,
+ },
+ backArrowContainer: {
+ padding: 6,
+ width: 36,
+ height: 36,
+ borderRadius: 10,
+ backgroundColor: Colors.LightPurple,
+ },
+ receiveCardsContainer: {
+ height: Dimensions.get('window').height * 0.12,
+ width: Dimensions.get('window').width * 0.45,
+ alignItems: 'center',
+ borderBottomRightRadius: 0,
+ padding: 15,
+ marginVertical: 18,
+ elevation: 1,
+ },
+ domainVerifiyIcon: {
+ padding: 20,
+ marginLeft: 120,
+ width: 130,
+ height: 130,
+ borderRadius: 60,
+ borderWidth: 10,
+ borderColor: Colors.White,
+ backgroundColor: Colors.LightPurple,
+ },
closeCardImage: {
width: 105,
height: 135,
@@ -185,13 +367,26 @@ export const PurpleTheme = {
height: 135,
borderRadius: 5,
},
+ versionContainer: {
+ backgroundColor: Colors.Grey6,
+ margin: 4,
+ borderRadius: 14,
+ },
+ primaryRow: {
+ backgroundColor: Colors.LightPurple,
+ paddingHorizontal: 18,
+ paddingVertical: 9,
+ justifyContent: 'space-between',
+ },
+ iconContainer: {
+ flexDirection: 'row',
+ alignItems: 'flex-end',
+ },
scannerContainer: {
- borderWidth: 4,
- borderColor: Colors.Black,
- borderRadius: 32,
- justifyContent: 'center',
- height: 300,
- width: 300,
+ borderRadius: 24,
+ alignSelf: 'center',
+ height: 350,
+ width: 320,
overflow: 'hidden',
},
scanner: {
@@ -199,9 +394,19 @@ export const PurpleTheme = {
width: '100%',
margin: 'auto',
},
- flipIconButton: {
- alignSelf: 'center',
+ cameraDisabledPopUp: {
alignItems: 'center',
+ justifyContent: 'space-between',
+ backgroundColor: Colors.Red,
+ height: 75,
+ position: 'relative',
+ paddingHorizontal: 15,
+ marginTop: -36,
+ },
+ photoConsentLabel: {
+ backgroundColor: Colors.White,
+ padding: 0,
+ borderWidth: 0,
},
tabIndicator: {
backgroundColor: Colors.Purple,
@@ -216,55 +421,134 @@ export const PurpleTheme = {
detailsText: {
fontWeight: 'bold',
fontSize: 15,
- fontFamily: 'Poppins_700Bold',
+ fontFamily: 'Inter_700Bold',
},
getId: {
justifyContent: 'center',
alignItems: 'center',
- marginTop: 10,
+ marginVertical: 6,
},
placeholder: {
- fontFamily: 'Poppins_400Regular',
+ fontFamily: 'Inter_600SemiBold',
+ },
+ hrLine: {
+ borderBottomColor: 'black',
+ borderBottomWidth: 1,
+ marginTop: 10,
+ },
+ }),
+ QrCodeStyles: StyleSheet.create({
+ magnifierZoom: {
+ backgroundColor: Colors.White,
+ width: 30,
+ height: 30,
+ alignItems: 'center',
+ padding: 5,
+ borderTopLeftRadius: 11,
+ elevation: 4,
+ },
+ expandedQrCode: {
+ backgroundColor: Colors.White,
+ width: 350,
+ borderRadius: 21,
+ },
+ QrCodeHeader: {
+ backgroundColor: Colors.White,
+ borderTopLeftRadius: 21,
+ borderTopRightRadius: 21,
+ justifyContent: 'space-between',
+ fontFamily: 'Inter_700Bold',
+ paddingBottom: 10,
+ paddingRight: 15,
+ paddingLeft: 130,
+ elevation: 2,
+ },
+ warningText: {
+ color: Colors.Red,
+ fontSize: 18,
},
}),
PinInputStyle: StyleSheet.create({
input: {
- borderBottomWidth: 1,
+ borderBottomWidth: 3,
borderColor: Colors.Grey,
color: Colors.Black,
flex: 1,
- fontFamily: 'Poppins_600SemiBold',
- fontSize: 18,
- fontWeight: '600',
+ fontSize: 33,
+ fontFamily: 'Inter_600SemiBold',
height: 40,
lineHeight: 28,
margin: 8,
textAlign: 'center',
},
+ onEnteringPin: {
+ borderBottomWidth: 3,
+ borderColor: Colors.Purple,
+ color: Colors.Black,
+ flex: 1,
+ fontFamily: 'Inter_700Bold',
+ fontSize: 29,
+ height: 60,
+ margin: 8,
+ textAlign: 'center',
+ },
}),
TextStyles: StyleSheet.create({
- base: {
+ header: {
+ color: Colors.Black,
+ fontFamily: 'Inter_700Bold',
+ fontSize: 18,
+ lineHeight: 22,
+ paddingTop: 4,
+ },
+ retrieveIdLabel: {
+ color: Colors.ShadeOfGrey,
+ fontFamily: 'Inter_600SemiBold',
+ lineHeight: 18,
+ },
+ helpDetailes: {
+ margin: 5,
+ color: Colors.Gray44,
+ fontFamily: 'Inter_600SemiBold',
+ },
+ aboutDetailes: {
color: Colors.Black,
fontSize: 18,
- lineHeight: 28,
+ margin: 7,
+ lineHeight: 18,
+ },
+ error: {
+ color: Colors.Red,
+ fontFamily: 'Inter_600SemiBold',
+ fontSize: 12,
+ },
+ base: {
+ color: Colors.Black,
+ fontSize: 16,
+ lineHeight: 18,
},
regular: {
- fontFamily: 'Poppins_400Regular',
+ fontFamily: 'Inter_400Regular',
+ fontSize: 14,
},
semibold: {
- fontFamily: 'Poppins_600SemiBold',
+ fontFamily: 'Inter_600SemiBold',
+ fontSize: 15,
},
bold: {
- fontFamily: 'Poppins_700Bold',
+ fontFamily: 'Inter_700Bold',
},
small: {
- fontSize: 14,
+ fontSize: 13,
lineHeight: 21,
},
smaller: {
- fontSize: 12,
+ fontSize: 11,
lineHeight: 18,
},
+ large: {
+ fontSize: 18,
+ },
}),
VcItemStyles: StyleSheet.create({
title: {
@@ -294,7 +578,7 @@ export const PurpleTheme = {
}),
ToastItemStyles: StyleSheet.create({
toastContainer: {
- backgroundColor: Colors.Orange,
+ backgroundColor: Colors.Purple,
position: 'absolute',
alignSelf: 'center',
top: 80,
@@ -319,22 +603,35 @@ export const PurpleTheme = {
borderColor: Colors.Purple,
},
container: {
- minHeight: 48,
+ height: 45,
flexDirection: 'row',
},
disabled: {
- opacity: 0.5,
+ backgroundColor: Colors.Grey,
},
addId: {
backgroundColor: Colors.Purple,
},
+ gradient: {
+ borderRadius: 9,
+ width: Dimensions.get('window').width * 0.72,
+ alignSelf: 'center',
+ margin: 4,
+ },
+ float: {
+ borderRadius: 9,
+ alignSelf: 'center',
+ fontSize: 10,
+ elevation: 5,
+ position: 'absolute',
+ bottom: 24,
+ },
clearAddIdBtnBg: {
backgroundColor: Colors.Transparent,
},
radius: {
- flex: 1,
borderRadius: 10,
- backgroundColor: Colors.Orange,
+ backgroundColor: Colors.Purple,
},
}),
OIDCAuthStyles: StyleSheet.create({
@@ -348,14 +645,35 @@ export const PurpleTheme = {
padding: 32,
},
}),
+ QRCodeOverlay: StyleSheet.create({
+ header: {},
+ }),
SelectVcOverlayStyles: StyleSheet.create({
overlay: {
elevation: 5,
backgroundColor: Colors.White,
padding: 0,
},
+ consentCheckContainer: {
+ backgroundColor: Colors.White,
+ borderWidth: 0,
+ marginTop: -15,
+ fontFamily: 'Inter_600SemiBold',
+ padding: 0,
+ },
+ timeoutHintContainer: {
+ backgroundColor: Colors.TimeoutHintBoxColor,
+ margin: 21,
+ paddingHorizontal: 14,
+ paddingVertical: 12,
+ borderRadius: 12,
+ },
+ sharedSuccessfully: {
+ flex: 1,
+ backgroundColor: Colors.White,
+ },
}),
- CreditsStyles: StyleSheet.create({
+ AppMetaDataStyles: StyleSheet.create({
buttonContainer: {
position: 'absolute',
left: 0,
@@ -365,9 +683,23 @@ export const PurpleTheme = {
flex: 1,
width: Dimensions.get('screen').width,
},
- markdownView: {
+ contentView: {
+ flex: 1,
padding: 20,
},
+ header: {
+ fontSize: 20,
+ fontWeight: 'normal',
+ color: 'rgb(28,28,30)',
+ },
+ }),
+ FooterStyles: StyleSheet.create({
+ bottom: {
+ justifyContent: 'flex-end',
+ backgroundColor: Colors.Grey6,
+ borderRadius: 15,
+ padding: 10,
+ },
}),
ModalStyles: StyleSheet.create({
modal: {
@@ -408,11 +740,51 @@ export const PurpleTheme = {
height: Dimensions.get('screen').height,
},
}),
+ KebabPopUpStyles: StyleSheet.create({
+ kebabPopUp: {
+ borderTopLeftRadius: 15,
+ borderTopRightRadius: 15,
+ width: Dimensions.get('screen').width,
+ marginTop: Dimensions.get('screen').height * 0.55,
+ },
+ kebabHeaderStyle: {
+ justifyContent: 'space-between',
+ fontFamily: 'Inter_700Bold',
+ paddingRight: 15,
+ paddingLeft: 130,
+ paddingTop: 18,
+ },
+ }),
MessageOverlayStyles: StyleSheet.create({
+ overlay: {
+ elevation: 5,
+ backgroundColor: Colors.White,
+ padding: 5,
+ borderRadius: 10,
+ },
+ buttonContainer: {
+ justifyContent: 'center',
+ marginBottom: 75,
+ },
+ popupOverLay: {
+ height: 150,
+ backgroundColor: Colors.White,
+ },
+ button: {
+ borderTopLeftRadius: 0,
+ borderTopRightRadius: 0,
+ },
+ halfButton: {
+ borderRadius: 8,
+ margin: '0.5%',
+ },
+ }),
+ BindingVcWarningOverlay: StyleSheet.create({
overlay: {
elevation: 5,
backgroundColor: Colors.White,
padding: 0,
+ borderRadius: 15,
},
button: {
borderTopLeftRadius: 0,
@@ -488,7 +860,7 @@ export const PurpleTheme = {
position: 'absolute',
top: 32,
right: 0,
- color: Colors.Orange,
+ color: Colors.Purple,
},
}),
MessageStyles: StyleSheet.create({
@@ -545,8 +917,8 @@ export const PurpleTheme = {
overlay: {
padding: 24,
bottom: 86,
- backgroundColor: Colors.Transparent,
- shadowColor: Colors.Transparent,
+ backgroundColor: 'transparent',
+ shadowColor: 'transparent',
},
slide: {
width: '100%',
@@ -563,7 +935,7 @@ export const PurpleTheme = {
sliderTitle: {
color: Colors.White,
marginBottom: 20,
- fontFamily: 'Poppins_700Bold',
+ fontFamily: 'Inter_700Bold',
},
text: {
color: Colors.White,
@@ -583,17 +955,12 @@ export const PurpleTheme = {
top: 40,
zIndex: 1,
},
- }),
- BindingVcWarningOverlay: StyleSheet.create({
- overlay: {
- elevation: 5,
- backgroundColor: Colors.White,
- padding: 0,
- borderRadius: 15,
- },
- button: {
- borderTopLeftRadius: 0,
- borderTopRightRadius: 0,
+ bottomContainer: {
+ padding: 20,
+ borderTopLeftRadius: 30,
+ borderTopRightRadius: 30,
+ marginTop: -185,
+ paddingBottom: 100,
},
}),
claimsContainer: StyleSheet.create({
@@ -601,13 +968,31 @@ export const PurpleTheme = {
backgroundColor: Colors.Transparent,
},
}),
- OpenCard: require('../../../purpleAassets/bg_cart_one.png'),
- CloseCard: require('../../../purpleAassets/cart_unsel.png'),
- ProfileIcon: require('../../../purpleAassets/profile_icon_unsel.png'),
- MosipLogo: require('../../../purpleAassets/logo.png'),
+ OpenCard: '',
+ CloseCard: '',
+ ProfileIcon: require('../../../purpleAssets/profile_icon.png'),
+ MosipSplashLogo: require('../../../assets/icon.png'),
+ MosipLogo: require('../../../assets/mosip-logo.png'),
+ CameraFlipIcon: require('../../../assets/camera-flip-icon.png'),
+ DomainWarningLogo: require('../../../assets/domain-warning.png'),
WarningLogo: require('../../../assets/warningLogo.png'),
- OtpLogo: require('../../../assets/otp-mobile-logo.png'),
+ OtpLogo: require('../../../purpleAssets/otp-mobile-logo.png'),
SuccessLogo: require('../../../assets/success-logo.png'),
+ ReceiveCardIcon: require('../../../assets/receive-card-icon.png'),
+ ReceivedCardsIcon: require('../../../assets/received-cards-icon.png'),
+ DigitalIdentityLogo: require('../../../assets/digital-identity-icon.png'),
+ InjiLogoWhite: require('../../../assets/inji-logo-white.png'),
+ InjiProgressingLogo: require('../../../assets/progressing-logo.png'),
+ LockIcon: require('../../../assets/lock-icon.png'),
+ InjiHomeLogo: require('../../../assets/inji-home-logo.png'),
+ MagnifierZoom: require('../../../assets/magnifier-zoom.png'),
+ HelpIcon: require('../../../assets/help-icon.png'),
+ sharingIntro: require('../../../assets/Secure-Sharing.png'),
+ walletIntro: require('../../../assets/intro-wallet-binding.png'),
+ IntroScanner: require('../../../assets/intro-scanner.png'),
+ injiSmallLogo: require('../../../assets/inji_small_logo.png'),
+ protectPrivacy: require('../../../assets/phone_mockup_1.png'),
+
elevation(level: ElevationLevel): ViewStyle {
// https://ethercreative.github.io/react-native-shadow-generator/
diff --git a/i18n.ts b/i18n.ts
index 94ef1f72..c84fec2c 100644
--- a/i18n.ts
+++ b/i18n.ts
@@ -8,17 +8,24 @@ import ar from './locales/ara.json';
import hi from './locales/hin.json';
import kn from './locales/kan.json';
import ta from './locales/tam.json';
-import AsyncStorage from '@react-native-async-storage/async-storage';
+import Storage from './shared/storage';
+
+import { iso6393To1 } from 'iso-639-3';
+import { LocalizedField } from './types/vc';
+
+import { APPLICATION_LANGUAGE } from 'react-native-dotenv';
const resources = { en, fil, ar, hi, kn, ta };
+const languageCodeMap = {};
+
export const SUPPORTED_LANGUAGES = {
en: 'English',
fil: 'Filipino',
ar: 'عربى',
- hi: 'Hindi',
- kn: 'Kannada',
- ta: 'Tamil',
+ hi: 'हिंदी',
+ kn: 'ಕನ್ನಡ',
+ ta: 'தமிழ்',
};
i18next
@@ -31,15 +38,67 @@ i18next
supportedLngs: Object.keys(SUPPORTED_LANGUAGES),
})
.then(async () => {
- const language = await AsyncStorage.getItem('language');
+ const language = await Storage.getItem('language');
if (language !== i18next.language) {
i18next.changeLanguage(language);
+ populateLanguageCodeMap();
+ }
+ if (!Object.keys(SUPPORTED_LANGUAGES).includes(i18next.language)) {
+ i18next.changeLanguage('en');
+ populateLanguageCodeMap();
}
});
export default i18next;
-function getLanguageCode(code: string) {
+export function getLanguageCode(code: string) {
const [language] = code.split('-');
return language;
}
+
+export function getVCDetailsForCurrentLanguage(locales) {
+ const currentLanguage = i18next.language;
+ const vcDetailsForCurrentLanguage = locales.filter(
+ (obj) => obj.language === languageCodeMap[currentLanguage]
+ );
+ return vcDetailsForCurrentLanguage[0]?.value
+ ? vcDetailsForCurrentLanguage[0].value
+ : locales[0]?.value;
+}
+
+// This method gets the value from iso-639-3 package, which contains key value pairs of three letter language codes[key] and two letter langugae code[value]. These values are according to iso standards.
+// The response received from the server is three letter language code and the value in the inji code base is two letter language code. Hence the conversion is done.
+function getThreeLetterLanguageCode(twoLetterLanguageCode) {
+ return Object.keys(iso6393To1).find(
+ (key) => iso6393To1[key] === twoLetterLanguageCode
+ );
+}
+
+function populateLanguageCodeMap() {
+ const supportedLanguages = Object.keys(SUPPORTED_LANGUAGES);
+ supportedLanguages.forEach((languageCode) => {
+ let threeLetterLanguageCode = languageCode;
+
+ if (isTwoLetterLanguageCode(languageCode)) {
+ threeLetterLanguageCode = getThreeLetterLanguageCode(languageCode);
+ }
+ languageCodeMap[languageCode] = threeLetterLanguageCode;
+ });
+}
+
+export function getLocalizedField(rawField: string | LocalizedField[]) {
+ if (typeof rawField === 'string') {
+ return rawField;
+ }
+ try {
+ const locales: LocalizedField[] = JSON.parse(JSON.stringify(rawField));
+ if (locales.length == 1) return locales[0]?.value;
+ return getVCDetailsForCurrentLanguage(locales);
+ } catch (e) {
+ return '';
+ }
+}
+
+function isTwoLetterLanguageCode(languageCode) {
+ return languageCode.length == 2;
+}
diff --git a/ios/Gemfile b/ios/Gemfile
new file mode 100644
index 00000000..7a118b49
--- /dev/null
+++ b/ios/Gemfile
@@ -0,0 +1,3 @@
+source "https://rubygems.org"
+
+gem "fastlane"
diff --git a/ios/Gemfile.lock b/ios/Gemfile.lock
new file mode 100644
index 00000000..fbfb0079
--- /dev/null
+++ b/ios/Gemfile.lock
@@ -0,0 +1,218 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ CFPropertyList (3.0.6)
+ rexml
+ addressable (2.8.4)
+ public_suffix (>= 2.0.2, < 6.0)
+ artifactory (3.0.15)
+ atomos (0.1.3)
+ aws-eventstream (1.2.0)
+ aws-partitions (1.765.0)
+ aws-sdk-core (3.172.0)
+ aws-eventstream (~> 1, >= 1.0.2)
+ aws-partitions (~> 1, >= 1.651.0)
+ aws-sigv4 (~> 1.5)
+ jmespath (~> 1, >= 1.6.1)
+ aws-sdk-kms (1.64.0)
+ aws-sdk-core (~> 3, >= 3.165.0)
+ aws-sigv4 (~> 1.1)
+ aws-sdk-s3 (1.122.0)
+ aws-sdk-core (~> 3, >= 3.165.0)
+ aws-sdk-kms (~> 1)
+ aws-sigv4 (~> 1.4)
+ aws-sigv4 (1.5.2)
+ aws-eventstream (~> 1, >= 1.0.2)
+ babosa (1.0.4)
+ claide (1.1.0)
+ colored (1.2)
+ colored2 (3.1.2)
+ commander (4.6.0)
+ highline (~> 2.0.0)
+ declarative (0.0.20)
+ digest-crc (0.6.4)
+ rake (>= 12.0.0, < 14.0.0)
+ domain_name (0.5.20190701)
+ unf (>= 0.0.5, < 1.0.0)
+ dotenv (2.8.1)
+ emoji_regex (3.2.3)
+ excon (0.99.0)
+ faraday (1.10.3)
+ faraday-em_http (~> 1.0)
+ faraday-em_synchrony (~> 1.0)
+ faraday-excon (~> 1.1)
+ faraday-httpclient (~> 1.0)
+ faraday-multipart (~> 1.0)
+ faraday-net_http (~> 1.0)
+ faraday-net_http_persistent (~> 1.0)
+ faraday-patron (~> 1.0)
+ faraday-rack (~> 1.0)
+ faraday-retry (~> 1.0)
+ ruby2_keywords (>= 0.0.4)
+ faraday-cookie_jar (0.0.7)
+ faraday (>= 0.8.0)
+ http-cookie (~> 1.0.0)
+ faraday-em_http (1.0.0)
+ faraday-em_synchrony (1.0.0)
+ faraday-excon (1.1.0)
+ faraday-httpclient (1.0.1)
+ faraday-multipart (1.0.4)
+ multipart-post (~> 2)
+ faraday-net_http (1.0.1)
+ faraday-net_http_persistent (1.2.0)
+ faraday-patron (1.0.0)
+ faraday-rack (1.0.0)
+ faraday-retry (1.0.3)
+ faraday_middleware (1.2.0)
+ faraday (~> 1.0)
+ fastimage (2.2.6)
+ fastlane (2.212.2)
+ CFPropertyList (>= 2.3, < 4.0.0)
+ addressable (>= 2.8, < 3.0.0)
+ artifactory (~> 3.0)
+ aws-sdk-s3 (~> 1.0)
+ babosa (>= 1.0.3, < 2.0.0)
+ bundler (>= 1.12.0, < 3.0.0)
+ colored
+ commander (~> 4.6)
+ dotenv (>= 2.1.1, < 3.0.0)
+ emoji_regex (>= 0.1, < 4.0)
+ excon (>= 0.71.0, < 1.0.0)
+ faraday (~> 1.0)
+ faraday-cookie_jar (~> 0.0.6)
+ faraday_middleware (~> 1.0)
+ fastimage (>= 2.1.0, < 3.0.0)
+ gh_inspector (>= 1.1.2, < 2.0.0)
+ google-apis-androidpublisher_v3 (~> 0.3)
+ google-apis-playcustomapp_v1 (~> 0.1)
+ google-cloud-storage (~> 1.31)
+ highline (~> 2.0)
+ json (< 3.0.0)
+ jwt (>= 2.1.0, < 3)
+ mini_magick (>= 4.9.4, < 5.0.0)
+ multipart-post (~> 2.0.0)
+ naturally (~> 2.2)
+ optparse (~> 0.1.1)
+ plist (>= 3.1.0, < 4.0.0)
+ rubyzip (>= 2.0.0, < 3.0.0)
+ security (= 0.1.3)
+ simctl (~> 1.6.3)
+ terminal-notifier (>= 2.0.0, < 3.0.0)
+ terminal-table (>= 1.4.5, < 2.0.0)
+ tty-screen (>= 0.6.3, < 1.0.0)
+ tty-spinner (>= 0.8.0, < 1.0.0)
+ word_wrap (~> 1.0.0)
+ xcodeproj (>= 1.13.0, < 2.0.0)
+ xcpretty (~> 0.3.0)
+ xcpretty-travis-formatter (>= 0.0.3)
+ gh_inspector (1.1.3)
+ google-apis-androidpublisher_v3 (0.42.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-core (0.11.0)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (>= 0.16.2, < 2.a)
+ httpclient (>= 2.8.1, < 3.a)
+ mini_mime (~> 1.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.a)
+ rexml
+ webrick
+ google-apis-iamcredentials_v1 (0.17.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-playcustomapp_v1 (0.13.0)
+ google-apis-core (>= 0.11.0, < 2.a)
+ google-apis-storage_v1 (0.19.0)
+ google-apis-core (>= 0.9.0, < 2.a)
+ google-cloud-core (1.6.0)
+ google-cloud-env (~> 1.0)
+ google-cloud-errors (~> 1.0)
+ google-cloud-env (1.6.0)
+ faraday (>= 0.17.3, < 3.0)
+ google-cloud-errors (1.3.1)
+ google-cloud-storage (1.44.0)
+ addressable (~> 2.8)
+ digest-crc (~> 0.4)
+ google-apis-iamcredentials_v1 (~> 0.1)
+ google-apis-storage_v1 (~> 0.19.0)
+ google-cloud-core (~> 1.6)
+ googleauth (>= 0.16.2, < 2.a)
+ mini_mime (~> 1.0)
+ googleauth (1.5.2)
+ faraday (>= 0.17.3, < 3.a)
+ jwt (>= 1.4, < 3.0)
+ memoist (~> 0.16)
+ multi_json (~> 1.11)
+ os (>= 0.9, < 2.0)
+ signet (>= 0.16, < 2.a)
+ highline (2.0.3)
+ http-cookie (1.0.5)
+ domain_name (~> 0.5)
+ httpclient (2.8.3)
+ jmespath (1.6.2)
+ json (2.6.3)
+ jwt (2.7.0)
+ memoist (0.16.2)
+ mini_magick (4.12.0)
+ mini_mime (1.1.2)
+ multi_json (1.15.0)
+ multipart-post (2.0.0)
+ nanaimo (0.3.0)
+ naturally (2.2.1)
+ optparse (0.1.1)
+ os (1.1.4)
+ plist (3.7.0)
+ public_suffix (5.0.1)
+ rake (13.0.6)
+ representable (3.2.0)
+ declarative (< 0.1.0)
+ trailblazer-option (>= 0.1.1, < 0.2.0)
+ uber (< 0.2.0)
+ retriable (3.1.2)
+ rexml (3.2.5)
+ rouge (2.0.7)
+ ruby2_keywords (0.0.5)
+ rubyzip (2.3.2)
+ security (0.1.3)
+ signet (0.17.0)
+ addressable (~> 2.8)
+ faraday (>= 0.17.5, < 3.a)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
+ simctl (1.6.10)
+ CFPropertyList
+ naturally
+ terminal-notifier (2.0.0)
+ terminal-table (1.8.0)
+ unicode-display_width (~> 1.1, >= 1.1.1)
+ trailblazer-option (0.1.2)
+ tty-cursor (0.7.1)
+ tty-screen (0.8.1)
+ tty-spinner (0.9.3)
+ tty-cursor (~> 0.7)
+ uber (0.1.0)
+ unf (0.1.4)
+ unf_ext
+ unf_ext (0.0.8.2)
+ unicode-display_width (1.8.0)
+ webrick (1.8.1)
+ word_wrap (1.0.0)
+ xcodeproj (1.22.0)
+ CFPropertyList (>= 2.3.3, < 4.0)
+ atomos (~> 0.1.3)
+ claide (>= 1.0.2, < 2.0)
+ colored2 (~> 3.1)
+ nanaimo (~> 0.3.0)
+ rexml (~> 3.2.4)
+ xcpretty (0.3.0)
+ rouge (~> 2.0.7)
+ xcpretty-travis-formatter (1.0.1)
+ xcpretty (~> 0.2, >= 0.0.7)
+
+PLATFORMS
+ arm64-darwin-22
+
+DEPENDENCIES
+ fastlane
+
+BUNDLED WITH
+ 2.4.12
diff --git a/ios/MOSIPResidentApp.xcodeproj/project.pbxproj b/ios/Inji.xcodeproj/project.pbxproj
similarity index 76%
rename from ios/MOSIPResidentApp.xcodeproj/project.pbxproj
rename to ios/Inji.xcodeproj/project.pbxproj
index 302502ba..fe67c80c 100644
--- a/ios/MOSIPResidentApp.xcodeproj/project.pbxproj
+++ b/ios/Inji.xcodeproj/project.pbxproj
@@ -12,28 +12,28 @@
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
510157BBABB44471B56F17BD /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB20D6FD6E0431BB5A6B1BF /* noop-file.swift */; };
- 96905EF65AED1B983A6B3ABC /* libPods-MOSIPResidentApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-MOSIPResidentApp.a */; };
+ 6EC198FEB3D4CE20C451C9C8 /* libPods-Inji.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F7F3091673D4A20E778B48BF /* libPods-Inji.a */; };
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; };
- 13B07F961A680F5B00A75B9A /* MOSIPResidentApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MOSIPResidentApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = MOSIPResidentApp/AppDelegate.h; sourceTree = ""; };
- 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = MOSIPResidentApp/AppDelegate.m; sourceTree = ""; };
- 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = MOSIPResidentApp/Images.xcassets; sourceTree = ""; };
- 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = MOSIPResidentApp/Info.plist; sourceTree = ""; };
- 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = MOSIPResidentApp/main.m; sourceTree = ""; };
- 3AB20D6FD6E0431BB5A6B1BF /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "MOSIPResidentApp/noop-file.swift"; sourceTree = ""; };
- 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-MOSIPResidentApp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MOSIPResidentApp.a"; sourceTree = BUILT_PRODUCTS_DIR; };
- 6C2E3173556A471DD304B334 /* Pods-MOSIPResidentApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MOSIPResidentApp.debug.xcconfig"; path = "Target Support Files/Pods-MOSIPResidentApp/Pods-MOSIPResidentApp.debug.xcconfig"; sourceTree = ""; };
- 7A4D352CD337FB3A3BF06240 /* Pods-MOSIPResidentApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MOSIPResidentApp.release.xcconfig"; path = "Target Support Files/Pods-MOSIPResidentApp/Pods-MOSIPResidentApp.release.xcconfig"; sourceTree = ""; };
- AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = MOSIPResidentApp/SplashScreen.storyboard; sourceTree = ""; };
+ 13B07F961A680F5B00A75B9A /* Inji.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Inji.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Inji/AppDelegate.h; sourceTree = ""; };
+ 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Inji/AppDelegate.m; sourceTree = ""; };
+ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Inji/Images.xcassets; sourceTree = ""; };
+ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Inji/Info.plist; sourceTree = ""; };
+ 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Inji/main.m; sourceTree = ""; };
+ 3AB20D6FD6E0431BB5A6B1BF /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "Inji/noop-file.swift"; sourceTree = ""; };
+ AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = Inji/SplashScreen.storyboard; sourceTree = ""; };
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = ""; };
- EBEDDC56BF724D17A326B9EC /* MOSIPResidentApp-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "MOSIPResidentApp-Bridging-Header.h"; path = "MOSIPResidentApp/MOSIPResidentApp-Bridging-Header.h"; sourceTree = ""; };
+ EBEDDC56BF724D17A326B9EC /* Inji-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "Inji-Bridging-Header.h"; path = "Inji/Inji-Bridging-Header.h"; sourceTree = ""; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
- FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-MOSIPResidentApp/ExpoModulesProvider.swift"; sourceTree = ""; };
+ F4401A7A527915991104FE89 /* Pods-Inji.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Inji.release.xcconfig"; path = "Target Support Files/Pods-Inji/Pods-Inji.release.xcconfig"; sourceTree = ""; };
+ F7F3091673D4A20E778B48BF /* libPods-Inji.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Inji.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ F842436D5AA4BFDC9B080787 /* Pods-Inji.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Inji.debug.xcconfig"; path = "Target Support Files/Pods-Inji/Pods-Inji.debug.xcconfig"; sourceTree = ""; };
+ FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Inji/ExpoModulesProvider.swift"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -41,14 +41,14 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 96905EF65AED1B983A6B3ABC /* libPods-MOSIPResidentApp.a in Frameworks */,
+ 6EC198FEB3D4CE20C451C9C8 /* libPods-Inji.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- 13B07FAE1A68108700A75B9A /* MOSIPResidentApp */ = {
+ 13B07FAE1A68108700A75B9A /* Inji */ = {
isa = PBXGroup;
children = (
BB2F792B24A3F905000567C9 /* Supporting */,
@@ -60,16 +60,16 @@
13B07FB71A68108700A75B9A /* main.m */,
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
3AB20D6FD6E0431BB5A6B1BF /* noop-file.swift */,
- EBEDDC56BF724D17A326B9EC /* MOSIPResidentApp-Bridging-Header.h */,
+ EBEDDC56BF724D17A326B9EC /* Inji-Bridging-Header.h */,
);
- name = MOSIPResidentApp;
+ name = Inji;
sourceTree = "";
};
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup;
children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
- 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-MOSIPResidentApp.a */,
+ F7F3091673D4A20E778B48BF /* libPods-Inji.a */,
);
name = Frameworks;
sourceTree = "";
@@ -84,7 +84,7 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
- 13B07FAE1A68108700A75B9A /* MOSIPResidentApp */,
+ 13B07FAE1A68108700A75B9A /* Inji */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
@@ -99,17 +99,17 @@
83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup;
children = (
- 13B07F961A680F5B00A75B9A /* MOSIPResidentApp.app */,
+ 13B07F961A680F5B00A75B9A /* Inji.app */,
);
name = Products;
sourceTree = "";
};
- 92DBD88DE9BF7D494EA9DA96 /* MOSIPResidentApp */ = {
+ 92DBD88DE9BF7D494EA9DA96 /* Inji */ = {
isa = PBXGroup;
children = (
FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */,
);
- name = MOSIPResidentApp;
+ name = Inji;
sourceTree = "";
};
BB2F792B24A3F905000567C9 /* Supporting */ = {
@@ -118,14 +118,14 @@
BB2F792C24A3F905000567C9 /* Expo.plist */,
);
name = Supporting;
- path = MOSIPResidentApp/Supporting;
+ path = Inji/Supporting;
sourceTree = "";
};
D65327D7A22EEC0BE12398D9 /* Pods */ = {
isa = PBXGroup;
children = (
- 6C2E3173556A471DD304B334 /* Pods-MOSIPResidentApp.debug.xcconfig */,
- 7A4D352CD337FB3A3BF06240 /* Pods-MOSIPResidentApp.release.xcconfig */,
+ F842436D5AA4BFDC9B080787 /* Pods-Inji.debug.xcconfig */,
+ F4401A7A527915991104FE89 /* Pods-Inji.release.xcconfig */,
);
path = Pods;
sourceTree = "";
@@ -133,7 +133,7 @@
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = {
isa = PBXGroup;
children = (
- 92DBD88DE9BF7D494EA9DA96 /* MOSIPResidentApp */,
+ 92DBD88DE9BF7D494EA9DA96 /* Inji */,
);
name = ExpoModulesProviders;
sourceTree = "";
@@ -141,25 +141,25 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
- 13B07F861A680F5B00A75B9A /* MOSIPResidentApp */ = {
+ 13B07F861A680F5B00A75B9A /* Inji */ = {
isa = PBXNativeTarget;
- buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "MOSIPResidentApp" */;
+ buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Inji" */;
buildPhases = (
- 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
+ 5C9927E01935CFEBE538B2C3 /* [CP] Check Pods Manifest.lock */,
FD10A7F022414F080027D42C /* Start Packager */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
- 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
+ 8DF8339253592BA8967F2133 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
- name = MOSIPResidentApp;
- productName = MOSIPResidentApp;
- productReference = 13B07F961A680F5B00A75B9A /* MOSIPResidentApp.app */;
+ name = Inji;
+ productName = Inji;
+ productReference = 13B07F961A680F5B00A75B9A /* Inji.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -171,12 +171,13 @@
LastUpgradeCheck = 1340;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
- DevelopmentTeam = 9L83VVTX8B;
+ DevelopmentTeam = F7JDUR6578;
LastSwiftMigration = 1250;
+ ProvisioningStyle = Automatic;
};
};
};
- buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "MOSIPResidentApp" */;
+ buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Inji" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
@@ -189,7 +190,7 @@
projectDirPath = "";
projectRoot = "";
targets = (
- 13B07F861A680F5B00A75B9A /* MOSIPResidentApp */,
+ 13B07F861A680F5B00A75B9A /* Inji */,
);
};
/* End PBXProject section */
@@ -222,7 +223,7 @@
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\n`node --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n";
};
- 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = {
+ 5C9927E01935CFEBE538B2C3 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -237,14 +238,14 @@
outputFileListPaths = (
);
outputPaths = (
- "$(DERIVED_FILE_DIR)/Pods-MOSIPResidentApp-checkManifestLockResult.txt",
+ "$(DERIVED_FILE_DIR)/Pods-Inji-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
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;
};
- 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = {
+ 8DF8339253592BA8967F2133 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -256,7 +257,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MOSIPResidentApp/Pods-MOSIPResidentApp-resources.sh\"\n";
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Inji/Pods-Inji-resources.sh\"\n";
showEnvVarsInLog = 0;
};
FD10A7F022414F080027D42C /* Start Packager */ = {
@@ -297,30 +298,34 @@
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-MOSIPResidentApp.debug.xcconfig */;
+ baseConfigurationReference = F842436D5AA4BFDC9B080787 /* Pods-Inji.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CODE_SIGN_ENTITLEMENTS = MOSIPResidentApp/MOSIPResidentApp.entitlements;
+ CODE_SIGN_ENTITLEMENTS = Inji/Inji.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 8;
- DEVELOPMENT_TEAM = 9L83VVTX8B;
+ DEVELOPMENT_TEAM = F7JDUR6578;
ENABLE_BITCODE = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"FB_SONARKIT_ENABLED=1",
);
- INFOPLIST_FILE = MOSIPResidentApp/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ INFOPLIST_FILE = Inji/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = Inji;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- MARKETING_VERSION = 0.4.1;
+ MARKETING_VERSION = 0.9.1;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-lc++",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.newlogic.inji;
- PRODUCT_NAME = MOSIPResidentApp;
- SWIFT_OBJC_BRIDGING_HEADER = "MOSIPResidentApp/MOSIPResidentApp-Bridging-Header.h";
+ PRODUCT_BUNDLE_IDENTIFIER = io.mosip.inji.mobileid;
+ PRODUCT_NAME = Inji;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OBJC_BRIDGING_HEADER = "Inji/Inji-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -330,25 +335,32 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-MOSIPResidentApp.release.xcconfig */;
+ baseConfigurationReference = F4401A7A527915991104FE89 /* Pods-Inji.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CODE_SIGN_ENTITLEMENTS = MOSIPResidentApp/MOSIPResidentApp.entitlements;
+ CODE_SIGN_ENTITLEMENTS = Inji/Inji.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
+ CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 8;
- DEVELOPMENT_TEAM = 9L83VVTX8B;
- INFOPLIST_FILE = MOSIPResidentApp/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ DEVELOPMENT_TEAM = "";
+ "DEVELOPMENT_TEAM[sdk=iphoneos*]" = LD7H4CQ5P9;
+ INFOPLIST_FILE = Inji/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = Inji;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- MARKETING_VERSION = 0.4.1;
+ MARKETING_VERSION = 0.9.1;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-lc++",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.newlogic.inji;
- PRODUCT_NAME = MOSIPResidentApp;
- SWIFT_OBJC_BRIDGING_HEADER = "MOSIPResidentApp/MOSIPResidentApp-Bridging-Header.h";
+ PRODUCT_BUNDLE_IDENTIFIER = io.mosip.inji.mobileid;
+ PRODUCT_NAME = Inji;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.mosip.inji.mobileid";
+ SWIFT_OBJC_BRIDGING_HEADER = "Inji/Inji-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
@@ -384,7 +396,7 @@
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_ENTITLEMENTS = MOSIPResidentApp/MOSIPResidentApp.entitlements;
+ CODE_SIGN_ENTITLEMENTS = Inji/Inji.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -405,7 +417,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
LIBRARY_SEARCH_PATHS = "\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = YES;
@@ -443,7 +455,7 @@
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_ENTITLEMENTS = MOSIPResidentApp/MOSIPResidentApp.entitlements;
+ CODE_SIGN_ENTITLEMENTS = Inji/Inji.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
@@ -457,7 +469,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
LIBRARY_SEARCH_PATHS = "\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = NO;
@@ -470,7 +482,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
- 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "MOSIPResidentApp" */ = {
+ 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Inji" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */,
@@ -479,7 +491,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "MOSIPResidentApp" */ = {
+ 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Inji" */ = {
isa = XCConfigurationList;
buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */,
diff --git a/ios/MOSIPResidentApp.xcodeproj/xcshareddata/xcschemes/MOSIPResidentApp.xcscheme b/ios/Inji.xcodeproj/xcshareddata/xcschemes/Inji.xcscheme
similarity index 80%
rename from ios/MOSIPResidentApp.xcodeproj/xcshareddata/xcschemes/MOSIPResidentApp.xcscheme
rename to ios/Inji.xcodeproj/xcshareddata/xcschemes/Inji.xcscheme
index 0a5c8596..34fa8d40 100644
--- a/ios/MOSIPResidentApp.xcodeproj/xcshareddata/xcschemes/MOSIPResidentApp.xcscheme
+++ b/ios/Inji.xcodeproj/xcshareddata/xcschemes/Inji.xcscheme
@@ -15,9 +15,9 @@
+ BuildableName = "Inji.app"
+ BlueprintName = "Inji"
+ ReferencedContainer = "container:Inji.xcodeproj">
@@ -33,9 +33,9 @@
+ BuildableName = "InjiTests.xctest"
+ BlueprintName = "InjiTests"
+ ReferencedContainer = "container:Inji.xcodeproj">
@@ -55,9 +55,9 @@
+ BuildableName = "Inji.app"
+ BlueprintName = "Inji"
+ ReferencedContainer = "container:Inji.xcodeproj">
@@ -79,9 +79,9 @@
+ BuildableName = "Inji.app"
+ BlueprintName = "Inji"
+ ReferencedContainer = "container:Inji.xcodeproj">
diff --git a/ios/MOSIPResidentApp.xcworkspace/contents.xcworkspacedata b/ios/Inji.xcworkspace/contents.xcworkspacedata
similarity index 77%
rename from ios/MOSIPResidentApp.xcworkspace/contents.xcworkspacedata
rename to ios/Inji.xcworkspace/contents.xcworkspacedata
index 60f5b43e..3a406aad 100644
--- a/ios/MOSIPResidentApp.xcworkspace/contents.xcworkspacedata
+++ b/ios/Inji.xcworkspace/contents.xcworkspacedata
@@ -2,7 +2,7 @@
+ location = "group:Inji.xcodeproj">
diff --git a/ios/MOSIPResidentApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Inji.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 100%
rename from ios/MOSIPResidentApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to ios/Inji.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
diff --git a/ios/MOSIPResidentApp/AppDelegate.h b/ios/Inji/AppDelegate.h
similarity index 100%
rename from ios/MOSIPResidentApp/AppDelegate.h
rename to ios/Inji/AppDelegate.h
diff --git a/ios/MOSIPResidentApp/AppDelegate.m b/ios/Inji/AppDelegate.m
similarity index 100%
rename from ios/MOSIPResidentApp/AppDelegate.m
rename to ios/Inji/AppDelegate.m
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/Inji/Images.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/Contents.json
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/Contents.json
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-1024@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-1024@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-1024@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-1024@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-20@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-20@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-20@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-20@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-20@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-20@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-20@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-20@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-20@3x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-20@3x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-20@3x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-20@3x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-29@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-29@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-29@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-29@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-29@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-29@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-29@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-29@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-29@3x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-29@3x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-29@3x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-29@3x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-40@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-40@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-40@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-40@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-40@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-40@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-40@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-40@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-40@3x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-40@3x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-40@3x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-40@3x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-50@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-50@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-50@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-50@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-50@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-50@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-50@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-50@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-57@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-57@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-57@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-57@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-57@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-57@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-57@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-57@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-60@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-60@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-60@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-60@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-60@3x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-60@3x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-60@3x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-60@3x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-72@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-72@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-72@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-72@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-72@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-72@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-72@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-72@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-76@1x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-76@1x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-76@1x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-76@1x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-76@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-76@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-76@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-76@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/ios/Inji/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png
rename to ios/Inji/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png
diff --git a/ios/MOSIPResidentApp/Images.xcassets/Contents.json b/ios/Inji/Images.xcassets/Contents.json
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/Contents.json
rename to ios/Inji/Images.xcassets/Contents.json
diff --git a/ios/Inji/Images.xcassets/SplashScreen.imageset/Contents.json b/ios/Inji/Images.xcassets/SplashScreen.imageset/Contents.json
new file mode 100644
index 00000000..2c0dd9b9
--- /dev/null
+++ b/ios/Inji/Images.xcassets/SplashScreen.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "splash.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "splash@2x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "splash@3x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Inji/Images.xcassets/SplashScreen.imageset/splash.png b/ios/Inji/Images.xcassets/SplashScreen.imageset/splash.png
new file mode 100644
index 00000000..b3c779cd
Binary files /dev/null and b/ios/Inji/Images.xcassets/SplashScreen.imageset/splash.png differ
diff --git a/ios/Inji/Images.xcassets/SplashScreen.imageset/splash@2x.png b/ios/Inji/Images.xcassets/SplashScreen.imageset/splash@2x.png
new file mode 100644
index 00000000..f0bc985d
Binary files /dev/null and b/ios/Inji/Images.xcassets/SplashScreen.imageset/splash@2x.png differ
diff --git a/ios/Inji/Images.xcassets/SplashScreen.imageset/splash@3x.png b/ios/Inji/Images.xcassets/SplashScreen.imageset/splash@3x.png
new file mode 100644
index 00000000..8b9628b1
Binary files /dev/null and b/ios/Inji/Images.xcassets/SplashScreen.imageset/splash@3x.png differ
diff --git a/ios/MOSIPResidentApp/Images.xcassets/SplashScreen.imageset/Contents.json b/ios/Inji/Images.xcassets/SplashScreenBackground.imageset/Contents.json
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/SplashScreen.imageset/Contents.json
rename to ios/Inji/Images.xcassets/SplashScreenBackground.imageset/Contents.json
diff --git a/ios/MOSIPResidentApp/Images.xcassets/SplashScreenBackground.imageset/image.png b/ios/Inji/Images.xcassets/SplashScreenBackground.imageset/image.png
similarity index 100%
rename from ios/MOSIPResidentApp/Images.xcassets/SplashScreenBackground.imageset/image.png
rename to ios/Inji/Images.xcassets/SplashScreenBackground.imageset/image.png
diff --git a/ios/MOSIPResidentApp/Info.plist b/ios/Inji/Info.plist
similarity index 89%
rename from ios/MOSIPResidentApp/Info.plist
rename to ios/Inji/Info.plist
index 470b5ed0..5346677c 100644
--- a/ios/MOSIPResidentApp/Info.plist
+++ b/ios/Inji/Info.plist
@@ -5,7 +5,7 @@
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
- MOSIP Resident App
+ Inji
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
@@ -30,7 +30,9 @@
CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
+ 5
+ ITSAppUsesNonExemptEncryption
+
LSRequiresIPhoneOS
NSAppTransportSecurity
@@ -54,6 +56,10 @@
Allow $(PRODUCT_NAME) to access your camera
NSFaceIDUsageDescription
Resident app can be unlocked using Face ID
+ NSLocationAlwaysAndWhenInUseUsageDescription
+ Allow $(PRODUCT_NAME) to access your location
+ NSLocationWhenInUseUsageDescription
+ Allow $(PRODUCT_NAME) to access your location
NSMicrophoneUsageDescription
Allow $(PRODUCT_NAME) to access your microphone
UILaunchStoryboardName
diff --git a/ios/MOSIPResidentApp/MOSIPResidentApp-Bridging-Header.h b/ios/Inji/Inji-Bridging-Header.h
similarity index 100%
rename from ios/MOSIPResidentApp/MOSIPResidentApp-Bridging-Header.h
rename to ios/Inji/Inji-Bridging-Header.h
diff --git a/ios/MOSIPResidentApp/MOSIPResidentApp.entitlements b/ios/Inji/Inji.entitlements
similarity index 100%
rename from ios/MOSIPResidentApp/MOSIPResidentApp.entitlements
rename to ios/Inji/Inji.entitlements
diff --git a/ios/MOSIPResidentApp/SplashScreen.storyboard b/ios/Inji/SplashScreen.storyboard
similarity index 82%
rename from ios/MOSIPResidentApp/SplashScreen.storyboard
rename to ios/Inji/SplashScreen.storyboard
index d209ca66..a0a61fca 100644
--- a/ios/MOSIPResidentApp/SplashScreen.storyboard
+++ b/ios/Inji/SplashScreen.storyboard
@@ -1,13 +1,15 @@
-
+
-
+
+
+
@@ -18,22 +20,22 @@
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
@@ -42,7 +44,10 @@
+
-
+
+
+
-
\ No newline at end of file
+
diff --git a/ios/MOSIPResidentApp/Supporting/Expo.plist b/ios/Inji/Supporting/Expo.plist
similarity index 100%
rename from ios/MOSIPResidentApp/Supporting/Expo.plist
rename to ios/Inji/Supporting/Expo.plist
diff --git a/ios/MOSIPResidentApp/main.m b/ios/Inji/main.m
similarity index 100%
rename from ios/MOSIPResidentApp/main.m
rename to ios/Inji/main.m
diff --git a/ios/MOSIPResidentApp/noop-file.swift b/ios/Inji/noop-file.swift
similarity index 100%
rename from ios/MOSIPResidentApp/noop-file.swift
rename to ios/Inji/noop-file.swift
diff --git a/ios/MOSIPResidentApp/Images.xcassets/SplashScreen.imageset/image.png b/ios/MOSIPResidentApp/Images.xcassets/SplashScreen.imageset/image.png
deleted file mode 100644
index 0eaf9d5a..00000000
Binary files a/ios/MOSIPResidentApp/Images.xcassets/SplashScreen.imageset/image.png and /dev/null differ
diff --git a/ios/MOSIPResidentApp/Images.xcassets/SplashScreenBackground.imageset/Contents.json b/ios/MOSIPResidentApp/Images.xcassets/SplashScreenBackground.imageset/Contents.json
deleted file mode 100644
index 3cf84897..00000000
--- a/ios/MOSIPResidentApp/Images.xcassets/SplashScreenBackground.imageset/Contents.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "images": [
- {
- "idiom": "universal",
- "filename": "image.png",
- "scale": "1x"
- },
- {
- "idiom": "universal",
- "scale": "2x"
- },
- {
- "idiom": "universal",
- "scale": "3x"
- }
- ],
- "info": {
- "version": 1,
- "author": "expo"
- }
-}
\ No newline at end of file
diff --git a/ios/Podfile b/ios/Podfile
index eda8886b..88612c2c 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -9,7 +9,7 @@ platform :ios, '13.0'
require 'json'
podfile_properties = JSON.parse(File.read('./Podfile.properties.json')) rescue {}
-target 'MOSIPResidentApp' do
+target 'Inji' do
use_expo_modules!
post_integrate do |installer|
begin
@@ -55,9 +55,28 @@ target 'MOSIPResidentApp' do
end
end
target.build_configurations.each do |config|
- config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0'
+ config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
+ # get team-id from project's first target
+ dev_team = ""
+ project = installer.aggregate_targets[0].user_project
+ project.targets.each do |target|
+ target.build_configurations.each do |config|
+ if dev_team.empty? and !config.build_settings['DEVELOPMENT_TEAM'].nil?
+ dev_team = config.build_settings['DEVELOPMENT_TEAM']
+ break
+ end
+ end
+ end
+
+ # Apply team-id
+ installer.pods_project.targets.each do |target|
+ target.build_configurations.each do |config|
+ config.build_settings["DEVELOPMENT_TEAM"] = dev_team
+ end
+ end
+
end
permissions_path = '../node_modules/react-native-permissions/ios'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index eaae254f..ca3fdbf7 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,5 +1,9 @@
PODS:
- boost-for-react-native (1.63.0)
+ - BVLinearGradient (2.6.2):
+ - React-Core
+ - CatCrypto (0.3.2)
+ - CrcSwift (0.0.3)
- DoubleConversion (1.1.6)
- EXApplication (4.0.2):
- ExpoModulesCore
@@ -12,8 +16,6 @@ PODS:
- ExpoModulesCore
- EXConstants (13.0.2):
- ExpoModulesCore
- - EXErrorRecovery (3.0.5):
- - ExpoModulesCore
- EXFileSystem (13.1.4):
- ExpoModulesCore
- EXFont (10.0.5):
@@ -62,7 +64,11 @@ PODS:
- GoogleSymbolUtilities (1.1.2)
- GoogleUtilitiesLegacy (1.3.2):
- GoogleSymbolUtilities (~> 1.1)
- - mosip-inji-face-sdk (0.1.7):
+ - GzipSwift (5.1.1)
+ - MMKV (1.2.13):
+ - MMKVCore (~> 1.2.13)
+ - MMKVCore (1.2.16)
+ - mosip-inji-face-sdk (0.1.12):
- React-Core
- NearbyMessages (1.1.1):
- GoogleInterchangeUtilities (~> 1.2)
@@ -270,12 +276,27 @@ PODS:
- React-jsi (= 0.64.4)
- React-perflogger (= 0.64.4)
- React-jsinspector (0.64.4)
+ - react-native-location (2.5.0):
+ - React
+ - react-native-mmkv-storage (0.8.0):
+ - MMKV (= 1.2.13)
+ - React-Core
- react-native-netinfo (7.1.3):
- React-Core
- react-native-restart (0.0.24):
- React-Core
+ - react-native-rsa-native (2.0.5):
+ - React
- react-native-safe-area-context (3.3.2):
- React-Core
+ - react-native-secure-key-store (2.0.10):
+ - React-Core
+ - react-native-secure-keystore (0.1.0):
+ - React-Core
+ - react-native-tuvali (0.4.3):
+ - CrcSwift (~> 0.0.3)
+ - GzipSwift
+ - React-Core
- React-perflogger (0.64.4)
- React-RCTActionSheet (0.64.4):
- React-Core/RCTActionSheetHeaders (= 0.64.4)
@@ -340,9 +361,12 @@ PODS:
- React-cxxreact (= 0.64.4)
- React-jsi (= 0.64.4)
- React-perflogger (= 0.64.4)
+ - RNArgon2 (2.0.1):
+ - CatCrypto
+ - React-Core
- RNBluetoothStateManager (1.3.4):
- React-Core
- - RNCAsyncStorage (1.15.17):
+ - RNCClipboard (1.11.2):
- React-Core
- RNCPicker (2.2.1):
- React-Core
@@ -376,12 +400,12 @@ PODS:
- ZXingObjC/Core
DEPENDENCIES:
+ - BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- EXApplication (from `../node_modules/expo-application/ios`)
- EXBarCodeScanner (from `../node_modules/expo-barcode-scanner/ios`)
- EXCamera (from `../node_modules/expo-camera/ios`)
- EXConstants (from `../node_modules/expo-constants/ios`)
- - EXErrorRecovery (from `../node_modules/expo-error-recovery/ios`)
- EXFileSystem (from `../node_modules/expo-file-system/ios`)
- EXFont (from `../node_modules/expo-font/ios`)
- EXImageLoader (from `../node_modules/expo-image-loader/ios`)
@@ -417,9 +441,15 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
+ - react-native-location (from `../node_modules/react-native-location`)
+ - react-native-mmkv-storage (from `../node_modules/react-native-mmkv-storage`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-restart (from `../node_modules/react-native-restart`)
+ - react-native-rsa-native (from `../node_modules/react-native-rsa-native`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
+ - react-native-secure-key-store (from `../node_modules/react-native-secure-key-store`)
+ - react-native-secure-keystore (from `../node_modules/react-native-secure-keystore`)
+ - react-native-tuvali (from `../node_modules/react-native-tuvali`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
@@ -432,8 +462,9 @@ DEPENDENCIES:
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
+ - RNArgon2 (from `../node_modules/react-native-argon2`)
- RNBluetoothStateManager (from `../node_modules/react-native-bluetooth-state-manager`)
- - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
+ - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
- "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFS (from `../node_modules/react-native-fs`)
@@ -450,14 +481,21 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- boost-for-react-native
+ - CatCrypto
+ - CrcSwift
- GoogleInterchangeUtilities
- GoogleNetworkingUtilities
- GoogleSymbolUtilities
- GoogleUtilitiesLegacy
+ - GzipSwift
+ - MMKV
+ - MMKVCore
- NearbyMessages
- ZXingObjC
EXTERNAL SOURCES:
+ BVLinearGradient:
+ :path: "../node_modules/react-native-linear-gradient"
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
EXApplication:
@@ -468,8 +506,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-camera/ios"
EXConstants:
:path: "../node_modules/expo-constants/ios"
- EXErrorRecovery:
- :path: "../node_modules/expo-error-recovery/ios"
EXFileSystem:
:path: "../node_modules/expo-file-system/ios"
EXFont:
@@ -536,12 +572,24 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
+ react-native-location:
+ :path: "../node_modules/react-native-location"
+ react-native-mmkv-storage:
+ :path: "../node_modules/react-native-mmkv-storage"
react-native-netinfo:
:path: "../node_modules/@react-native-community/netinfo"
react-native-restart:
:path: "../node_modules/react-native-restart"
+ react-native-rsa-native:
+ :path: "../node_modules/react-native-rsa-native"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
+ react-native-secure-key-store:
+ :path: "../node_modules/react-native-secure-key-store"
+ react-native-secure-keystore:
+ :path: "../node_modules/react-native-secure-keystore"
+ react-native-tuvali:
+ :path: "../node_modules/react-native-tuvali"
React-perflogger:
:path: "../node_modules/react-native/ReactCommon/reactperflogger"
React-RCTActionSheet:
@@ -566,10 +614,12 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
+ RNArgon2:
+ :path: "../node_modules/react-native-argon2"
RNBluetoothStateManager:
:path: "../node_modules/react-native-bluetooth-state-manager"
- RNCAsyncStorage:
- :path: "../node_modules/@react-native-async-storage/async-storage"
+ RNCClipboard:
+ :path: "../node_modules/@react-native-clipboard/clipboard"
RNCPicker:
:path: "../node_modules/@react-native-picker/picker"
RNDeviceInfo:
@@ -597,12 +647,14 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
+ BVLinearGradient: 34a999fda29036898a09c6a6b728b0b4189e1a44
+ CatCrypto: a477899b6be4954e75be4897e732da098cc0a5a8
+ CrcSwift: f85dea6b41dddb5f98bb3743fd777ce58b77bc2e
DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
EXApplication: 54fe5bd6268d697771645e8f1aef8b806a65247a
EXBarCodeScanner: e5ca0062d8ad1c4c1d2e386d6a308d5a32213020
EXCamera: 4a0d00d6d1e4703c31a75514d8bc804a2eab27bd
EXConstants: 88bf79622fbd9b476c96d8ec57fe97ca44fe8e3c
- EXErrorRecovery: b0d7582714a2cc896e94a2308a356f94dbf14ef7
EXFileSystem: 08a3033ac372b6346becf07839e1ccef26fb1058
EXFont: 2597c10ac85a69d348d44d7873eccf5a7576ef5e
EXImageLoader: 347b72c2ec2df65120ccec40ea65a4c4f24317ff
@@ -618,13 +670,16 @@ SPEC CHECKSUMS:
EXUpdates: a83e036243b0f6ece53a8c1cb883b6751c88a5f8
EXUpdatesInterface: a9814f422d3cd6e7cfd260d13c27786148ece20e
FBLazyVector: fa8275d5086566e22a26ddc385ab5772e7f9b1bd
- FBReactNativeSpec: c3dafd68550f3c95f009beee5c20ab07949ec4e4
+ FBReactNativeSpec: c74a4bea62abb8c7b5a2c27314a28bcf35d7cf9e
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
GoogleInterchangeUtilities: d5bc4d88d5b661ab72f9d70c58d02ca8c27ad1f7
GoogleNetworkingUtilities: 3edd3a8161347494f2da60ea0deddc8a472d94cb
GoogleSymbolUtilities: 631ee17048aa5e9ab133470d768ea997a5ef9b96
GoogleUtilitiesLegacy: 5501bedec1646bd284286eb5fc9453f7e23a12f4
- mosip-inji-face-sdk: a1355473a393f2cdd6d927c51af4363be6d97d9f
+ GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa
+ MMKV: aac95d817a100479445633f2b3ed8961b4ac5043
+ MMKVCore: 9cfef4c48c6c46f66226fc2e4634d78490206a48
+ mosip-inji-face-sdk: d5bc0fb66721c25450f92d3297efcb2cf0117271
NearbyMessages: bd9e88f2df7fbab78be58fed58580d5d5bd62cbf
Permission-BluetoothPeripheral: 67708853584bb9208c76d36d0e0ea4eafb97ea5b
Permission-Camera: bf6791b17c7f614b6826019fcfdcc286d3a107f6
@@ -641,9 +696,15 @@ SPEC CHECKSUMS:
React-jsi: 64f80675a66899bf0f4a58b8e3908966fa516234
React-jsiexecutor: 8c077bef1c64430b6034f27df1000d194551e2eb
React-jsinspector: d4f6973dd474357dbaaf6f52f31ffc713bf3e766
+ react-native-location: 5a40ec1cc6abf2f6d94df979f98ec76c3a415681
+ react-native-mmkv-storage: 8ba3c0216a6df283ece11205b442a3e435aec4e5
react-native-netinfo: 42c0965fca99069b92e3f7360ab2d425985e5104
react-native-restart: 45c8dca02491980f2958595333cbccd6877cb57e
+ react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
react-native-safe-area-context: 584dc04881deb49474363f3be89e4ca0e854c057
+ react-native-secure-key-store: 910e6df6bc33cb790aba6ee24bc7818df1fe5898
+ react-native-secure-keystore: 3ba6b598e4c3716de1e95cf90dc5b99eed8f0795
+ react-native-tuvali: cf1b72f6ad8ec7694caab7ceb5e5386815c2fbcf
React-perflogger: 5a890ca0911669421b7611661e9b58f91c805f5c
React-RCTActionSheet: bd180e0879f8424a73650c5c28fbef4f3b5b27fb
React-RCTAnimation: 1004d2b4be1f2cedfdc4cb2326adc95b989e6c6b
@@ -656,8 +717,9 @@ SPEC CHECKSUMS:
React-RCTVibration: 761849eea2a1abc99d5e4171bae17ab3da3143ac
React-runtimeexecutor: 5b441857030bb6c3abaa7517f333cb01875ae499
ReactCommon: b4a65d2d6e9eeffd4b32dde1245962b3f43907d0
+ RNArgon2: 1481820722fd4af1575c09f7fc9ad67c00ee8a42
RNBluetoothStateManager: ae6a26260cbdf1827b58bd3bcc563527d61e6488
- RNCAsyncStorage: 6bd5a7ba3dde1c3facba418aa273f449bdc5437a
+ RNCClipboard: 3f0451a8100393908bea5c5c5b16f96d45f30bfc
RNCPicker: cb57c823d5ce8d2d0b5dfb45ad97b737260dc59e
RNDeviceInfo: aad3c663b25752a52bf8fce93f2354001dd185aa
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
@@ -672,6 +734,6 @@ SPEC CHECKSUMS:
Yoga: d1fc3575b8b68891ff5ef3c276daa855e841eb32
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
-PODFILE CHECKSUM: aca728a65db3db54edf138095b290280c97a5389
+PODFILE CHECKSUM: e8bdbcbb2053c9b2971c35e1aafa6988c4dadeab
-COCOAPODS: 1.11.3
+COCOAPODS: 1.12.1
diff --git a/ios/fastlane/Appfile b/ios/fastlane/Appfile
new file mode 100644
index 00000000..de847afe
--- /dev/null
+++ b/ios/fastlane/Appfile
@@ -0,0 +1,5 @@
+app_identifier(ENV["INJI_IOS_DEVELOPER_APP_IDENTIFIER"]) # The bundle identifier of your app
+apple_id(ENV["IOS_FASTLANE_APPLE_ID"]) # Your Apple Developer Portal username
+
+itc_team_id(ENV["APP_STORE_CONNECT_TEAM_ID"]) # App Store Connect Team ID
+team_id(ENV["INJI_IOS_DEVELOPER_PORTAL_TEAM_ID"]) # Developer Portal Team ID
diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile
new file mode 100644
index 00000000..8749a477
--- /dev/null
+++ b/ios/fastlane/Fastfile
@@ -0,0 +1,160 @@
+xcode_select '/Applications/Xcode_14.2.app'
+
+default_platform(:ios)
+APP_STORE_CONNECT_TEAM_ID = ENV["APP_STORE_CONNECT_TEAM_ID"]
+APPLE_ISSUER_ID = ENV["APPLE_ISSUER_ID"]
+APPLE_KEY_CONTENT = ENV["APPLE_KEY_CONTENT"]
+APPLE_KEY_ID = ENV["APPLE_KEY_ID"]
+DEVELOPER_APP_IDENTIFIER = ENV["INJI_IOS_DEVELOPER_APP_IDENTIFIER"]
+TEAM_ID = ENV["INJI_IOS_DEVELOPER_PORTAL_TEAM_ID"]
+FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD = ENV["INJI_IOS_FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"]
+FASTLANE_USER= ENV["IOS_FASTLANE_APPLE_ID"]
+PROVISIONING_PROFILE_SPECIFIER = ENV["INJI_IOS_PROVISIONING_PROFILE_SPECIFIER"]
+TEMP_KEYCHAIN_USER = ENV["INJI_IOS_TEMP_KEYCHAIN_USER"]
+TEMP_KEYCHAIN_PASSWORD = ENV["INJI_IOS_TEMP_KEYCHAIN_PASSWORD"]
+GIT_AUTHORIZATION = ENV["GIT_AUTHORIZATION"]
+SLACK_URL = ENV["SLACK_URL"]
+MATCH_PASSWORD = ENV["MATCH_PASSWORD"]
+FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT = "120"
+TESTFLIGHT_INTERNAL_TESTERS_GROUP = ENV["TESTFLIGHT_INTERNAL_TESTERS_GROUP"]
+TESTFLIGHT_BETA_APP_DESCRIPTION = ENV["TESTFLIGHT_BETA_APP_DESCRIPTION"]
+DEVELOPER_APP_ID = ENV["DEVELOPER_APP_ID"]
+
+def delete_temp_keychain(name)
+ delete_keychain(
+ name: name
+ ) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
+end
+
+def create_temp_keychain(name, password)
+ create_keychain(
+ name: name,
+ password: password,
+ unlock: false,
+ timeout: 3600
+ )
+end
+
+def ensure_temp_keychain(name, password)
+ delete_temp_keychain(name)
+ create_temp_keychain(name, password)
+end
+
+
+platform :ios do
+
+ lane :beta do
+ keychain_name = TEMP_KEYCHAIN_USER
+ keychain_password = TEMP_KEYCHAIN_PASSWORD
+ ensure_temp_keychain(keychain_name, keychain_password)
+
+ api_key = app_store_connect_api_key(
+ key_id: "#{APPLE_KEY_ID}",
+ issuer_id: "#{APPLE_ISSUER_ID}",
+ key_content: "#{APPLE_KEY_CONTENT}",
+ duration: 1200,
+ in_house: false,
+ is_key_content_base64: true
+ )
+
+ version = get_version_number(xcodeproj: "Inji.xcodeproj")
+
+ previous_build_number = latest_testflight_build_number(
+ app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
+ api_key: api_key,
+ version: version
+ )
+
+ current_build_number = previous_build_number + 1
+
+ increment_build_number(
+ xcodeproj: "Inji.xcodeproj",
+ build_number: current_build_number
+ )
+
+ match(
+ type: 'appstore',
+ app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
+ git_basic_authorization: Base64.strict_encode64("#{GIT_AUTHORIZATION}"),
+ readonly: false,
+ keychain_name: keychain_name,
+ keychain_password: keychain_password,
+ api_key: api_key
+ )
+
+ profile_mapping = Actions.lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING]
+
+ gym(
+ configuration: "Release",
+ workspace: "Inji.xcworkspace",
+ scheme: "Inji",
+ export_method: "app-store",
+
+ export_options: {
+ provisioningProfiles: {
+ "#{DEVELOPER_APP_ID}" => "#{PROVISIONING_PROFILE_SPECIFIER}"
+ }
+ }
+ )
+
+ pilot(
+ app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
+ api_key: api_key,
+ ipa: "./Inji.ipa",
+ changelog: "#{TESTFLIGHT_BETA_APP_DESCRIPTION}",
+ localized_build_info: {
+ "default": {
+ whats_new: "#{TESTFLIGHT_BETA_APP_DESCRIPTION}",
+ }
+ },
+ skip_waiting_for_build_processing: false,
+ distribute_external: true,
+ submit_beta_review: false,
+ groups: ["#{TESTFLIGHT_INTERNAL_TESTERS_GROUP}"],
+ )
+
+ delete_temp_keychain(keychain_name)
+
+ slack(
+ message: "Inji - #{version} (#{current_build_number}) is uploaded to testflight.",
+ success: true,
+ slack_url: "#{SLACK_URL}",
+ default_payloads: [:git_branch, :last_git_commit]
+ )
+ end
+
+ lane :build_verify do
+ keychain_name = TEMP_KEYCHAIN_USER
+ keychain_password = TEMP_KEYCHAIN_PASSWORD
+ ensure_temp_keychain(keychain_name, keychain_password)
+
+ api_key = app_store_connect_api_key(
+ key_id: "#{APPLE_KEY_ID}",
+ issuer_id: "#{APPLE_ISSUER_ID}",
+ key_content: "#{APPLE_KEY_CONTENT}",
+ duration: 1200,
+ in_house: false,
+ is_key_content_base64: true
+ )
+
+ match(
+ type: 'appstore',
+ app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
+ git_basic_authorization: Base64.strict_encode64("#{GIT_AUTHORIZATION}"),
+ readonly: false,
+ keychain_name: keychain_name,
+ keychain_password: keychain_password,
+ api_key: api_key
+ )
+
+ gym(
+ configuration: "Release",
+ workspace: "Inji.xcworkspace",
+ scheme: "Inji",
+ export_method: "app-store",
+ )
+
+ delete_temp_keychain(keychain_name)
+
+ end
+end
\ No newline at end of file
diff --git a/ios/fastlane/Matchfile b/ios/fastlane/Matchfile
new file mode 100644
index 00000000..6b294b46
--- /dev/null
+++ b/ios/fastlane/Matchfile
@@ -0,0 +1,5 @@
+git_url("https://github.com/mosip/inji-ios-priv")
+storage_mode("git")
+
+type("appstore") # The default type, can be: appstore, adhoc, enterprise or development
+
diff --git a/lib/date-fns/locale/_lib/buildFormatLongFn/index.ts b/lib/date-fns/locale/_lib/buildFormatLongFn/index.ts
deleted file mode 100644
index 3c512ab2..00000000
--- a/lib/date-fns/locale/_lib/buildFormatLongFn/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { FormatLongFn, FormatLongWidth } from '../../types';
-
-export interface BuildFormatLongFnArgs<
- DefaultMatchWidth extends FormatLongWidth
-> {
- formats: Partial<{ [format in FormatLongWidth]: string }> & {
- [format in DefaultMatchWidth]: string;
- };
- defaultWidth: DefaultMatchWidth;
-}
-
-export default function buildFormatLongFn<
- DefaultMatchWidth extends FormatLongWidth
->(args: BuildFormatLongFnArgs): FormatLongFn {
- return (options = {}) => {
- // TODO: Remove String()
- const width = options.width
- ? (String(options.width) as FormatLongWidth)
- : args.defaultWidth;
- const format = args.formats[width] || args.formats[args.defaultWidth];
- return format;
- };
-}
diff --git a/lib/date-fns/locale/_lib/buildLocalizeFn/index.ts b/lib/date-fns/locale/_lib/buildLocalizeFn/index.ts
deleted file mode 100644
index 517b2830..00000000
--- a/lib/date-fns/locale/_lib/buildLocalizeFn/index.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-import type { Era, Quarter, Month, Day } from '../../../types';
-import type {
- LocaleDayPeriod,
- LocalePatternWidth,
- LocaleUnit,
- LocalizeFn,
- LocalizeUnitIndex,
-} from '../../types';
-
-type LocalizeEraValues = readonly [string, string];
-
-type LocalizeQuarterValues = readonly [string, string, string, string];
-
-type LocalizeDayValues = readonly [
- string,
- string,
- string,
- string,
- string,
- string,
- string
-];
-
-type LocalizeMonthValues = readonly [
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string,
- string
-];
-
-export type LocalizeUnitValuesIndex> =
- Values extends Record
- ? string
- : Values extends LocalizeEraValues
- ? Era
- : Values extends LocalizeQuarterValues
- ? Quarter
- : Values extends LocalizeDayValues
- ? Day
- : Values extends LocalizeMonthValues
- ? Month
- : never;
-
-export type LocalizeUnitValues =
- Unit extends LocaleDayPeriod
- ? Record
- : Unit extends Era
- ? LocalizeEraValues
- : Unit extends Quarter
- ? LocalizeQuarterValues
- : Unit extends Day
- ? LocalizeDayValues
- : Unit extends Month
- ? LocalizeMonthValues
- : never;
-
-export type LocalizePeriodValuesMap = {
- [pattern in LocalePatternWidth]?: LocalizeUnitValues;
-};
-
-export type BuildLocalizeFnArgCallback = (
- value: Result
-) => LocalizeUnitIndex;
-
-export type BuildLocalizeFnArgs<
- Result extends LocaleUnit,
- ArgCallback extends BuildLocalizeFnArgCallback | undefined
-> = {
- values: LocalizePeriodValuesMap;
- defaultWidth: LocalePatternWidth;
- formattingValues?: LocalizePeriodValuesMap;
- defaultFormattingWidth?: LocalePatternWidth;
-} & (ArgCallback extends undefined
- ? { argumentCallback?: undefined }
- : { argumentCallback: BuildLocalizeFnArgCallback });
-
-export default function buildLocalizeFn<
- Result extends LocaleUnit,
- ArgCallback extends BuildLocalizeFnArgCallback | undefined
->(
- args: BuildLocalizeFnArgs
-): LocalizeFn {
- return (dirtyIndex, dirtyOptions) => {
- const options = dirtyOptions || {};
-
- const context = options.context ? String(options.context) : 'standalone';
-
- let valuesArray: LocalizeUnitValues;
- if (context === 'formatting' && args.formattingValues) {
- const defaultWidth = args.defaultFormattingWidth || args.defaultWidth;
- const width = (
- options.width ? String(options.width) : defaultWidth
- ) as LocalePatternWidth;
- valuesArray = (args.formattingValues[width] ||
- args.formattingValues[defaultWidth]) as LocalizeUnitValues;
- } else {
- const defaultWidth = args.defaultWidth;
- const width = (
- options.width ? String(options.width) : args.defaultWidth
- ) as LocalePatternWidth;
- valuesArray = (args.values[width] ||
- args.values[defaultWidth]) as LocalizeUnitValues;
- }
- const index = (
- args.argumentCallback
- ? args.argumentCallback(dirtyIndex as Result)
- : (dirtyIndex as LocalizeUnitIndex as unknown)
- ) as LocalizeUnitValuesIndex;
- // @ts-ignore: For some reason TypeScript just don't want to match it, no matter how hard we try. I challenge you to try to remove it!
- return valuesArray[index];
- };
-}
diff --git a/lib/date-fns/locale/_lib/buildMatchFn/index.ts b/lib/date-fns/locale/_lib/buildMatchFn/index.ts
deleted file mode 100644
index 25f89ba0..00000000
--- a/lib/date-fns/locale/_lib/buildMatchFn/index.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import type {
- BuildMatchFnArgs,
- LocaleDayPeriod,
- LocaleUnit,
- LocalePatternWidth,
- MatchFn,
-} from '../../types';
-
-export default function buildMatchFn<
- Result extends LocaleUnit,
- DefaultMatchWidth extends LocalePatternWidth,
- DefaultParseWidth extends LocalePatternWidth
->(
- args: BuildMatchFnArgs
-): MatchFn {
- return (string, options = {}) => {
- const width = options.width;
-
- const matchPattern =
- (width && args.matchPatterns[width]) ||
- args.matchPatterns[args.defaultMatchWidth];
- const matchResult = string.match(matchPattern);
-
- if (!matchResult) {
- return null;
- }
- const matchedString = matchResult[0];
-
- const parsePatterns =
- (width && args.parsePatterns[width]) ||
- args.parsePatterns[args.defaultParseWidth];
-
- const key = (
- Array.isArray(parsePatterns)
- ? findIndex(parsePatterns, (pattern) => pattern.test(matchedString))
- : findKey(parsePatterns, (pattern: any) => pattern.test(matchedString))
- ) as Result extends LocaleDayPeriod ? string : number;
-
- let value: Result;
-
- value = (args.valueCallback ? args.valueCallback(key) : key) as Result;
- value = options.valueCallback ? options.valueCallback(value) : value;
-
- const rest = string.slice(matchedString.length);
-
- return { value, rest };
- };
-}
-
-function findKey(
- object: Obj,
- predicate: (value: Value) => boolean
-): keyof Obj | undefined {
- for (const key in object) {
- if (object.hasOwnProperty(key) && predicate(object[key])) {
- return key;
- }
- }
- return undefined;
-}
-
-function findIndex- (
- array: Item[],
- predicate: (item: Item) => boolean
-): number | undefined {
- for (let key = 0; key < array.length; key++) {
- if (predicate(array[key])) {
- return key;
- }
- }
- return undefined;
-}
diff --git a/lib/date-fns/locale/_lib/buildMatchPatternFn/index.ts b/lib/date-fns/locale/_lib/buildMatchPatternFn/index.ts
deleted file mode 100644
index 88b6b2f6..00000000
--- a/lib/date-fns/locale/_lib/buildMatchPatternFn/index.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { MatchFn, MatchValueCallback } from '../../types';
-
-export interface BuildMatchPatternFnArgs {
- matchPattern: RegExp;
- parsePattern: RegExp;
- valueCallback?: MatchValueCallback;
-}
-
-export default function buildMatchPatternFn(
- args: BuildMatchPatternFnArgs
-): MatchFn {
- return (string, options = {}) => {
- const matchResult = string.match(args.matchPattern);
- if (!matchResult) return null;
- const matchedString = matchResult[0];
-
- const parseResult = string.match(args.parsePattern);
- if (!parseResult) return null;
- let value = (
- args.valueCallback ? args.valueCallback(parseResult[0]) : parseResult[0]
- ) as Result;
- value = options.valueCallback ? options.valueCallback(value) : value;
-
- const rest = string.slice(matchedString.length);
-
- return { value, rest };
- };
-}
diff --git a/lib/date-fns/locale/fil/_lib/formatDistance/index.ts b/lib/date-fns/locale/fil/_lib/formatDistance/index.ts
deleted file mode 100644
index 5aad7e16..00000000
--- a/lib/date-fns/locale/fil/_lib/formatDistance/index.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import type { FormatDistanceFn, FormatDistanceLocale } from '../../../types';
-
-type FormatDistanceTokenValue =
- | string
- | {
- one: string;
- other: string;
- };
-
-const formatDistanceLocale: FormatDistanceLocale = {
- lessThanXSeconds: {
- one: 'wala pang isang segundo',
- other: 'wala pang {{count}} na segundo',
- },
-
- xSeconds: {
- one: 'isang segundo',
- other: '{{count}} segundo',
- },
-
- halfAMinute: 'kalahating minuto',
-
- lessThanXMinutes: {
- one: 'wala pang isang minuto',
- other: 'wala pang {{count}} na minuto',
- },
-
- xMinutes: {
- one: 'isang minuto',
- other: '{{count}} minuto',
- },
-
- aboutXHours: {
- one: 'mga isang oras',
- other: 'mga {{count}} na oras',
- },
-
- xHours: {
- one: 'isang oras',
- other: '{{count}} na oras',
- },
-
- xDays: {
- one: 'isang araw',
- other: '{{count}} na araw',
- },
-
- aboutXWeeks: {
- one: 'mga isang linggo',
- other: 'mga {{count}} na linggo',
- },
-
- xWeeks: {
- one: 'isang linggo',
- other: '{{count}} na linggo',
- },
-
- aboutXMonths: {
- one: 'mga isang buwan',
- other: 'mga {{count}} na buwan',
- },
-
- xMonths: {
- one: 'isang buwan',
- other: '{{count}} na buwan',
- },
-
- aboutXYears: {
- one: 'mga isang taon',
- other: 'mga {{count}} na taon',
- },
-
- xYears: {
- one: 'isang taon',
- other: '{{count}} na taon',
- },
-
- overXYears: {
- one: 'mahigit isang taon',
- other: 'mahigit {{count}} na taon',
- },
-
- almostXYears: {
- one: 'halos isang taon',
- other: 'halos {{count}} na taon',
- },
-};
-
-const formatDistance: FormatDistanceFn = (token, count, options) => {
- let result;
-
- const tokenValue = formatDistanceLocale[token];
- if (typeof tokenValue === 'string') {
- result = tokenValue;
- } else if (count === 1) {
- result = tokenValue.one;
- } else {
- result = tokenValue.other.replace('{{count}}', count.toString());
- }
-
- if (options?.addSuffix) {
- if (options.comparison && options.comparison > 0) {
- return 'sa ' + result;
- } else {
- return result + ' nakaraan';
- }
- }
-
- return result;
-};
-
-export default formatDistance;
diff --git a/lib/date-fns/locale/fil/_lib/formatLong/index.ts b/lib/date-fns/locale/fil/_lib/formatLong/index.ts
deleted file mode 100644
index f4c7fa38..00000000
--- a/lib/date-fns/locale/fil/_lib/formatLong/index.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import buildFormatLongFn from '../../../_lib/buildFormatLongFn/index';
-import type { FormatLong } from '../../../types';
-
-const dateFormats = {
- full: 'EEEE, MMMM do, y',
- long: 'MMMM do, y',
- medium: 'MMM d, y',
- short: 'MM/dd/yyyy',
-};
-
-const timeFormats = {
- full: 'h:mm:ss a zzzz',
- long: 'h:mm:ss a z',
- medium: 'h:mm:ss a',
- short: 'h:mm a',
-};
-
-const dateTimeFormats = {
- full: "{{date}} 'at' {{time}}",
- long: "{{date}} 'at' {{time}}",
- medium: '{{date}}, {{time}}',
- short: '{{date}}, {{time}}',
-};
-
-const formatLong: FormatLong = {
- date: buildFormatLongFn({
- formats: dateFormats,
- defaultWidth: 'full',
- }),
-
- time: buildFormatLongFn({
- formats: timeFormats,
- defaultWidth: 'full',
- }),
-
- dateTime: buildFormatLongFn({
- formats: dateTimeFormats,
- defaultWidth: 'full',
- }),
-};
-
-export default formatLong;
diff --git a/lib/date-fns/locale/fil/_lib/formatRelative/index.ts b/lib/date-fns/locale/fil/_lib/formatRelative/index.ts
deleted file mode 100644
index ae1a32df..00000000
--- a/lib/date-fns/locale/fil/_lib/formatRelative/index.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { FormatRelativeFn } from '../../../types';
-
-const formatRelativeLocale = {
- lastWeek: "'last' eeee 'at' p",
- yesterday: "'yesterday at' p",
- today: "'today at' p",
- tomorrow: "'tomorrow at' p",
- nextWeek: "eeee 'at' p",
- other: 'P',
-};
-
-const formatRelative: FormatRelativeFn = (token, _date, _baseDate, _options) =>
- formatRelativeLocale[token];
-
-export default formatRelative;
diff --git a/lib/date-fns/locale/fil/_lib/localize/index.ts b/lib/date-fns/locale/fil/_lib/localize/index.ts
deleted file mode 100644
index 8754f4ce..00000000
--- a/lib/date-fns/locale/fil/_lib/localize/index.ts
+++ /dev/null
@@ -1,199 +0,0 @@
-import type { Quarter } from '../../../../types';
-import type { Localize, LocalizeFn } from '../../../types';
-import buildLocalizeFn from '../../../_lib/buildLocalizeFn/index';
-
-const eraValues = {
- narrow: ['B', 'A'] as const,
- abbreviated: ['BC', 'AD'] as const,
- wide: ['Before Christ', 'Anno Domini'] as const,
-};
-
-const quarterValues = {
- narrow: ['1', '2', '3', '4'] as const,
- abbreviated: ['Q1', 'Q2', 'Q3', 'Q4'] as const,
- wide: [
- 'Unang sangkapat',
- 'Ikalawang sangkapat',
- 'Ikatlong sangkapat',
- 'Ikaapat sangkapat',
- ] as const,
-};
-
-// Note: in English, the names of days of the week and months are capitalized.
-// If you are making a new locale based on this one, check if the same is true for the language you're working on.
-// Generally, formatted dates should look like they are in the middle of a sentence,
-// e.g. in Spanish language the weekdays and months should be in the lowercase.
-const monthValues = {
- narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'] as const,
- abbreviated: [
- 'Enero',
- 'Peb',
- 'Marso',
- 'Abr',
- 'Mayo',
- 'Hun',
- 'Hul',
- 'Agosto',
- 'Set',
- 'Okt',
- 'Nob',
- 'Dis',
- ] as const,
- wide: [
- 'Enero',
- 'Pebrero',
- 'Marso',
- 'Abril',
- 'Mayo',
- 'Hunyo',
- 'Hulyo',
- 'Agosto',
- 'Setyembre',
- 'Oktubre',
- 'Nobyembre',
- 'Disyembre',
- ] as const,
-};
-
-const dayValues = {
- narrow: ['L', 'L', 'M', 'M', 'H', 'B', 'S'] as const,
- short: ['Li', 'Lu', 'Ma', 'Mi', 'Hu', 'Bi', 'Sa'] as const,
- abbreviated: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'] as const,
- wide: [
- 'Linggo',
- 'Lunes',
- 'Martes',
- 'Miyerkules',
- 'Huwebes',
- 'Biyernes',
- 'Sabado',
- ] as const,
-};
-
-const dayPeriodValues = {
- narrow: {
- am: 'a',
- pm: 'p',
- midnight: 'mi',
- noon: 'n',
- morning: 'umaga',
- afternoon: 'hapon',
- evening: 'gabi',
- night: 'gabi',
- },
- abbreviated: {
- am: 'AM',
- pm: 'PM',
- midnight: 'hatinggabi',
- noon: 'tanghali',
- morning: 'umaga',
- afternoon: 'hapon',
- evening: 'gabi',
- night: 'gabi',
- },
- wide: {
- am: 'a.m.',
- pm: 'p.m.',
- midnight: 'hatinggabi',
- noon: 'tanghali',
- morning: 'umaga',
- afternoon: 'hapon',
- evening: 'gabi',
- night: 'gabi',
- },
-};
-
-const formattingDayPeriodValues = {
- narrow: {
- am: 'a',
- pm: 'p',
- midnight: 'mi',
- noon: 'n',
- morning: 'sa umaga',
- afternoon: 'sa hapon',
- evening: 'sa gabi',
- night: 'sa gabi',
- },
- abbreviated: {
- am: 'AM',
- pm: 'PM',
- midnight: 'midnight',
- noon: 'noon',
- morning: 'sa umaga',
- afternoon: 'sa hapon',
- evening: 'sa gabi',
- night: 'sa gabi',
- },
- wide: {
- am: 'a.m.',
- pm: 'p.m.',
- midnight: 'midnight',
- noon: 'noon',
- morning: 'sa umaga',
- afternoon: 'sa hapon',
- evening: 'sa gabi',
- night: 'sa gabi',
- },
-};
-
-const ordinalNumber: LocalizeFn = (
- dirtyNumber,
- _options
-) => {
- const number = Number(dirtyNumber);
-
- // If ordinal numbers depend on context, for example,
- // if they are different for different grammatical genders,
- // use `options.unit`.
- //
- // `unit` can be 'year', 'quarter', 'month', 'week', 'date', 'dayOfYear',
- // 'day', 'hour', 'minute', 'second'.
-
- // const rem100 = number % 100
- // if (rem100 > 20 || rem100 < 10) {
- // switch (rem100 % 10) {
- // case 1:
- // return number + 'st'
- // case 2:
- // return number + 'nd'
- // case 3:
- // return number + 'rd'
- // }
- // }
-
- return 'ika-' + number;
-};
-
-const localize: Localize = {
- ordinalNumber,
-
- era: buildLocalizeFn({
- values: eraValues,
- defaultWidth: 'wide',
- }),
-
- quarter: buildLocalizeFn({
- values: quarterValues,
- defaultWidth: 'wide',
- argumentCallback: (quarter) => (quarter - 1) as Quarter,
- }),
-
- month: buildLocalizeFn({
- values: monthValues,
- defaultWidth: 'wide',
- }),
-
- day: buildLocalizeFn({
- values: dayValues,
- defaultWidth: 'wide',
- }),
-
- dayPeriod: buildLocalizeFn({
- values: dayPeriodValues,
- defaultWidth: 'wide',
- formattingValues: formattingDayPeriodValues,
- defaultFormattingWidth: 'wide',
- }),
-};
-
-export default localize;
diff --git a/lib/date-fns/locale/fil/_lib/match/index.ts b/lib/date-fns/locale/fil/_lib/match/index.ts
deleted file mode 100644
index bdfeb742..00000000
--- a/lib/date-fns/locale/fil/_lib/match/index.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import type { Quarter } from '../../../../types';
-import type { Match } from '../../../types';
-import buildMatchFn from '../../../_lib/buildMatchFn/index';
-import buildMatchPatternFn from '../../../_lib/buildMatchPatternFn/index';
-
-const matchOrdinalNumberPattern = /^(\d+)(th|st|nd|rd)?/i;
-const parseOrdinalNumberPattern = /\d+/i;
-
-const matchEraPatterns = {
- narrow: /^(b|a)/i,
- abbreviated: /^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,
- wide: /^(before christ|before common era|anno domini|common era)/i,
-};
-const parseEraPatterns = {
- any: [/^b/i, /^(a|c)/i] as const,
-};
-
-const matchQuarterPatterns = {
- narrow: /^[1234]/i,
- abbreviated: /^q[1234]/i,
- wide: /^[1234](th|st|nd|rd)? quarter/i,
-};
-const parseQuarterPatterns = {
- any: [/1/i, /2/i, /3/i, /4/i] as const,
-};
-
-const matchMonthPatterns = {
- narrow: /^[jfmasond]/i,
- abbreviated: /^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,
- wide: /^(january|february|march|april|may|june|july|august|september|october|november|december)/i,
-};
-const parseMonthPatterns = {
- narrow: [
- /^j/i,
- /^f/i,
- /^m/i,
- /^a/i,
- /^m/i,
- /^j/i,
- /^j/i,
- /^a/i,
- /^s/i,
- /^o/i,
- /^n/i,
- /^d/i,
- ] as const,
- any: [
- /^ja/i,
- /^f/i,
- /^mar/i,
- /^ap/i,
- /^may/i,
- /^jun/i,
- /^jul/i,
- /^au/i,
- /^s/i,
- /^o/i,
- /^n/i,
- /^d/i,
- ] as const,
-};
-
-const matchDayPatterns = {
- narrow: /^[smtwf]/i,
- short: /^(su|mo|tu|we|th|fr|sa)/i,
- abbreviated: /^(sun|mon|tue|wed|thu|fri|sat)/i,
- wide: /^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i,
-};
-const parseDayPatterns = {
- narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i] as const,
- any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i] as const,
-};
-
-const matchDayPeriodPatterns = {
- narrow: /^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,
- any: /^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i,
-};
-const parseDayPeriodPatterns = {
- any: {
- am: /^a/i,
- pm: /^p/i,
- midnight: /^mi/i,
- noon: /^no/i,
- morning: /morning/i,
- afternoon: /afternoon/i,
- evening: /evening/i,
- night: /night/i,
- },
-};
-
-const match: Match = {
- ordinalNumber: buildMatchPatternFn({
- matchPattern: matchOrdinalNumberPattern,
- parsePattern: parseOrdinalNumberPattern,
- valueCallback: (value) => parseInt(value, 10),
- }),
-
- era: buildMatchFn({
- matchPatterns: matchEraPatterns,
- defaultMatchWidth: 'wide',
- parsePatterns: parseEraPatterns,
- defaultParseWidth: 'any',
- }),
-
- quarter: buildMatchFn({
- matchPatterns: matchQuarterPatterns,
- defaultMatchWidth: 'wide',
- parsePatterns: parseQuarterPatterns,
- defaultParseWidth: 'any',
- valueCallback: (index) => (index + 1) as Quarter,
- }),
-
- month: buildMatchFn({
- matchPatterns: matchMonthPatterns,
- defaultMatchWidth: 'wide',
- parsePatterns: parseMonthPatterns,
- defaultParseWidth: 'any',
- }),
-
- day: buildMatchFn({
- matchPatterns: matchDayPatterns,
- defaultMatchWidth: 'wide',
- parsePatterns: parseDayPatterns,
- defaultParseWidth: 'any',
- }),
-
- dayPeriod: buildMatchFn({
- matchPatterns: matchDayPeriodPatterns,
- defaultMatchWidth: 'any',
- parsePatterns: parseDayPeriodPatterns,
- defaultParseWidth: 'any',
- }),
-};
-
-export default match;
diff --git a/lib/date-fns/locale/fil/index.d.ts b/lib/date-fns/locale/fil/index.d.ts
deleted file mode 100644
index e3e20b26..00000000
--- a/lib/date-fns/locale/fil/index.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.
-
-import { fil } from 'date-fns/locale';
-export default fil;
diff --git a/lib/date-fns/locale/fil/index.js.flow b/lib/date-fns/locale/fil/index.js.flow
deleted file mode 100644
index b9dfe669..00000000
--- a/lib/date-fns/locale/fil/index.js.flow
+++ /dev/null
@@ -1,35 +0,0 @@
-// @flow
-// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.
-
-export type Locale = {
- code?: string,
- formatDistance?: (...args: Array) => any,
- formatRelative?: (...args: Array) => any,
- localize?: {
- ordinalNumber: (...args: Array) => any,
- era: (...args: Array) => any,
- quarter: (...args: Array) => any,
- month: (...args: Array) => any,
- day: (...args: Array) => any,
- dayPeriod: (...args: Array) => any,
- },
- formatLong?: {
- date: (...args: Array) => any,
- time: (...args: Array) => any,
- dateTime: (...args: Array) => any,
- },
- match?: {
- ordinalNumber: (...args: Array) => any,
- era: (...args: Array) => any,
- quarter: (...args: Array) => any,
- month: (...args: Array) => any,
- day: (...args: Array) => any,
- dayPeriod: (...args: Array) => any,
- },
- options?: {
- weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
- firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
- },
-}
-
-declare module.exports: Locale
diff --git a/lib/date-fns/locale/fil/index.ts b/lib/date-fns/locale/fil/index.ts
deleted file mode 100644
index 0d1a97c7..00000000
--- a/lib/date-fns/locale/fil/index.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import formatDistance from './_lib/formatDistance/index';
-import formatLong from './_lib/formatLong/index';
-import formatRelative from './_lib/formatRelative/index';
-import localize from './_lib/localize/index';
-import match from './_lib/match/index';
-import type { Locale } from '../types';
-
-/**
- * @type {Locale}
- * @category Locales
- * @summary Filipino locale (Philippines)
- * @language Filipino
- * @iso-639-2 fil
- * @author Paolo Miguel de Leon [@pmigueld]{@link https://github.com/pmigueld}
- */
-const locale: Locale = {
- code: 'fil',
- formatDistance: formatDistance,
- formatLong: formatLong,
- formatRelative: formatRelative,
- localize: localize,
- match: match,
- options: {
- weekStartsOn: 0 /* Sunday */,
- firstWeekContainsDate: 1,
- },
-};
-
-export default locale;
diff --git a/lib/date-fns/locale/fil/snapshot.md b/lib/date-fns/locale/fil/snapshot.md
deleted file mode 100644
index c596e77e..00000000
--- a/lib/date-fns/locale/fil/snapshot.md
+++ /dev/null
@@ -1,330 +0,0 @@
-# English (en-US) locale
-
-## `format` and `parse`
-
-| Title | Token string | Date | `format` result | `parse` result |
-| ------------------------------- | ------------ | ------------------------ | ------------------------------------------------------- | ------------------------ |
-| Calendar year | yo | 1987-02-11T12:13:14.015Z | 1987th | 1987-01-01T00:00:00.000Z |
-| | | 0005-01-01T12:13:14.015Z | 5th | 0005-01-01T00:00:00.000Z |
-| Local week-numbering year | Yo | 1987-02-11T12:13:14.015Z | 1987th | 1986-12-28T00:00:00.000Z |
-| | | 0005-01-01T12:13:14.015Z | 5th | 0004-12-26T00:00:00.000Z |
-| Quarter (formatting) | Qo | 2019-01-01T12:13:14.015Z | 1st | 2019-01-01T00:00:00.000Z |
-| | | 2019-04-01T12:13:14.015Z | 2nd | 2019-04-01T00:00:00.000Z |
-| | QQQ | 2019-01-01T12:13:14.015Z | Q1 | 2019-01-01T00:00:00.000Z |
-| | | 2019-04-01T12:13:14.015Z | Q2 | 2019-04-01T00:00:00.000Z |
-| | QQQQ | 2019-01-01T12:13:14.015Z | 1st quarter | 2019-01-01T00:00:00.000Z |
-| | | 2019-04-01T12:13:14.015Z | 2nd quarter | 2019-04-01T00:00:00.000Z |
-| | QQQQQ | 2019-01-01T12:13:14.015Z | 1 | 2019-01-01T00:00:00.000Z |
-| | | 2019-04-01T12:13:14.015Z | 2 | 2019-04-01T00:00:00.000Z |
-| Quarter (stand-alone) | qo | 2019-01-01T12:13:14.015Z | 1st | 2019-01-01T00:00:00.000Z |
-| | | 2019-04-01T12:13:14.015Z | 2nd | 2019-04-01T00:00:00.000Z |
-| | qqq | 2019-01-01T12:13:14.015Z | Q1 | 2019-01-01T00:00:00.000Z |
-| | | 2019-04-01T12:13:14.015Z | Q2 | 2019-04-01T00:00:00.000Z |
-| | qqqq | 2019-01-01T12:13:14.015Z | 1st quarter | 2019-01-01T00:00:00.000Z |
-| | | 2019-04-01T12:13:14.015Z | 2nd quarter | 2019-04-01T00:00:00.000Z |
-| Month (formatting) | Mo | 2019-02-11T12:13:14.015Z | 2nd | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | 7th | 2019-07-01T00:00:00.000Z |
-| | MMM | 2019-02-11T12:13:14.015Z | Feb | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | Jul | 2019-07-01T00:00:00.000Z |
-| | MMMM | 2019-02-11T12:13:14.015Z | February | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | July | 2019-07-01T00:00:00.000Z |
-| | MMMMM | 2019-02-11T12:13:14.015Z | F | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
-| Month (stand-alone) | Lo | 2019-02-11T12:13:14.015Z | 2nd | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | 7th | 2019-07-01T00:00:00.000Z |
-| | LLL | 2019-02-11T12:13:14.015Z | Feb | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | Jul | 2019-07-01T00:00:00.000Z |
-| | LLLL | 2019-02-11T12:13:14.015Z | February | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | July | 2019-07-01T00:00:00.000Z |
-| | LLLLL | 2019-02-11T12:13:14.015Z | F | 2019-02-01T00:00:00.000Z |
-| | | 2019-07-10T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
-| Local week of year | wo | 2019-01-01T12:13:14.015Z | 1st | 2018-12-30T00:00:00.000Z |
-| | | 2019-12-01T12:13:14.015Z | 49th | 2019-12-01T00:00:00.000Z |
-| ISO week of year | Io | 2019-01-01T12:13:14.015Z | 1st | 2018-12-31T00:00:00.000Z |
-| | | 2019-12-01T12:13:14.015Z | 48th | 2019-11-25T00:00:00.000Z |
-| Day of month | do | 2019-02-11T12:13:14.015Z | 11th | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-28T12:13:14.015Z | 28th | 2019-02-28T00:00:00.000Z |
-| Day of year | Do | 2019-02-11T12:13:14.015Z | 42nd | 2019-02-11T00:00:00.000Z |
-| | | 2019-12-31T12:13:14.015Z | 365th | 2019-12-31T00:00:00.000Z |
-| Day of week (formatting) | E | 2019-02-11T12:13:14.015Z | Mon | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fri | 2019-02-15T00:00:00.000Z |
-| | EE | 2019-02-11T12:13:14.015Z | Mon | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fri | 2019-02-15T00:00:00.000Z |
-| | EEE | 2019-02-11T12:13:14.015Z | Mon | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fri | 2019-02-15T00:00:00.000Z |
-| | EEEE | 2019-02-11T12:13:14.015Z | Monday | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Friday | 2019-02-15T00:00:00.000Z |
-| | EEEEE | 2019-02-11T12:13:14.015Z | M | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | F | 2019-02-15T00:00:00.000Z |
-| | EEEEEE | 2019-02-11T12:13:14.015Z | Mo | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fr | 2019-02-15T00:00:00.000Z |
-| ISO day of week (formatting) | io | 2019-02-11T12:13:14.015Z | 1st | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | 5th | 2019-02-15T00:00:00.000Z |
-| | iii | 2019-02-11T12:13:14.015Z | Mon | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fri | 2019-02-15T00:00:00.000Z |
-| | iiii | 2019-02-11T12:13:14.015Z | Monday | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Friday | 2019-02-15T00:00:00.000Z |
-| | iiiii | 2019-02-11T12:13:14.015Z | M | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | F | 2019-02-15T00:00:00.000Z |
-| | iiiiii | 2019-02-11T12:13:14.015Z | Mo | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fr | 2019-02-15T00:00:00.000Z |
-| Local day of week (formatting) | eo | 2019-02-11T12:13:14.015Z | 2nd | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | 6th | 2019-02-15T00:00:00.000Z |
-| | eee | 2019-02-11T12:13:14.015Z | Mon | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fri | 2019-02-15T00:00:00.000Z |
-| | eeee | 2019-02-11T12:13:14.015Z | Monday | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Friday | 2019-02-15T00:00:00.000Z |
-| | eeeee | 2019-02-11T12:13:14.015Z | M | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | F | 2019-02-15T00:00:00.000Z |
-| | eeeeee | 2019-02-11T12:13:14.015Z | Mo | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fr | 2019-02-15T00:00:00.000Z |
-| Local day of week (stand-alone) | co | 2019-02-11T12:13:14.015Z | 2nd | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | 6th | 2019-02-15T00:00:00.000Z |
-| | ccc | 2019-02-11T12:13:14.015Z | Mon | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fri | 2019-02-15T00:00:00.000Z |
-| | cccc | 2019-02-11T12:13:14.015Z | Monday | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Friday | 2019-02-15T00:00:00.000Z |
-| | ccccc | 2019-02-11T12:13:14.015Z | M | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | F | 2019-02-15T00:00:00.000Z |
-| | cccccc | 2019-02-11T12:13:14.015Z | Mo | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-15T12:13:14.015Z | Fr | 2019-02-15T00:00:00.000Z |
-| AM, PM | a | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | aa | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | aaa | 2019-02-11T11:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
-| | aaaa | 2019-02-11T11:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
-| | aaaaa | 2019-02-11T11:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
-| AM, PM, noon, midnight | b | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | bb | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
-| | bbb | 2019-02-11T11:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
-| | bbbb | 2019-02-11T11:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
-| | bbbbb | 2019-02-11T11:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
-| Flexible day period | B | 2019-02-11T11:13:14.015Z | in the morning | 2019-02-11T04:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | in the afternoon | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | in the evening | 2019-02-11T17:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | at night | 2019-02-11T00:00:00.000Z |
-| | BB | 2019-02-11T11:13:14.015Z | in the morning | 2019-02-11T04:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | in the afternoon | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | in the evening | 2019-02-11T17:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | at night | 2019-02-11T00:00:00.000Z |
-| | BBB | 2019-02-11T11:13:14.015Z | in the morning | 2019-02-11T04:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | in the afternoon | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | in the evening | 2019-02-11T17:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | at night | 2019-02-11T00:00:00.000Z |
-| | BBBB | 2019-02-11T11:13:14.015Z | in the morning | 2019-02-11T04:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | in the afternoon | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | in the evening | 2019-02-11T17:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | at night | 2019-02-11T00:00:00.000Z |
-| | BBBBB | 2019-02-11T11:13:14.015Z | in the morning | 2019-02-11T04:00:00.000Z |
-| | | 2019-02-11T14:13:14.015Z | in the afternoon | 2019-02-11T12:00:00.000Z |
-| | | 2019-02-11T19:13:14.015Z | in the evening | 2019-02-11T17:00:00.000Z |
-| | | 2019-02-11T02:13:14.015Z | at night | Invalid Date |
-| Hour [1-12] | ho | 2019-02-11T11:13:14.015Z | 11th | 2019-02-11T11:00:00.000Z |
-| | | 2019-02-11T23:13:14.015Z | 11th | 2019-02-11T23:00:00.000Z |
-| Hour [0-23] | Ho | 2019-02-11T11:13:14.015Z | 11th | 2019-02-11T11:00:00.000Z |
-| | | 2019-02-11T23:13:14.015Z | 23rd | 2019-02-11T23:00:00.000Z |
-| Hour [0-11] | Ko | 2019-02-11T11:13:14.015Z | 11th | 2019-02-11T11:00:00.000Z |
-| | | 2019-02-11T23:13:14.015Z | 11th | 2019-02-11T23:00:00.000Z |
-| Hour [1-24] | ko | 2019-02-11T11:13:14.015Z | 11th | 2019-02-11T11:00:00.000Z |
-| | | 2019-02-11T23:13:14.015Z | 23rd | 2019-02-11T23:00:00.000Z |
-| Minute | mo | 2019-01-01T12:01:14.015Z | 1st | 2019-01-01T12:01:00.000Z |
-| | | 2019-04-01T12:55:14.015Z | 55th | 2019-04-01T12:55:00.000Z |
-| Second | so | 2019-01-01T12:13:01.015Z | 1st | 2019-01-01T12:13:01.000Z |
-| | | 2019-04-01T12:13:55.015Z | 55th | 2019-04-01T12:13:55.000Z |
-| Long localized date | P | 1987-02-11T12:13:14.015Z | 02/11/1987 | 1987-02-11T00:00:00.000Z |
-| | | 1453-05-29T23:59:59.999Z | 05/29/1453 | 1453-05-29T00:00:00.000Z |
-| | PP | 1987-02-11T12:13:14.015Z | Feb 11, 1987 | 1987-02-11T00:00:00.000Z |
-| | | 1453-05-29T23:59:59.999Z | May 29, 1453 | 1453-05-29T00:00:00.000Z |
-| | PPP | 1987-02-11T12:13:14.015Z | February 11th, 1987 | 1987-02-11T00:00:00.000Z |
-| | | 1453-05-29T23:59:59.999Z | May 29th, 1453 | 1453-05-29T00:00:00.000Z |
-| | PPPP | 1987-02-11T12:13:14.015Z | Wednesday, February 11th, 1987 | 1987-02-11T00:00:00.000Z |
-| | | 1453-05-29T23:59:59.999Z | Sunday, May 29th, 1453 | 1453-05-29T00:00:00.000Z |
-| Long localized time | p | 1987-02-11T12:13:14.015Z | 12:13 PM | 1987-02-11T12:13:00.000Z |
-| | | 1453-05-29T23:59:59.999Z | 11:59 PM | 1453-05-29T23:59:00.000Z |
-| | pp | 1987-02-11T12:13:14.015Z | 12:13:14 PM | 1987-02-11T12:13:14.000Z |
-| | | 1453-05-29T23:59:59.999Z | 11:59:59 PM | 1453-05-29T23:59:59.000Z |
-| | ppp | 1987-02-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
-| | | 1453-05-29T23:59:59.999Z | 11:59:59 PM GMT+0 | Errored |
-| | pppp | 1987-02-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
-| | | 1453-05-29T23:59:59.999Z | 11:59:59 PM GMT+00:00 | Errored |
-| Combination of date and time | Pp | 1987-02-11T12:13:14.015Z | 02/11/1987, 12:13 PM | 1987-02-11T12:13:00.000Z |
-| | | 1453-05-29T23:59:59.999Z | 05/29/1453, 11:59 PM | 1453-05-29T23:59:00.000Z |
-| | PPpp | 1987-02-11T12:13:14.015Z | Feb 11, 1987, 12:13:14 PM | 1987-02-11T12:13:14.000Z |
-| | | 1453-05-29T23:59:59.999Z | May 29, 1453, 11:59:59 PM | 1453-05-29T23:59:59.000Z |
-| | PPPppp | 1987-02-11T12:13:14.015Z | February 11th, 1987 at 12:13:14 PM GMT+0 | Errored |
-| | | 1453-05-29T23:59:59.999Z | May 29th, 1453 at 11:59:59 PM GMT+0 | Errored |
-| | PPPPpppp | 1987-02-11T12:13:14.015Z | Wednesday, February 11th, 1987 at 12:13:14 PM GMT+00:00 | Errored |
-| | | 1453-05-29T23:59:59.999Z | Sunday, May 29th, 1453 at 11:59:59 PM GMT+00:00 | Errored |
-
-## `formatDistance`
-
-If now is January 1st, 2000, 00:00.
-
-| Date | Result | `includeSeconds: true` | `addSuffix: true` |
-| ------------------------ | ------------------ | ---------------------- | ---------------------- |
-| 2006-01-01T00:00:00.000Z | about 6 years | about 6 years | in about 6 years |
-| 2005-01-01T00:00:00.000Z | about 5 years | about 5 years | in about 5 years |
-| 2004-01-01T00:00:00.000Z | about 4 years | about 4 years | in about 4 years |
-| 2003-01-01T00:00:00.000Z | about 3 years | about 3 years | in about 3 years |
-| 2002-01-01T00:00:00.000Z | about 2 years | about 2 years | in about 2 years |
-| 2001-06-01T00:00:00.000Z | over 1 year | over 1 year | in over 1 year |
-| 2001-02-01T00:00:00.000Z | about 1 year | about 1 year | in about 1 year |
-| 2001-01-01T00:00:00.000Z | about 1 year | about 1 year | in about 1 year |
-| 2000-06-01T00:00:00.000Z | 5 months | 5 months | in 5 months |
-| 2000-03-01T00:00:00.000Z | 2 months | 2 months | in 2 months |
-| 2000-02-01T00:00:00.000Z | about 1 month | about 1 month | in about 1 month |
-| 2000-01-15T00:00:00.000Z | 14 days | 14 days | in 14 days |
-| 2000-01-02T00:00:00.000Z | 1 day | 1 day | in 1 day |
-| 2000-01-01T06:00:00.000Z | about 6 hours | about 6 hours | in about 6 hours |
-| 2000-01-01T01:00:00.000Z | about 1 hour | about 1 hour | in about 1 hour |
-| 2000-01-01T00:45:00.000Z | about 1 hour | about 1 hour | in about 1 hour |
-| 2000-01-01T00:30:00.000Z | 30 minutes | 30 minutes | in 30 minutes |
-| 2000-01-01T00:15:00.000Z | 15 minutes | 15 minutes | in 15 minutes |
-| 2000-01-01T00:01:00.000Z | 1 minute | 1 minute | in 1 minute |
-| 2000-01-01T00:00:25.000Z | less than a minute | half a minute | in less than a minute |
-| 2000-01-01T00:00:15.000Z | less than a minute | less than 20 seconds | in less than a minute |
-| 2000-01-01T00:00:05.000Z | less than a minute | less than 10 seconds | in less than a minute |
-| 2000-01-01T00:00:00.000Z | less than a minute | less than 5 seconds | less than a minute ago |
-| 1999-12-31T23:59:55.000Z | less than a minute | less than 10 seconds | less than a minute ago |
-| 1999-12-31T23:59:45.000Z | less than a minute | less than 20 seconds | less than a minute ago |
-| 1999-12-31T23:59:35.000Z | less than a minute | half a minute | less than a minute ago |
-| 1999-12-31T23:59:00.000Z | 1 minute | 1 minute | 1 minute ago |
-| 1999-12-31T23:45:00.000Z | 15 minutes | 15 minutes | 15 minutes ago |
-| 1999-12-31T23:30:00.000Z | 30 minutes | 30 minutes | 30 minutes ago |
-| 1999-12-31T23:15:00.000Z | about 1 hour | about 1 hour | about 1 hour ago |
-| 1999-12-31T23:00:00.000Z | about 1 hour | about 1 hour | about 1 hour ago |
-| 1999-12-31T18:00:00.000Z | about 6 hours | about 6 hours | about 6 hours ago |
-| 1999-12-30T00:00:00.000Z | 2 days | 2 days | 2 days ago |
-| 1999-12-15T00:00:00.000Z | 17 days | 17 days | 17 days ago |
-| 1999-12-01T00:00:00.000Z | about 1 month | about 1 month | about 1 month ago |
-| 1999-11-01T00:00:00.000Z | 2 months | 2 months | 2 months ago |
-| 1999-06-01T00:00:00.000Z | 7 months | 7 months | 7 months ago |
-| 1999-01-01T00:00:00.000Z | about 1 year | about 1 year | about 1 year ago |
-| 1998-12-01T00:00:00.000Z | about 1 year | about 1 year | about 1 year ago |
-| 1998-06-01T00:00:00.000Z | over 1 year | over 1 year | over 1 year ago |
-| 1998-01-01T00:00:00.000Z | about 2 years | about 2 years | about 2 years ago |
-| 1997-01-01T00:00:00.000Z | about 3 years | about 3 years | about 3 years ago |
-| 1996-01-01T00:00:00.000Z | about 4 years | about 4 years | about 4 years ago |
-| 1995-01-01T00:00:00.000Z | about 5 years | about 5 years | about 5 years ago |
-| 1994-01-01T00:00:00.000Z | about 6 years | about 6 years | about 6 years ago |
-
-## `formatDistanceStrict`
-
-If now is January 1st, 2000, 00:00.
-
-| Date | Result | `addSuffix: true` | With forced unit (i.e. `hour`) |
-| ------------------------ | ---------- | ----------------- | ------------------------------ |
-| 2006-01-01T00:00:00.000Z | 6 years | in 6 years | 52608 hours |
-| 2005-01-01T00:00:00.000Z | 5 years | in 5 years | 43848 hours |
-| 2004-01-01T00:00:00.000Z | 4 years | in 4 years | 35064 hours |
-| 2003-01-01T00:00:00.000Z | 3 years | in 3 years | 26304 hours |
-| 2002-01-01T00:00:00.000Z | 2 years | in 2 years | 17544 hours |
-| 2001-06-01T00:00:00.000Z | 1 year | in 1 year | 12408 hours |
-| 2001-02-01T00:00:00.000Z | 1 year | in 1 year | 9528 hours |
-| 2001-01-01T00:00:00.000Z | 1 year | in 1 year | 8784 hours |
-| 2000-06-01T00:00:00.000Z | 5 months | in 5 months | 3648 hours |
-| 2000-03-01T00:00:00.000Z | 2 months | in 2 months | 1440 hours |
-| 2000-02-01T00:00:00.000Z | 1 month | in 1 month | 744 hours |
-| 2000-01-15T00:00:00.000Z | 14 days | in 14 days | 336 hours |
-| 2000-01-02T00:00:00.000Z | 1 day | in 1 day | 24 hours |
-| 2000-01-01T06:00:00.000Z | 6 hours | in 6 hours | 6 hours |
-| 2000-01-01T01:00:00.000Z | 1 hour | in 1 hour | 1 hour |
-| 2000-01-01T00:45:00.000Z | 45 minutes | in 45 minutes | 1 hour |
-| 2000-01-01T00:30:00.000Z | 30 minutes | in 30 minutes | 1 hour |
-| 2000-01-01T00:15:00.000Z | 15 minutes | in 15 minutes | 0 hours |
-| 2000-01-01T00:01:00.000Z | 1 minute | in 1 minute | 0 hours |
-| 2000-01-01T00:00:25.000Z | 25 seconds | in 25 seconds | 0 hours |
-| 2000-01-01T00:00:15.000Z | 15 seconds | in 15 seconds | 0 hours |
-| 2000-01-01T00:00:05.000Z | 5 seconds | in 5 seconds | 0 hours |
-| 2000-01-01T00:00:00.000Z | 0 seconds | 0 seconds ago | 0 hours |
-| 1999-12-31T23:59:55.000Z | 5 seconds | 5 seconds ago | 0 hours |
-| 1999-12-31T23:59:45.000Z | 15 seconds | 15 seconds ago | 0 hours |
-| 1999-12-31T23:59:35.000Z | 25 seconds | 25 seconds ago | 0 hours |
-| 1999-12-31T23:59:00.000Z | 1 minute | 1 minute ago | 0 hours |
-| 1999-12-31T23:45:00.000Z | 15 minutes | 15 minutes ago | 0 hours |
-| 1999-12-31T23:30:00.000Z | 30 minutes | 30 minutes ago | 1 hour |
-| 1999-12-31T23:15:00.000Z | 45 minutes | 45 minutes ago | 1 hour |
-| 1999-12-31T23:00:00.000Z | 1 hour | 1 hour ago | 1 hour |
-| 1999-12-31T18:00:00.000Z | 6 hours | 6 hours ago | 6 hours |
-| 1999-12-30T00:00:00.000Z | 2 days | 2 days ago | 48 hours |
-| 1999-12-15T00:00:00.000Z | 17 days | 17 days ago | 408 hours |
-| 1999-12-01T00:00:00.000Z | 1 month | 1 month ago | 744 hours |
-| 1999-11-01T00:00:00.000Z | 2 months | 2 months ago | 1464 hours |
-| 1999-06-01T00:00:00.000Z | 7 months | 7 months ago | 5136 hours |
-| 1999-01-01T00:00:00.000Z | 1 year | 1 year ago | 8760 hours |
-| 1998-12-01T00:00:00.000Z | 1 year | 1 year ago | 9504 hours |
-| 1998-06-01T00:00:00.000Z | 2 years | 2 years ago | 13896 hours |
-| 1998-01-01T00:00:00.000Z | 2 years | 2 years ago | 17520 hours |
-| 1997-01-01T00:00:00.000Z | 3 years | 3 years ago | 26280 hours |
-| 1996-01-01T00:00:00.000Z | 4 years | 4 years ago | 35064 hours |
-| 1995-01-01T00:00:00.000Z | 5 years | 5 years ago | 43824 hours |
-| 1994-01-01T00:00:00.000Z | 6 years | 6 years ago | 52584 hours |
-
-## `formatRelative`
-
-If now is January 1st, 2000, 00:00.
-
-| Date | Result |
-| ------------------------ | ----------------------- |
-| 2000-01-10T00:00:00.000Z | 01/10/2000 |
-| 2000-01-05T00:00:00.000Z | Wednesday at 12:00 AM |
-| 2000-01-02T00:00:00.000Z | tomorrow at 12:00 AM |
-| 2000-01-01T00:00:00.000Z | today at 12:00 AM |
-| 1999-12-31T00:00:00.000Z | yesterday at 12:00 AM |
-| 1999-12-27T00:00:00.000Z | last Monday at 12:00 AM |
-| 1999-12-21T00:00:00.000Z | 12/21/1999 |
-
-## `formatDuration`
-
-| Duration | Result |
-| ------------- | --------- |
-| {"years":0} | 0 years |
-| {"years":1} | 1 year |
-| {"years":2} | 2 years |
-| {"months":0} | 0 months |
-| {"months":1} | 1 month |
-| {"months":2} | 2 months |
-| {"weeks":0} | 0 weeks |
-| {"weeks":1} | 1 week |
-| {"weeks":2} | 2 weeks |
-| {"days":0} | 0 days |
-| {"days":1} | 1 day |
-| {"days":2} | 2 days |
-| {"hours":0} | 0 hours |
-| {"hours":1} | 1 hour |
-| {"hours":2} | 2 hours |
-| {"minutes":0} | 0 minutes |
-| {"minutes":1} | 1 minute |
-| {"minutes":2} | 2 minutes |
-| {"seconds":0} | 0 seconds |
-| {"seconds":1} | 1 second |
-| {"seconds":2} | 2 seconds |
diff --git a/lib/date-fns/locale/index.ts b/lib/date-fns/locale/index.ts
deleted file mode 100644
index 53a7bd2e..00000000
--- a/lib/date-fns/locale/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as fil } from './fil';
diff --git a/lib/date-fns/locale/types.ts b/lib/date-fns/locale/types.ts
deleted file mode 100644
index 3cc6325a..00000000
--- a/lib/date-fns/locale/types.ts
+++ /dev/null
@@ -1,273 +0,0 @@
-/* eslint-disable no-unused-vars */
-
-import type {
- Day,
- Era,
- FirstWeekContainsDate,
- Month,
- Quarter,
- Unit,
-} from '../types';
-import type {
- BuildLocalizeFnArgCallback,
- LocalizeUnitValues,
- LocalizeUnitValuesIndex,
-} from './_lib/buildLocalizeFn';
-
-export interface Locale {
- code: string;
- formatDistance: FormatDistanceFn;
- formatRelative: FormatRelativeFn;
- localize: Localize;
- formatLong: FormatLong;
- match: Match;
- options?: LocaleOptions;
-}
-
-export interface LocaleOptions {
- weekStartsOn?: Day;
- firstWeekContainsDate?: FirstWeekContainsDate;
-}
-
-export type FormatDistanceToken =
- | 'lessThanXSeconds'
- | 'xSeconds'
- | 'halfAMinute'
- | 'lessThanXMinutes'
- | 'xMinutes'
- | 'aboutXHours'
- | 'xHours'
- | 'xDays'
- | 'aboutXWeeks'
- | 'xWeeks'
- | 'aboutXMonths'
- | 'xMonths'
- | 'aboutXYears'
- | 'xYears'
- | 'overXYears'
- | 'almostXYears';
-
-export type FormatDistanceLocale = {
- [token in FormatDistanceToken]: Value;
-};
-
-export interface FormatDistanceFnOptions {
- addSuffix?: boolean;
- comparison?: -1 | 0 | 1;
-}
-
-export type FormatDistanceTokenFn = (
- count: number,
- options?: FormatDistanceOptions
-) => string;
-
-export interface FormatDistanceOptions {
- addSuffix?: boolean;
- comparison?: -1 | 0 | 1;
-}
-
-export type FormatDistanceFn = (
- token: FormatDistanceToken,
- count: number,
- options?: FormatDistanceOptions
-) => string;
-
-export type FormatRelativeTokenFn = (
- date: Date | number,
- baseDate: Date | number,
- options?: { weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 }
-) => string;
-
-export type FormatRelativeToken =
- | 'lastWeek'
- | 'yesterday'
- | 'today'
- | 'tomorrow'
- | 'nextWeek'
- | 'other';
-
-export interface FormatRelativeFnOptions {
- weekStartsOn?: Day;
- locale?: Locale;
-}
-
-export type FormatRelativeFn = (
- token: FormatRelativeToken,
- date: Date,
- baseDate: Date,
- options?: FormatRelativeFnOptions
-) => string;
-
-// TODO: You're real champion if you're actually get back to it. Proud of you!
-// Try to get rid of this and (especially) ArgCallback types because the only
-// case when it's helpful is when using quarter. Maybe.
-export type LocalizeUnitIndex =
- Unit extends LocaleUnit
- ? LocalizeUnitValuesIndex>
- : number;
-
-export type LocalizeFn<
- Result extends LocaleUnit | number,
- ArgCallback extends BuildLocalizeFnArgCallback | undefined = undefined
-> = (
- value: ArgCallback extends undefined
- ? Result
- : Result extends Quarter
- ? Quarter
- : LocalizeUnitIndex,
- options?: {
- width?: LocalePatternWidth;
- context?: 'formatting' | 'standalone';
- unit?: Unit;
- }
-) => string;
-
-export interface Localize {
- ordinalNumber: LocalizeFn<
- number,
- BuildLocalizeFnArgCallback | undefined
- >;
- era: LocalizeFn;
- quarter: LocalizeFn>;
- month: LocalizeFn;
- day: LocalizeFn;
- dayPeriod: LocalizeFn;
-}
-
-export interface BuildMatchFnArgs<
- Result extends LocaleUnit,
- DefaultMatchWidth extends LocalePatternWidth,
- DefaultParseWidth extends LocalePatternWidth
-> {
- matchPatterns: MatchPatterns;
- defaultMatchWidth: DefaultMatchWidth;
- parsePatterns: ParsePatterns;
- defaultParseWidth: DefaultParseWidth;
- valueCallback?: MatchValueCallback<
- Result extends LocaleDayPeriod ? string : number,
- Result
- >;
-}
-
-export type MatchPatterns = {
- [pattern in LocalePatternWidth]?: RegExp;
-} & { [key in DefaultWidth]: RegExp };
-
-export type ParsePatterns<
- Result extends LocaleUnit,
- DefaultWidth extends LocalePatternWidth
-> = {
- [pattern in LocalePatternWidth]?: ParsePattern;
-} & { [key in DefaultWidth]: ParsePattern };
-
-export type ParsePattern =
- Result extends LocaleDayPeriod
- ? Record
- : Result extends Quarter
- ? readonly [RegExp, RegExp, RegExp, RegExp]
- : Result extends Era
- ? readonly [RegExp, RegExp]
- : Result extends Day
- ? readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp]
- : Result extends Month
- ? readonly [
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp,
- RegExp
- ]
- : never;
-
-export type BuildMatchFn<
- Result extends LocaleUnit,
- DefaultMatchWidth extends LocalePatternWidth,
- DefaultParseWidth extends LocalePatternWidth
-> = (
- args: BuildMatchFnArgs
-) => MatchFn;
-
-export type MatchFn = (
- str: string,
- options?: {
- width?: LocalePatternWidth;
- valueCallback?: MatchValueCallback;
- }
-) => { value: Result; rest: string } | null;
-
-export type MatchValueCallback = (value: Arg) => Result;
-
-export interface Match {
- ordinalNumber: MatchFn;
- era: MatchFn;
- quarter: MatchFn;
- month: MatchFn;
- day: MatchFn;
- dayPeriod: MatchFn;
-}
-
-export type LocaleOrdinalUnit =
- | 'second'
- | 'minute'
- | 'hour'
- | 'day'
- | 'week'
- | 'month'
- | 'quarter'
- | 'year'
- | 'date'
- | 'dayOfYear';
-
-export type LocalePatternWidth =
- | 'narrow'
- | 'short'
- | 'abbreviated'
- | 'wide'
- | 'any';
-
-export type LocaleDayPeriod =
- | 'am'
- | 'pm'
- | 'midnight'
- | 'noon'
- | 'morning'
- | 'afternoon'
- | 'evening'
- | 'night';
-
-export type LocaleOptionUnit =
- | 'year'
- | 'quarter'
- | 'month'
- | 'week'
- | 'date'
- | 'dayOfYear'
- | 'day'
- | 'hour'
- | 'minute'
- | 'second';
-
-export type FormatLongWidth = 'full' | 'long' | 'medium' | 'short' | 'any';
-
-export type DateTimeFormat = { [format in FormatLongWidth]: string };
-
-export type LocaleUnit = Era | Quarter | Month | Day | LocaleDayPeriod;
-
-export interface FormatLong {
- date: FormatLongFn;
- time: FormatLongFn;
- dateTime: FormatLongFn;
-}
-
-export interface FormatLongFnOptions {
- width?: FormatLongWidth;
-}
-
-export type FormatLongFn = (options: FormatLongFnOptions) => string;
diff --git a/locales/ara.json b/locales/ara.json
index c8a862d7..ad61e33d 100644
--- a/locales/ara.json
+++ b/locales/ara.json
@@ -1,336 +1,568 @@
-{
- "DeviceInfoList": {
- "requestedBy": "مطلوب بواسطة",
- "sentBy": "مرسل بواسطة",
- "deviceRefNumber": "الرقم المرجعي للجهاز",
- "name": "اسم"
- },
- "FaceScanner": {},
- "OIDcAuth": {
- "title": "مصادقة OIDC",
- "text": "ليتم استبداله بموفر OIDC UI",
- "verify": "تحقق"
- },
- "PasscodeVerify": {
- "passcodeMismatchError": "رمز المرور غير متطابق."
- },
- "QrScanner": {
- "missingPermissionText": "يستخدم هذا التطبيق الكاميرا لمسح رمز الاستجابة السريعة لجهاز آخر.",
- "allowCameraButton": "السماح بالوصول إلى الكاميرا"
- },
- "VcDetails": {
- "generatedOn": "تم إنشاؤه في",
- "status": "الحالة",
- "valid": "صالح",
- "photo": " صورة",
- "fullName": "الاسم الكامل",
- "gender": "الجنس",
- "dateOfBirth": "डتاريخ الميلاد",
- "phoneNumber": "رقم الهاتف",
- "email": "البريد الإلكتروني",
- "address": "عنوان",
- "reasonForSharing": "سبب المشاركة",
- "idType": "نوع الهوية",
- "id": "Id",
- "nationalCard": "البطاقة الوطنية",
- "uin": "UIN",
- "enableVerification": "تفعيل",
- "profileAuthenticated": "تم تنشيطه لتسجيل الدخول عبر الإنترنت",
- "offlineAuthDisabledHeader": "التنشيط معلق لتسجيل الدخول عبر الإنترنت",
- "offlineAuthDisabledMessage": "الرجاء النقر فوق الزر أدناه لتفعيل بيانات الاعتماد هذه لاستخدامها في تسجيل الدخول عبر الإنترنت.",
- "vid": "VID",
- "verificationEnabledSuccess": "تم تنشيطه لتسجيل الدخول عبر الإنترنت",
- "goback": "عُد",
- "BindingWarning": "لقد قمت بالفعل بتنشيط تسجيل الدخول عبر الإنترنت لبيانات الاعتماد هذه على جهاز آخر. لن تتمكن بعد الآن من استخدام هذا الجهاز لتسجيل الدخول إذا قمت بتنشيطه مرة أخرى على هذا الجهاز.",
- "yes_confirm": "نعم ، أنا أؤكد",
- "no": "رقم",
- "Alert": "انذار",
- "ok": "تمام"
- },
- "AuthScreen": {
- "header": "هل ترغب في استخدام المقاييس الحيوية لفتح التطبيق؟",
- "useBiometrics": "استخدام القياسات الحيوية",
- "usePasscode": "मأفضل استخدام رمز مرور",
- "errors": {
- "unavailable": "س الحيوية",
- "unenrolled": "إصبعك في إعدادات جهازك",
- "failed": "الحيوية",
- "generic": "الحيوية"
- }
- },
- "BiometricScreen": {
- "unlock": "افتح ببصمة الإصبع"
- },
- "HistoryTab": {
- "noHistory": "لا يوجد سجل متاح حتى الآن",
- "downloaded": "تم التنزيل",
- "shared": "مشتركة",
- "received": "مستلم",
- "deleted": "محذوف"
- },
- "HomeScreen": {
- "myVcsTab": "محذوف\n{{vcLabel}}",
- "receivedVcsTab": "مستلم\n{{vcLabel}}",
- "historyTab": "تاريخ"
- },
- "AddVcModal": {
- "requestingCredential": "جارٍ طلب بيانات الاعتماد...",
- "errors": {
- "input": {
- "empty": "فارغًا",
- "invalidFormat": "غير صحيح"
- },
- "backend": {
- "invalidOtp": "OTP غير صالح",
- "invalidUin": "UIN غير صالح",
- "invalidVid": "VID غير صالح",
- "missingUin": "UIN غير متوفر في قاعدة البيانات",
- "missingVid": "VID غير متوفر في قاعدة البيانات"
- }
- }
- },
- "DownloadingVcModal": {
- "header": "تنزيل ملف{{vcLabel}}",
- "bodyText": "قد يستغرق هذا بعض الوقت ، وسنخبرك عندما يتم تنزيل {{vcLabel}} وإتاحته",
- "backButton": "العودة إلى المنزل"
- },
- "GetIdInputModal": {
- "header": "لاسترداد UIN أو VID ، أدخل رقم التطبيق {{vcLabel}}",
- "getUIN": "احصل على UIN / VID",
- "applicationId": "رقم التطبيق {{vcLabel}}",
- "requestingOTP": "طلب OTP...",
- "qstnMarkToolTip": "تمت طباعة رقم التطبيق {{vcLabel}} على الإقرار المقدم بعد التسجيل"
- },
- "IdInputModal": {
- "header": "أدخل UIN المقدم من MOSIP أو VID لـ {{vcLabel}} الذي تريد استرداده",
- "generateVc": "إنشاء {{vcLabel}}",
- "enterId": "أدخل {{idType}}",
- "noUIN/VID": "ليس لديك UIN / VID الخاص بك؟ أحضره هنا",
- "requestingOTP": "طلب OTP..."
- },
- "OtpVerificationModal": {
- "enterOtp": "أدخل رمز التحقق المكون من 6 أرقام الذي أرسلناه إليك",
- "header": "التحقق من OTP"
- },
- "MyVcsTab": {
- "addVcButton": "{{vcLabel}} إضافة",
- "generateVc": "{{vcLabel}}إنشاء",
- "generateVcDescription": "إضافة {{vcLabel}} أدناه لتنزيل {{vcLabel}}"
- },
- "OnboardingOverlay": {
- "stepOneTitle": "مرحبًا!",
- "stepOneText": "احتفظ ببيانات الاعتماد الرقمية معك في جميع الأوقات. للبدء ، أضف {{vcLabel}} إلى ملفك الشخصي.",
- "stepTwoTitle": "{{vcLabel}} إدارة",
- "stepTwoText": "بمجرد إنشائه ، يتم تخزين {{vcLabel}}بأمان على هاتفك المحمول ويمكن إعادة تسميته أو مشاركته في أي وقت.",
- "stepThreeTitle": "مشاركة سهلة",
- "stepThreeText": "مشاركة واستلام {{vcLabel}} switflyباستخدام كاميرا هاتفك لمسح رموز QR.",
- "stepThreeButton": "ابدأ وأضف{{vcLabel}} "
- },
- "ReceivedVcsTab": {
- "noReceivedVcsTitle": "لا يوجد {{vcLabel}} متاح حتى الآن",
- "noReceivedVcsText": "اضغط على الطلب أدناه لتلقي{{vcLabel}}"
- },
- "ViewVcModal": {
- "cancel": "يلغي",
- "lock": "قفل",
- "unlock": "الغاء القفل",
- "rename": "إعادة تسمية",
- "delete": "حذف",
- "revoke": "إبطال",
- "revoking": "تحتوي محفظتك على بيانات اعتماد مع VID {{vid}}. سيؤدي إبطال هذا إلى حذفه تلقائيًا من المحفظة. هل انت متأكد انك تريد المتابعة؟",
- "requestingOtp": "جارٍ طلب OTP...",
- "editTag": "टتحرير العلامة",
- "redirecting": "إعادة توجيه...",
- "inProgress": "جار التحميل...",
- "success": {
- "unlocked": "تم إلغاء قفل {{vcLabel}} بنجاح",
- "locked": "تم قفل {{vcLabel}} بنجاح",
- "revoked": "تم إبطال VID {{vid}}. ستتم إزالة أي بيانات اعتماد تحتوي على نفس الشيء تلقائيًا من المحفظة"
- }
- },
- "MainLayout": {
- "home": "المنزل",
- "scan": "مسح",
- "request": "طلب",
- "profile": "الملف الشخصي"
- },
- "PasscodeScreen": {
- "header": "تعيين رمز مرور لتأمين تطبيقك",
- "confirmPasscode": "تأكيد رمز المرور الخاص بك",
- "enterPasscode": "المرور الخاص بك"
- },
- "Credits": {
- "header": "الائتمانات والإشعارات القانونية",
- "back": "رجوع"
- },
- "ProfileScreen": {
- "name": "اسم",
- "vcLabel": "تسمية VC",
- "language": "اللغة",
- "bioUnlock": "فتح المقاييس الحيوية",
- "authFactorUnlock": "إلغاء تأمين عامل المصادقة",
- "credits": "القانونية",
- "logout": "تسجيل الخروج",
- "revokeLabel": "إبطال VID",
- "revokeHeader": "إبطال VID",
- "revokingVids": "({{count}}) أنت على وشك إلغاء معرّفات VID.",
- "revokingVidsAfter": "هذا يعني أنك لن تكون قادرًا على استخدام أو عرض أي من المعرفات المرتبطة بمعرف (معرفات) VID هؤلاء. \nهل انت متأكد انك تريد المتابعة?",
- "empty": "فارغة",
- "revokeSuccessful": "تم إبطال VID بنجاح",
- "version": "الإصدار"
- },
- "QrScreen": {
- "title": "QR تسجيل الدخول",
- "alignQr": "قم بمحاذاة رمز الاستجابة السريعة داخل الإطار للمسح الضوئي",
- "confirmation": "تأكيد",
- "checkDomain": "تحقق أيضًا من وجود رمز قفل على شريط العناوين.",
- "domainHead": "https://",
- "selectId": "حدد المعرف",
- "noBindedVc": "لا يوجد {{vcLabel}} مرتبط متاح للتحقق",
- "back": "عُد",
- "confirm": "يتأكد",
- "verify": "تحقق",
- "faceAuth": "مصادقة الوجه",
- "consent": "موافقة",
- "loading": "جار التحميل...",
- "domainWarning": "يرجى تأكيد مجال موقع الويب الذي تقوم بمسح رمز الاستجابة السريعة منه على النحو التالي",
- "access": " يطلب الوصول إلى",
- "status": "حالة",
- "successMessage":"لقد قمت بتسجيل الدخول بنجاح ",
- "okay": "تمام"
- },
- "ReceiveVcScreen": {
- "header": "تفاصيل {{vcLabel}}",
- "acceptRequest": "قبول الطلب واستلام {{vcLabel}}",
- "acceptRequestAndVerify": "قبول الطلب والتحقق",
- "reject": "رفض"
- },
- "RequestScreen": {
- "bluetoothDenied": "الرجاء تمكين Bluetooth لتتمكن من طلب{{vcLabel}}",
- "showQrCode": "{{vcLabel}} أظهر رمز الاستجابة السريعة هذا لطلب ",
- "incomingVc": "الوارد {{vcLabel}}",
- "request": "طلب",
- "status": {
- "accepted": {
- "title": "نجاح!",
- "message": "تم استلام {{vcLabel}}بنجاح من {{sender}}"
- },
- "rejected": {
- "title": " إشعار",
- "message": "لقد رفضت {{sender}} {{vcLabel}}"
- },
- "disconnected": {
- "title": "ير متصل",
- "message": "انقطع الاتصال. يرجى المحاولة مرة أخرى."
- },
- "waitingConnection": "انتظار الاتصال ...",
- "exchangingDeviceInfo": {
- "message": "تبادل معلومات الجهاز...",
- "timeoutHint": "يستغرق تبادل معلومات الجهاز وقتًا طويلاً..."
- },
- "connected": {
- "message": "متصل بالجهاز. في انتظار {{vcLabel}}...",
- "timeoutHint": "لم ترد بيانات حتى الآن. هل جهاز الإرسال لا يزال متصلاً؟"
- }
+{
+ "ActivityLogText": {
+ "VC_SHARED": "مشترك",
+ "VC_RECEIVED": "الواردة",
+ "VC_RECEIVED_NOT_SAVED": "تلقى لم يتم حفظها",
+ "VC_DELETED": "تم الحذف",
+ "VC_DOWNLOADED": "تم تنزيله",
+ "VC_REVOKED": "إلغاء - فسخ",
+ "VC_SHARED_WITH_VERIFICATION_CONSENT": "مشترك. يتم إعطاء الموافقة للتحقق من التواجد",
+ "VC_RECEIVED_WITH_PRESENCE_VERIFIED": "الواردة. تم التحقق من الحضور",
+ "VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "الواردة. فشل التحقق من التواجد",
+ "PRESENCE_VERIFIED_AND_VC_SHARED": "التحقق منها ومشاركتها",
+ "PRESENCE_VERIFICATION_FAILED": "فشل التحقق",
+ "QRLOGIN_SUCCESFULL": "QRL تم تسجيل الدخول بنجاح",
+ "WALLET_BINDING_SUCCESSFULL": "تفعيل ناجحة",
+ "WALLET_BINDING_FAILURE": "فشل التفعيل",
+ "VC_REMOVED":"تمت إزالته من المحفظة"
+ },
+ "DeviceInfoList": {
+ "requestedBy": "مطلوب بواسطة",
+ "sentBy": "مرسل بواسطة",
+ "deviceRefNumber": "الرقم المرجعي للجهاز",
+ "name": "اسم",
+ "Verifier": "المدقق",
+ "Wallet": "محفظة"
+ },
+ "FaceScanner": {},
+ "OIDcAuth": {
+ "title": "مصادقة OIDC",
+ "text": "ليتم استبداله بموفر واجهة مستخدم OIDC",
+ "verify": "تحقق"
+ },
+ "PasscodeVerify": {
+ "passcodeMismatchError": "رمز المرور غير متطابق."
+ },
+ "QrScanner": {
+ "cameraAccessDisabled": "تم تعطيل الوصول إلى الكاميرا!",
+ "cameraPermissionGuideLabel": "انتقل إلى الإعدادات وقم بتمكين الوصول إلى الكاميرا يدويًا.",
+ "flipCamera": "فليب الكاميرا"
+ },
+ "VcDetails": {
+ "generatedOn": "تم إنشاؤه في",
+ "status": "الحالة",
+ "valid": "صالح",
+ "photo": " صورة",
+ "fullName": "الاسم الكامل",
+ "gender": "الجنس",
+ "dateOfBirth": "डتاريخ الميلاد",
+ "phoneNumber": "رقم الهاتف",
+ "email": "البريد الإلكتروني",
+ "address": "عنوان",
+ "reasonForSharing": "سبب المشاركة",
+ "idType": "نوع الهوية",
+ "id": "بطاقة تعريف",
+ "qrCodeHeader": "رمز الاستجابة السريعة",
+ "nationalCard": "البطاقة الوطنية",
+ "uin": "UIN",
+ "vid": "VID",
+ "enableVerification": "تفعيل",
+ "profileAuthenticated": "تم التنشيط لتسجيل الدخول عبر الإنترنت!",
+ "offlineAuthDisabledHeader": "التنشيط معلق لتسجيل الدخول عبر الإنترنت!",
+ "offlineAuthDisabledMessage": "الرجاء النقر فوق الزر أدناه لتنشيط بيانات الاعتماد هذه لاستخدامها في تسجيل الدخول عبر الإنترنت.",
+ "verificationEnabledSuccess": "تم التنشيط لتسجيل الدخول عبر الإنترنت",
+ "goback": "عُد",
+ "BindingWarning": "إذا قمت بتمكين التحقق من بيانات الاعتماد هذه في محفظة أخرى ، فسيتم تجاوزها. هل تريد المتابعة؟",
+ "yes_confirm": "نعم ، أنا أؤكد",
+ "no": "رقم",
+ "Alert": "انذار",
+ "ok": "تمام",
+ "credentialRegistry": "سجل الاعتماد",
+ "errors": {
+ "savingFailed": {
+ "title": "فشل حفظ بطاقة",
+ "message": "حدث خطأ أثناء حفظ البطاقة في المتجر."
},
- "online": "متصل",
- "offline": "غير متصل على الانترنت",
- "gotoSettings": "اذهب للاعدادات"
- },
- "ScanScreen": {
- "header": "مسح رمز الاستجابة السريعة",
- "noShareableVcs": "لا يمكن مشاركة {{vcLabel}}",
- "sharingVc": "مشاركة {{vcLabel}}",
- "errors": {
- "locationDisabled": {
- "message": "يجب تمكين خدمات الموقع لوظيفة المسح",
- "button": "تمكين خدمات الموقع"
- },
- "locationDenied": {
- "message": "إذن الموقع مطلوب لوظيفة المسح",
- "button": "الموقع"
- }
- },
- "status": {
- "connecting": "ارٍ التوصيل...",
- "connectingTimeout": "يستغرق إنشاء الاتصال بعض الوقت. هل الجهاز الآخر مفتوح للاتصالات؟",
- "exchangingDeviceInfo": "تبادل معلومات الجهاز ...",
- "exchangingDeviceInfoTimeout": "يستغرق الأمر بعض الوقت لتبادل معلومات الجهاز. قد تضطر إلى إعادة الاتصال.",
- "invalid": "غير صالح"
- }
- },
- "SelectVcOverlay": {
- "header": "يشارك {{vcLabel}}",
- "chooseVc": "اختر {{vcLabel}} الذي ترغب في المشاركة معه",
- "share": "شارك",
- "verifyAndShare": "التحقق من الهوية والمشاركة"
- },
- "SendVcScreen": {
- "reasonForSharing": "سبب المشاركة (اختياري)",
- "acceptRequest": "اقبل الطلب واختر {{vcLabel}}",
- "acceptRequestAndVerify": "قبول الطلب والتحقق",
- "reject": "رفض",
- "status": {
- "sharing": {
- "title": "مشاركة...",
- "hint": "الرجاء الانتظار حتى يقبل الجهاز المتلقي المشاركة أو يرفضها.",
- "timeoutHint": "تستغرق مشاركتها وقتًا أطول من المتوقع. قد تكون هناك مشكلة في الاتصال."
- },
- "accepted": {
- "title": "النجاح!",
- "message": "تمت مشاركة {{vcLabel}} بنجاح مع {{receiver}}"
- },
- "rejected": {
- "title": "تنويه",
- "message": "تم رفض {{vcLabel}} من قِبل {{receiver}}"
- }
- },
- "consentToPhotoVerification": "أوافق على التقاط صورتي للمصادقة"
- },
- "VerifyIdentityOverlay": {
- "status": {
- "verifyingIdentity": "التحقق من الهوية..."
- },
- "errors": {
- "invalidIdentity": {
- "title": "تعذر التحقق من الهوية",
- "message": "حدث خطأ ولم نتمكن من مسح صورتك ضوئيًا. حاول مرة أخرى ، وتأكد من أن وجهك مرئي وخالي من أي ملحقات.",
- "messageNoRetry": "حدث خطأ ولم نتمكن من مسح صورتك ضوئيًا."
- }
- }
- },
- "SendVcModal": {
- "reasonForSharing": "سبب المشاركة (optional)",
- "acceptRequest": "قبول الطلب واختيار {{vcLabel}}",
- "reject": "رفض",
- "statusSharing": {
- "title": "مشاركة ..."
- },
- "statusAccepted": {
- "title": "نجاح!",
- "message": "تمت مشاركة {{vcLabel}} بنجاح مع{{receiver}}"
- },
- "statusRejected": {
- "title": " إشعار",
- "message": "تم رفض {{vcLabel}}من قِبل {{receiver}}"
- }
- },
- "WelcomeScreen": {
- "title": "حل هوية مفتوحة المصدر",
- "getStarted": "البدء",
- "unlockApp": "فتح التطبيق"
- },
- "common": {
- "cancel": "إلغاء",
- "save": "حفظ",
- "dismiss": "رفض",
- "editLabel": "يحرر {{label}}",
- "tryAgain": "حاول مجددا",
- "camera": {
- "errors": {
- "missingPermission": "يستخدم هذا التطبيق الكاميرا لمسح رمز الاستجابة السريعة لجهاز آخر."
- },
- "allowAccess": "اسمح بالوصول إلى الكاميرا"
+ "diskFullError": {
+ "title": "فشل حفظ البطاقة",
+ "message": "لا يمكن استلام المزيد من البطاقات أو حفظها حيث أن بيانات التطبيق ممتلئة."
}
}
- }
\ No newline at end of file
+ },
+ "HomeScreenKebabPopUp": {
+ "title": "المزيد من الخيارات",
+ "unPinCard": "قم بفك البطاقة",
+ "pinCard": "البطاقة الشخصية",
+ "offlineAuthenticationDisabled!": "التنشيط معلق لتسجيل الدخول عبر الإنترنت!",
+ "offlineAuthDisabledMessage": "انقر هنا لتمكين استخدام بيانات الاعتماد هذه للمصادقة عبر الإنترنت.",
+ "viewActivityLog": "عرض سجل النشاط",
+ "removeFromWallet": "إزالة من المحفظة",
+ "revokeId": "إبطال الهوية",
+ "revokeMessage": "إبطال المعرف الظاهري لملف التعريف هذا"
+ },
+ "WalletBinding": {
+ "inProgress": "في تَقَدم",
+ "profileAuthenticated": "تم التنشيط لتسجيل الدخول عبر الإنترنت!"
+ },
+ "BindingVcWarningOverlay": {
+ "alert": "يرجى تأكيد",
+ "BindingWarning": "إذا قمت بتمكين التحقق من بيانات الاعتماد هذه في محفظة أخرى ، فسيتم تجاوزها. هل تريد المتابعة؟",
+ "yesConfirm": "نعم ، أؤكد",
+ "no": "لا"
+ },
+ "RemoveVcWarningOverlay": {
+ "alert": "يرجى تأكيد",
+ "removeWarning": "هل تريد حقًا إزالة البطاقة",
+ "confirm": "يتأكد",
+ "no": "لا"
+ },
+ "AuthScreen": {
+ "header": "هل ترغب في استخدام المقاييس الحيوية لفتح التطبيق؟",
+ "Description": "هل ترغب في استخدام المقاييس الحيوية لفتح التطبيق؟",
+ "useBiometrics": "استخدام القياسات الحيوية",
+ "usePasscode": "मأفضل استخدام رمز مرور",
+ "errors": {
+ "unavailable": "س الحيوية",
+ "unenrolled": "إصبعك في إعدادات جهازك",
+ "failed": "الحيوية",
+ "generic": "الحيوية"
+ }
+ },
+ "BiometricScreen": {
+ "unlock": "افتح ببصمة الإصبع"
+ },
+ "HistoryScreen": {
+ "noHistory": "لا يوجد سجل حتى الان",
+ "downloaded": "يملك",
+ "shared": "مشترك",
+ "received": "تلقى",
+ "deleted": "إزالة"
+ },
+ "SettingScreen": {
+ "header": "إعدادات",
+ "injiAsVerifierApp": " كتطبيق للتحقق إنجي",
+ "receiveCard": "البطاقة المستلمة",
+ "basicSettings": "الإعدادات الأساسية",
+ "bioUnlock": "افتح مع القياسات الحيوية",
+ "language": "لغة",
+ "aboutInji": "حول إنجي",
+ "credentialRegistry": "سجل الاعتماد",
+ "errorMessage": "تم إدخال عنوان URL غير صحيح. الرجاء إدخال عنوان URL صالح للمتابعة.",
+ "injiTourGuide": "مرشد إنجي السياحي",
+ "logout": "تسجيل خروج",
+ "resetInjiProps": "إعادة تعيين دعائم إنجي ..."
+ },
+ "AboutInji": {
+ "aboutInji": "حول إنجي",
+ "header": "حول إنجي",
+ "appID": "ID طبيق",
+ "aboutDetailes": "إنجي هو تطبيق جوال يمكن استخدامه كمحفظة رقمية لتخزين بيانات الاعتماد. كما يسمح بالتحقق من الهوية في الوضعين غير المتصلين بالإنترنت وفي أي مكان وزمان.",
+ "forMoreDetailes": "لمزيد من التفاصيل",
+ "clickHere": "انقر هنا",
+ "version": "الإصدار",
+ "tuvaliVersion": "نسخة توفالي"
+ },
+ "HelpScreen": {
+ "header": "يساعد",
+ "whatIsDigitalCredential?": "ما هو الاعتماد الرقمي؟",
+ "detail-1": "بيانات الاعتماد الرقمية هي النسخة الرقمية لبطاقة الهوية الفعلية الخاصة بك",
+ "whatCanDoWithDigitalCredential?": "ماذا يمكننا أن نفعل ببيانات الاعتماد الرقمية؟",
+ "detail-2": "يمكنك الاستفادة من مختلف الخدمات الحكومية والخاصة باستخدام بيانات الاعتماد الرقمية الخاصة بك.",
+ "howToAddCard?": "كيف تضيف بطاقة؟",
+ "detail-3": "لإضافة بطاقة ، انقر فوق الزر '+' في الصفحة الرئيسية وحدد الخيار المناسب.",
+ "howToRemoveCardFromWallet?": "كيف تشارك البطاقة؟",
+ "detail-4": "اسحب لليسار على البطاقة> انقر فوق المزيد> إزالة من المحفظة",
+ "canWeAddMultipleCards?": "هل يمكننا إضافة عدة بطاقات؟",
+ "detail-5": "نعم ، يمكنك إضافة عدة بطاقات إلى المحفظة بالنقر فوق الزر '+' في الصفحة الرئيسية.",
+ "howToShareCard?": "كيف تشارك البطاقة؟",
+ "detail-6": "انقر فوق الزر 'مشاركة' وقم بمسح رمز الاستجابة السريعة ضوئيًا من الطرف الطالب. بمجرد إنشاء الاتصال ، ستتم مشاركة البطاقة.",
+ "howToActivateCardForOnlineLogin?": "كيف يتم تفعيل البطاقة لتسجيل الدخول عبر الإنترنت؟",
+ "detail-7": "بعد إضافة بطاقة إلى المحفظة بنجاح ، انقر فوق 'تعليق التنشيط لتسجيل الدخول عبر الإنترنت' على البطاقة. عند النقر فوق 'تنشيط' ، ستكون البطاقة جاهزة للاستخدام لتسجيل الدخول عبر الإنترنت.",
+ "howToViewActivity?": "كيفية عرض سجلات النشاط؟",
+ "detail-8": "في الصفحة الرئيسية ، انقر فوق 'المحفوظات' لعرض تفاصيل نشاط المستخدم.",
+ "whatCanDoBiometricsChanged?": "ماذا يحدث عندما يتم تغيير المقاييس الحيوية لمخزن مفاتيح ذكري المظهر؟",
+ "detail-9": "يحتوي ملف تخزين مفاتيح ذكري المظهر على معلومات مهمة مثل المفاتيح الخاصة لإثباتات الهوية. عندما تقوم بتغيير القياسات الحيوية الخاصة بك ، فإن المفاتيح القديمة لم تعد آمنة. للحفاظ على أمان الأشياء ، نقوم بإزالة إثبات الهوية الموقعة بواسطة تلك المفاتيح القديمة. يمكنك ببساطة تنزيل إثباتات هويتك مرة أخرى ، وسيتم توقيعها بأحدث المفاتيح وأكثرها أمانًا."
+ },
+ "AddVcModal": {
+ "requestingCredential": "جارٍ طلب بيانات الاعتماد...",
+ "errors": {
+ "input": {
+ "empty": "فارغًا",
+ "invalidFormat": "غير صحيح"
+ },
+ "backend": {
+ "invalidOtp": "OTP غير صالح",
+ "expiredOtp": "انتهت صلاحية كلمة المرور لمرة واحدة",
+ "invalidUin": "UIN غير صالح",
+ "invalidVid": "VID غير صالح",
+ "missingUin": "تم إلغاء تنشيط / حظر UIN الذي تم إدخاله. الرجاء إدخال UIN صالح للمتابعة",
+ "missingVid": "VID غير متوفر في قاعدة البيانات",
+ "noMessageAvailable": "حاول بعد فترةe",
+ "whileGeneratingOtpErrorIsOccured": "أثناء إنشاء خطأ OTP",
+ "networkRequestFailed": "فشل طلب الشبكة",
+ "deactivatedVid": "تم إلغاء تنشيط / انتهاء صلاحية VID المُدخل. الرجاء إدخال VID صالح للمتابعة"
+ }
+ }
+ },
+ "GetVcModal": {
+ "retrievingId": "استرجاع الهوية",
+ "errors": {
+ "input": {
+ "empty": "لا يمكن أن يكون الإدخال فارغًا",
+ "invalidFormat": "تنسيق الإدخال غير صحيح"
+ },
+ "backend": {
+ "invalidOtp": "OTP غير صالح",
+ "expiredOtp": "انتهت صلاحية كلمة المرور لمرة واحدة",
+ "applicationProcessing": "غير جاهز AID",
+ "noMessageAvailable": "حاول بعد فترة",
+ "networkRequestFailed": "فشل طلب الشبكة",
+ "invalidAid": "AID الذي تم إدخاله غير متوفر. يرجى التحقق من AID الخاص بك قبل الدخول",
+ "timeout": "نفذ الوقت"
+ }
+ }
+ },
+ "DownloadingVcModal": {
+ "header": "تنزيل ملفبطاقة",
+ "bodyText": "قد يستغرق هذا بعض الوقت ، وسنخبرك عندما يتم تنزيل بطاقة وإتاحته",
+ "backButton": "العودة إلى المنزل"
+ },
+ "GetIdInputModal": {
+ "header": "استرجع UIN / VID الخاص بك",
+ "applicationIdLabel": "الرجاء إدخال معرف التطبيق الخاص بك",
+ "enterApplicationId": "أدخل معرف التطبيق",
+ "requestingOTP": "جارٍ طلب OTP ...",
+ "qstnMarkToolTip": "معرف التطبيق متاح في الإقرار الذي تم استلامه بعد التسجيل.",
+ "getUIN": "احصل على UIN / VID"
+ },
+ "IdInputModal": {
+ "header": "استرجع هويتك",
+ "guideLabel": "حدد نوع المعرف وأدخل UIN أو VID المقدم من MOSIP للمعرف الذي ترغب في استرداده",
+ "generateVc": "إنشاء بطاقة",
+ "downloadID": "معرف التنزيل",
+ "enterId": "أدخل {{idType}}",
+ "noUIN/VID": "ليس لديك UIN / VID؟ ",
+ "getItHere": "احصل عليها الآن",
+ "requestingOTP": "جارٍ طلب OTP ..."
+ },
+ "OtpVerificationModal": {
+ "title": "التحقق من OTP",
+ "otpSentMessage": "لقد أرسلنا الرمز المكون من 6 أرقام إلى رقم هاتفك المحمول المسجل!",
+ "resendTheCode": "يمكنك إعادة إرسال الرمز بتنسيق ",
+ "resendCode": "أعد إرسال الرمز"
+ },
+ "MyVcsTab": {
+ "bringYourDigitalID": "أحضر هويتك الرقمية",
+ "generateVcDescription": "اضغط على \"إضافة بطاقة \" أدناه لتنزيل بطاقتك",
+ "downloadCard": "تحميل البطاقة",
+ "downloadingYourCard": "تنزيل بطاقتك ، قد يستغرق هذا ما يصل إلى 5 دقائق",
+ "errors": {
+ "savingFailed": {
+ "title": "فشل حفظ بطاقة",
+ "message": "حدث خطأ أثناء حفظ البطاقة في المتجر."
+ },
+ "storageLimitReached": {
+ "title": "بيانات التطبيق غير كافية",
+ "message": "لا يمكنك إضافة أو استلام بطاقات لأن بيانات التطبيق ممتلئة. امسح بيانات التطبيق للمتابعة."
+ },
+ "vcIsTampered": {
+ "title": "تم العبث ببعض إثباتات الهوية",
+ "message": "تتم إزالة الملفات المتأثرة ، يرجى إعادة التنزيل."
+ },
+ "keystoreNotExists": {
+ "title": "غير معثور عليه تخزين المفتاح الآمن",
+ "message": "تم إلغاء قفل تخزين المفاتيح على هاتفك. قد يتم تسريب مفاتيحك في حالة اختراق الهاتف.",
+ "riskOkayText": "حسنًا ، سأخاطر بذلك"
+ }
+ }
+ },
+ "OnboardingOverlay": {
+ "stepOneTitle": "مشاركة آمنة!",
+ "stepOneText": "احتفظ ببيانات الاعتماد الرقمية الخاصة بك معك في جميع الأوقات. يساعدك Inji على إدارتها واستخدامها بشكل فعال. للبدء ، أضف بطاقات إلى ملف التعريف الخاص بك.",
+ "stepTwoTitle": "المحفظة الرقمية الموثوقة",
+ "stepTwoText": "قم بتخزين وحمل جميع بطاقاتك المهمة في محفظة واحدة موثوق بها.",
+ "stepThreeTitle": "مشاركة آمنة",
+ "stepThreeText": "شارك بطاقاتك بأمان وبطريقة خالية من المتاعب واستفد من الخدمات المتنوعة.",
+ "stepFourTitle": "مصادقة خالية من المتاعب",
+ "stepFourText": "قم بمصادقة نفسك بسهولة باستخدام بيانات الاعتماد الرقمية المخزنة.",
+ "getStarted": "البدء",
+ "goBack": "عُد",
+ "back": "خلف",
+ "skip": "يتخطى",
+ "next": "التالي"
+ },
+ "ReceivedVcsTab": {
+ "receivedCards": "البطاقات المستلمة",
+ "header": "البطاقات المستلمة",
+ "noReceivedVcsTitle": "لا يوجد بطاقة متاح حتى الآن",
+ "noReceivedVcsText": "اضغط على الطلب أدناه لتلقيبطاقة"
+ },
+ "ViewVcModal": {
+ "title": "تفاصيل الهوية",
+ "inProgress": "في تَقَدم",
+ "cancel": "يلغي",
+ "lock": "قفل",
+ "unlock": "الغاء القفل",
+ "rename": "إعادة تسمية",
+ "delete": "يمسح",
+ "revoke": "سحب او إبطال",
+ "revoking": "تحتوي محفظتك على بيانات اعتماد مع VID {{vid}}. سيؤدي إبطال هذا إلى حذفه تلقائيًا من المحفظة. هل انت متأكد انك تريد المتابعة؟",
+ "requestingOtp": "جارٍ طلب OTP ...",
+ "editTag": "إعادة تسمية",
+ "redirecting": "إعادة توجيه...",
+ "success": {
+ "unlocked": "تم إلغاء قفل بطاقة بنجاح",
+ "locked": "تم قفل بطاقة بنجاح",
+ "revoked": "تم إبطال VID {{vid}}. ستتم إزالة أي بيانات اعتماد تحتوي على نفس الشيء تلقائيًا من المحفظة"
+ }
+ },
+ "MainLayout": {
+ "home": "المنزل",
+ "scan": "مسح",
+ "history": "تاريخ",
+ "request": "طلب",
+ "settings": "إعدادات"
+ },
+ "PasscodeScreen": {
+ "header": "تعيين رمز المرور",
+ "enterNewPassword": "أدخل رمز مرور جديد",
+ "reEnterPassword": "أعد إدخال رمز المرور الجديد",
+ "confirmPasscode": "قم بتأكيد رمز المرور",
+ "enterPasscode": "أدخل رمز المرور الخاص"
+ },
+ "AppMetaData": {
+ "header": "حول إنجي",
+ "version": "الإصدار",
+ "useBle": "مدعوم من BLE"
+ },
+ "QrScreen": {
+ "title": "QR تسجيل الدخول",
+ "alignQr": "قم بمحاذاة رمز الاستجابة السريعة داخل الإطار للمسح الضوئي",
+ "confirmation": "تأكيد",
+ "checkDomain": "تحقق أيضًا من وجود رمز قفل على شريط العناوين.",
+ "domainHead": "https://",
+ "selectId": "حدد المعرف",
+ "noBindedVc": "لا يوجد بطاقة مرتبط متاح للتحقق",
+ "back": "عُد",
+ "confirm": "يتأكد",
+ "verify": "تحقق",
+ "faceAuth": "مصادقة الوجه",
+ "consent": "موافقة",
+ "loading": "جار التحميل...",
+ "domainWarning": "يرجى تأكيد مجال موقع الويب الذي تقوم بمسح رمز الاستجابة السريعة منه على النحو التالي",
+ "access": " يطلب الوصول إلى",
+ "status": "حالة",
+ "successMessage": "لقد قمت بتسجيل الدخول بنجاح ",
+ "okay": "تمام",
+ "allow": "يسمح",
+ "cancel": "يلغي",
+ "essentialClaims": "الادعاءات الأساسية",
+ "voluntaryClaims": "المطالبات الطوعية",
+ "required": "مطلوب"
+ },
+ "ReceiveVcScreen": {
+ "header": "تفاصيل بطاقة",
+ "save": "احفظ بطاقة",
+ "verifyAndSave": "تحقق وحفظ",
+ "reject": "يرفض",
+ "discard": "ينبذ",
+ "goToReceivedVCTab": "عرض تم استلامه بطاقة",
+ "saving": "جارٍ حفظ البطاقة",
+ "errors": {
+ "savingFailed": {
+ "title": "فشل حفظ بطاقة",
+ "message": "حدث خطأ أثناء حفظ البطاقة في المتجر."
+ }
+ }
+ },
+ "RequestScreen": {
+ "receiveCard": "البطاقة المستلمة",
+ "bluetoothDenied": "يرجى تمكين بلوتوث لتتمكن من طلب البطاقة",
+ "bluetoothStateIos": "تم إيقاف تشغيل البلوتوث ، يرجى تشغيله من مركز التحكم",
+ "bluetoothStateAndroid": "تم إيقاف تشغيل البلوتوث ، يرجى تشغيله من قائمة الإعدادات السريعة",
+ "showQrCode": "اعرض رمز الاستجابة السريعة هذا لطلب المقيم بطاقة",
+ "incomingVc": "الوارد بطاقة",
+ "request": "طلب",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "مطلوب إذن الأجهزة المجاورة لتتمكن من طلب البطاقة",
+ "button": "السماح إذن"
+ },
+ "storageLimitReached": {
+ "title": "بيانات التطبيق غير كافية",
+ "message": "لا يمكنك إضافة أو استلام بطاقات لأن بيانات التطبيق ممتلئة. امسح بيانات التطبيق للمتابعة."
+ }
+ },
+ "status": {
+ "accepted": {
+ "title": "نجاح!",
+ "message": "تم استلام بطاقةبنجاح من محفظة"
+ },
+ "rejected": {
+ "title": " إشعار",
+ "message": "لقد رفضت محفظة بطاقة"
+ },
+ "disconnected": {
+ "title": "ير متصل",
+ "message": "انقطع الاتصال. يرجى المحاولة مرة أخرى."
+ },
+ "waitingConnection": "انتظار الاتصال ...",
+ "exchangingDeviceInfo": {
+ "message": "تبادل معلومات الجهاز...",
+ "timeoutHint": "يستغرق تبادل معلومات الجهاز وقتًا طويلاً..."
+ },
+ "connected": {
+ "message": "متصل بالجهاز. في انتظار بطاقة...",
+ "timeoutHint": "لم ترد بيانات حتى الآن. هل جهاز الإرسال لا يزال متصلاً؟"
+ },
+ "offline": {
+ "message": "يرجى الاتصال بالإنترنت لتمكين وضع المشاركة عبر الإنترنت"
+ },
+ "bleError": {
+ "title": "فشل التحويل!",
+ "message": "حدث خطأ أثناء نقل بطاقة. حاول مرة اخرى.",
+ "hint": "خطأ: {{code}}"
+ }
+ },
+ "online": "متصل",
+ "offline": "غير متصل على الانترنت",
+ "gotoSettings": "اذهب للاعدادات"
+ },
+ "ScanScreen": {
+ "header": "مسح رمز الاستجابة السريعة",
+ "noShareableVcs": "لا تتوفر بطاقات قابلة للمشاركة.",
+ "bluetoothStateAndroid": "يرجى تشغيل البلوتوث من الإعدادات السريعة لدعم المشاركة المحلية",
+ "bluetoothStateIos": "يرجى تشغيل البلوتوث من مركز التحكم لدعم المشاركة المحلية",
+ "enableBluetoothMessage": "يرجى تمكين أذونات البلوتوث لدعم المشاركة المحلية",
+ "enableBluetoothButtonText": "السماح لأذونات البلوتوث",
+ "scanningGuide": "امسك الهاتف بثبات وامسح رمز الاستجابة السريعة ضوئيًا",
+ "sharingVc": "مشاركة بطاقة ",
+ "errors": {
+ "locationDisabled": {
+ "message": "يجب تمكين خدمات الموقع لمشاركة البطاقة",
+ "button": "تمكين خدمات الموقع"
+ },
+ "locationDenied": {
+ "message": "مطلوب إذن الموقع لمشاركة البطاقة",
+ "button": "الموقع"
+ },
+ "nearbyDevicesPermissionDenied": {
+ "message": "مطلوب إذن \"الأجهزة المجاورة\" لتتمكن من مشاركة البطاقة",
+ "button": "السماح إذن"
+ },
+ "storageLimitReached": {
+ "title": "بيانات التطبيق غير كافية",
+ "message": "لا يمكنك مشاركة البطاقات لأن بيانات التطبيق ممتلئة. امسح بيانات التطبيق للمتابعة."
+ }
+ },
+ "status": {
+ "inProgress": "في تَقَدم",
+ "establishingConnection": "اجراء اتصال",
+ "sharingInProgress": "جاري المشاركة",
+ "connectingTimeout": "يستغرق إنشاء الاتصال بعض الوقت. هل الجهاز الآخر مفتوح للاتصالات؟",
+ "exchangingDeviceInfo": "تبادل معلومات الجهاز ...",
+ "exchangingDeviceInfoTimeout": "يستغرق الأمر بعض الوقت لتبادل معلومات الجهاز. قد تضطر إلى إعادة الاتصال.",
+ "invalid": "رمز الاستجابة السريعة غير صالح",
+ "offline": "يرجى الاتصال بالإنترنت لمسح رموز QR ضوئيًا باستخدام وضع المشاركة عبر الإنترنت",
+ "sent": "تم إرسال بطاقة ...",
+ "sentHint": "في انتظار أن يحفظ المستلم بطاقة أو يتجاهلها",
+ "sharing": {
+ "title": "مشاركة...",
+ "hint": "يرجى الانتظار حتى نشارك البطاقة المختارة.",
+ "timeoutHint": "تستغرق مشاركتها وقتًا أطول من المتوقع. قد تكون هناك مشكلة في الاتصال."
+ },
+ "accepted": {
+ "title": "تم مشاركة المعرف بنجاح",
+ "message": "تمت مشاركة بطاقة بنجاح مع المدقق",
+ "gotohome": "اذهب الى المنزل"
+ },
+ "rejected": {
+ "title": "يلاحظ",
+ "message": "تم تجاهل بطاقة بواسطة المدقق"
+ },
+ "bleError": {
+ "title": "فشل التحويل!",
+ "message": "حدث خطأ أثناء نقل بطاقة . حاول مرة اخرى.",
+ "hint": "خطأ: {{code}}"
+ }
+ }
+ },
+ "SelectVcOverlay": {
+ "header": "يشارك بطاقة",
+ "chooseVc": "اختر بطاقة الذي ترغب في المشاركة معه",
+ "share": "شارك",
+ "verifyAndShare": "التحقق من الهوية والمشاركة"
+ },
+ "SendVcScreen": {
+ "reasonForSharing": "سبب المشاركة (اختياري)",
+ "acceptRequest": "يشارك",
+ "acceptRequestAndVerify": "شارك مع سيلفي",
+ "reject": "رفض",
+ "consentToPhotoVerification": "أوافق على التقاط صورتي للمصادقة",
+ "pleaseSelectAnId": "الرجاء تحديد معرف",
+ "status": {
+ "sharing": {
+ "title": "مشاركة...",
+ "hint": "الرجاء الانتظار حتى يقبل الجهاز المتلقي المشاركة أو يرفضها.",
+ "timeoutHint": "تستغرق مشاركتها وقتًا أطول من المتوقع. قد تكون هناك مشكلة في الاتصال."
+ },
+ "accepted": {
+ "title": "النجاح!",
+ "message": "تمت مشاركة بطاقة بنجاح مع المدقق"
+ },
+ "rejected": {
+ "title": "تنويه",
+ "message": "تم رفض بطاقة من قِبل المدقق"
+ }
+ }
+ },
+ "VerifyIdentityOverlay": {
+ "faceAuth": "مصادقة الوجه",
+ "status": {
+ "verifyingIdentity": "التحقق من الهوية..."
+ },
+ "errors": {
+ "invalidIdentity": {
+ "title": "تعذر التحقق من الهوية",
+ "message": "الوجه غير معروف. حاول مرة اخرى.",
+ "messageNoRetry": "الوجه غير معروف."
+ }
+ }
+ },
+ "WelcomeScreen": {
+ "title": "حل هوية مفتوحة المصدر",
+ "getStarted": "البدء",
+ "unlockApp": "فتح التطبيق",
+ "failedToReadKeys": "فشلت قراءة المفاتيح",
+ "retryRead": "هل تريد إعادة المحاولة؟",
+ "errors": {
+ "decryptionFailed": "فشل في فك تشفير البيانات",
+ "invalidateKeyError": {
+ "title": "تمت إزالة بعض البطاقات لدواعي أمنية.",
+ "message": "يرجى إعادة التنزيل."
+ }
+ },
+ "ignore": "يتجاهل"
+ },
+ "SetupLanguage": {
+ "header": "حدد اللغة",
+ "description": "اختر لغتك المفضلة",
+ "save": "حفظ التفضيل"
+ },
+ "common": {
+ "cancel": "إلغاء",
+ "accept": "يقبل",
+ "save": "حفظ",
+ "dismiss": "رفض",
+ "editLabel": "يحرر {{label}}",
+ "tryAgain": "حاول مجددا",
+ "ignore": "يتجاهل",
+ "camera": {
+ "errors": {
+ "missingPermission": "يستخدم هذا التطبيق الكاميرا لمسح رمز الاستجابة السريعة لجهاز آخر."
+ },
+ "allowAccess": "اسمح بالوصول إلى الكاميرا"
+ },
+ "errors": {
+ "genericError": "هناك شئ غير صحيح. الرجاء معاودة المحاولة في وقت لاحق!"
+ },
+ "clipboard": {
+ "copy": "ينسخ",
+ "copied": "نسخ"
+ },
+ "biometricPopup": {
+ "title": "فتح التطبيق",
+ "description": "يرجى استخدام بصمة الإصبع لفتح التطبيق"
+ }
+ }
+}
diff --git a/locales/en.json b/locales/en.json
index 7a59c03e..351f2b04 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -11,13 +11,18 @@
"VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "received. Presence verification failed",
"PRESENCE_VERIFIED_AND_VC_SHARED": "verified and shared",
"PRESENCE_VERIFICATION_FAILED": "verification failed",
- "QRLOGIN_SUCCESFULL": "QRLogin sucessfull"
+ "QRLOGIN_SUCCESFULL": "QRLogin successful",
+ "WALLET_BINDING_SUCCESSFULL": "Activation successful",
+ "WALLET_BINDING_FAILURE": "Activation failed",
+ "VC_REMOVED":"Removed from wallet"
},
"DeviceInfoList": {
"requestedBy": "Requested by",
"sentBy": "Sent by",
"deviceRefNumber": "Device reference number",
- "name": "Name"
+ "name": "Name",
+ "Verifier": "Verifier",
+ "Wallet": "Wallet"
},
"FaceScanner": {},
"OIDcAuth": {
@@ -29,8 +34,9 @@
"passcodeMismatchError": "Passcode did not match."
},
"QrScanner": {
- "missingPermissionText": "This app uses the camera to scan the QR code of another device.",
- "allowCameraButton": "Allow access to camera"
+ "cameraAccessDisabled": "Camera access disabled!",
+ "cameraPermissionGuideLabel": "Go to settings and enable the camera access manually.",
+ "flipCamera": "Flip Camera"
},
"VcDetails": {
"generatedOn": "Generated on",
@@ -46,18 +52,65 @@
"reasonForSharing": "Reason for sharing",
"idType": "ID type",
"id": "Id",
+ "qrCodeHeader": "QR Code",
"nationalCard": "National Card",
"uin": "UIN",
"vid": "VID",
- "enableVerification": "Enable Verification",
- "profileAuthenticated": "Profile is authenticated!",
- "offlineAuthDisabledHeader": "Offline Authentication disabled!",
- "offlineAuthDisabledMessage": "Click 'Enable Authentication' to enable this credentials to be used for offline authentication."
+ "enableVerification": "Activate",
+ "profileAuthenticated": "Activated for online login!",
+ "offlineAuthDisabledHeader": "Activation pending for online login!",
+ "offlineAuthDisabledMessage": "Please click the button below to activate this credential to be used for online login.",
+ "verificationEnabledSuccess": "Activated for online login",
+ "goback": "GO BACK",
+ "BindingWarning": "If you have enabled verification for this credential on another wallet, it will get overridden. Do you want to proceed?",
+ "yes_confirm": "Yes, I Confirm",
+ "no": "No",
+ "Alert": "Alert",
+ "ok": "Okay",
+ "credentialRegistry": "Credential Registry",
+ "errors": {
+ "savingFailed": {
+ "title": "Failed to save the Card",
+ "message": "Something went wrong while saving Card to the store."
+ },
+ "diskFullError": {
+ "title": "Failed to save the Card",
+ "message": "No more Cards can be received or saved as App Data is full."
+ }
+ }
+ },
+ "HomeScreenKebabPopUp": {
+ "title": "More Options",
+ "unPinCard": "Unpin Card",
+ "pinCard": "Pin Card",
+ "offlineAuthenticationDisabled!": "Activation pending for online login!",
+ "offlineAuthDisabledMessage": "Click here to enable this credentials to be used for online authentication.",
+ "viewActivityLog": "View Activity Log",
+ "removeFromWallet": "Remove from Wallet",
+ "revokeId": "Revoke ID",
+ "revokeMessage": "Revoke the virtual ID for this profile"
+ },
+ "WalletBinding": {
+ "inProgress": "In progress",
+ "profileAuthenticated": "Activated for online login!"
+ },
+ "BindingVcWarningOverlay": {
+ "alert": "Alert",
+ "BindingWarning": "You have already activated online login for this credential on another device. You will no longer be able to use that device for login if you activate it again on this device. Do you want to proceed?",
+ "yesConfirm": "Yes, I Confirm",
+ "no": "No"
+ },
+ "RemoveVcWarningOverlay": {
+ "alert": "Please Confirm",
+ "removeWarning": "Do you want to remove this card?",
+ "confirm": "Yes, I confirm",
+ "no": "No"
},
"AuthScreen": {
- "header": "Would you like to use biometrics to unlock the application?",
- "useBiometrics": "Use biometrics",
- "usePasscode": "I'd rather use a passcode",
+ "header": "Select App Unlock Method",
+ "Description": "Would you like to use biometrics to unlock the application?",
+ "useBiometrics": "Use Biometrics",
+ "usePasscode": "Use Passcode",
"errors": {
"unavailable": "Device does not support Biometrics",
"unenrolled": "To use Biometrics, please enroll your biometrics in your device settings",
@@ -68,17 +121,57 @@
"BiometricScreen": {
"unlock": "Unlock with biometrics"
},
- "HistoryTab": {
+ "HistoryScreen": {
"noHistory": "No history available yet",
"downloaded": "downloaded",
"shared": "shared",
"received": "received",
"deleted": "deleted"
},
- "HomeScreen": {
- "myVcsTab": "My\n{{vcLabel}}",
- "receivedVcsTab": "Received\n{{vcLabel}}",
- "historyTab": "History"
+ "SettingScreen": {
+ "header": "Settings",
+ "injiAsVerifierApp": "Inji as verifier app",
+ "receiveCard": "Receive Card",
+ "basicSettings": "Basic settings",
+ "bioUnlock": "Unlock with Biometric",
+ "language": "Language",
+ "aboutInji": "About Inji",
+ "credentialRegistry": "Credential Registry",
+ "errorMessage": "Incorrect URL entered. Please enter a valid URL to proceed.",
+ "injiTourGuide": "Inji Tour Guide",
+ "logout": "Logout",
+ "resetInjiProps": "Resetting Inji Props..."
+ },
+ "AboutInji": {
+ "aboutInji": "About Inji",
+ "header": "ABOUT INJI",
+ "appID": "App ID",
+ "aboutDetailes": "Inji is a mobile app that can be used as a digital wallet to store credentials. It also allows identity verification in both offline and online modes, at any place and time.",
+ "forMoreDetailes": "For more details",
+ "clickHere": "Click here",
+ "version": "Version",
+ "tuvaliVersion": "Tuvali-version"
+ },
+ "HelpScreen": {
+ "header": "Help",
+ "whatIsDigitalCredential?": "What is a digital credential?",
+ "detail-1": "A digital credential is the digital version of your physical Identity card",
+ "whatCanDoWithDigitalCredential?": "What can we do with digital credentials?",
+ "detail-2": "You can avail various Government and private services using your digital credentials.",
+ "howToAddCard?": "How to add a card?",
+ "detail-3": "To add a card, click on '+' button on the Home page and select the appropriate option.",
+ "howToRemoveCardFromWallet?": "How to share a card?",
+ "detail-4": "Swipe left on the card > click on More > Remove from Wallet",
+ "canWeAddMultipleCards?": "Can we add multiple cards?",
+ "detail-5": "Yes, you can add multiple cards to the wallet by clicking on '+' button on the Home page.",
+ "howToShareCard?": "How to share a card?",
+ "detail-6": "Click on 'Share' button and scan the QR code from the requesting party. Once the connection is established, the card will be shared.",
+ "howToActivateCardForOnlineLogin?": "How to activate a card for online login?",
+ "detail-7": "After successfully adding a card to the wallet, click on 'Activation pending for Online login' on the card. On clicking on 'Activate', the card will be ready to be used for online login.",
+ "howToViewActivity?": "How to view activity logs?",
+ "detail-8": "On the Home page, click on 'History' to view the details of the user's activitie.",
+ "whatCanDoBiometricsChanged?": "What happens when Android keystore biometric is changed?",
+ "detail-9": "The Android keystore holds important information like private keys for identity proofs. When you change your biometrics, old keys are no longer safe. To keep things secure, we remove identity proofs signed by those old keys. You can simply download your identity proofs again, and they will be signed with the latest, safer keys."
},
"AddVcModal": {
"requestingCredential": "Requesting credential...",
@@ -89,54 +182,114 @@
},
"backend": {
"invalidOtp": "OTP is invalid",
+ "expiredOtp": "OTP has expired",
"invalidUin": "UIN invalid",
"invalidVid": "VID invalid",
- "missingUin": "UIN not available in database",
- "missingVid": "VID not available in database"
+ "missingUin": "The entered UIN is deactivated/blocked. Please enter a valid UIN to proceed",
+ "missingVid": "VID not available in database",
+ "noMessageAvailable": "Try after sometime",
+ "whileGeneratingOtpErrorIsOccured": "while generating otp error is occurred",
+ "networkRequestFailed": "Network request failed",
+ "deactivatedVid": "The entered VID is deactivated/expired. Please enter a valid VID to proceed"
+ }
+ }
+ },
+ "GetVcModal": {
+ "retrievingId": "Retrieving ID",
+ "errors": {
+ "input": {
+ "empty": "Input cannot be empty",
+ "invalidFormat": "The input format is incorrect"
+ },
+ "backend": {
+ "invalidOtp": "Invalid OTP",
+ "expiredOtp": "OTP has expired",
+ "applicationProcessing": "AID is not ready yet",
+ "noMessageAvailable": "Try after sometime",
+ "networkRequestFailed": "Network request failed",
+ "invalidAid": "AID entered is not available. Please check your AID before entering",
+ "timeout": "Timeout"
}
}
},
"DownloadingVcModal": {
- "header": "Downloading your {{vcLabel}}",
- "bodyText": "This may take some time, we will notify you when your {{vcLabel}} has been downloaded and is available",
+ "header": "Downloading your card",
+ "bodyText": "This may take sometime, we will notify you when your card has been downloaded and is available",
"backButton": "Back home"
},
"GetIdInputModal": {
- "header": "To retrieve your UIN or VID, enter your application {{vcLabel}} number",
- "getUIN": "Get UIN/VID",
- "applicationId": "Application {{vcLabel}} number",
+ "header": "Retrieve your UIN/VID",
+ "applicationIdLabel": "Please enter your Application ID",
+ "enterApplicationId": "Enter Application ID",
"requestingOTP": "Requesting OTP...",
- "qstnMarkToolTip": "Application {{vcLabel}} Number is printed on the acknowledgment provided after enrollment"
+ "qstnMarkToolTip": "Application ID is available in the acknowledgement received after enrolment.",
+ "getUIN": "Get UIN/VID"
},
"IdInputModal": {
- "header": "Enter the MOSIP-provided UIN or VID of the {{vcLabel}} you wish to retrieve",
- "generateVc": "Generate {{vcLabel}}",
- "enterId": "Enter your {{idType}}",
- "noUIN/VID": "Don't have your UIN/VID? Get it here",
+ "header": "Retrieve your ID",
+ "guideLabel": "Select ID type and enter the MOSIP provided UIN or VID of the ID you wish to retrieve",
+ "generateVc": "Generate Card",
+ "downloadID": "Download ID",
+ "enterId": "Enter ID",
+ "noUIN/VID": "Don’t have UIN/VID? ",
+ "getItHere": "Get it now",
"requestingOTP": "Requesting OTP..."
},
"OtpVerificationModal": {
- "enterOtp": "Enter the 6-digit verification code we sent you"
+ "title": "OTP Verification",
+ "otpSentMessage": "We've sent the 6 digit code to your registered mobile number!",
+ "resendTheCode": "You can resend the code in ",
+ "resendCode": "Resend Code"
},
"MyVcsTab": {
- "addVcButton": "Add {{vcLabel}}",
- "generateVc": "Generate your {{vcLabel}}",
- "generateVcDescription": "Tap on \"Add {{vcLabel}}\" below to download your {{vcLabel}}"
+ "bringYourDigitalID": "Bring your digital identity",
+ "generateVcDescription": "Tap on \"Download card\" below to download your card",
+ "downloadCard": "Download Card",
+ "downloadingYourCard": "Downloading your card, this can take upto 5 minutes",
+ "errors": {
+ "savingFailed": {
+ "title": "Failed to save the Card",
+ "message": "Something went wrong while saving Card to the store."
+ },
+ "storageLimitReached": {
+ "title": "Insufficient Appdata",
+ "message": "You cannot add or receive cards since the Appdata is full. Clear Appdata to proceed."
+ },
+ "vcIsTampered": {
+ "title": "Some identity proofs are tampered",
+ "message": "Affected files are removed, please re-download."
+ },
+ "keystoreNotExists": {
+ "title": "Secure Key Storage not found",
+ "message": "The key storage on your phone is not secured. Your keys could be leaked if phone is hacked.",
+ "riskOkayText": "OK, I'll risk it"
+ }
+ }
},
"OnboardingOverlay": {
"stepOneTitle": "Welcome!",
- "stepOneText": "Keep your digital credential with you at all times. To get started, add {{vcLabel}} to your profile.",
- "stepTwoTitle": "{{vcLabel}} management",
- "stepTwoText": "Once generated, {{vcLabel}} are safely stored on your mobile and can be renamed or shared at any time.",
- "stepThreeTitle": "Easy sharing",
- "stepThreeText": "Share and receive {{vcLabel}} switfly using your phone camera to scan QR codes.",
- "stepThreeButton": "Get started and add {{vcLabel}}"
+ "stepOneText": "Keep your digital credential with you at all times. Inji helps you manage and use them effectively. To get started, add cards to your profile.",
+ "stepTwoTitle": "Trusted Digital Wallet",
+ "stepTwoText": "Store and carry all your important cards in a single trusted wallet.",
+ "stepThreeTitle": "Secure Sharing",
+ "stepThreeText": "Share your cards securely in a hassle free way and avail various services.",
+ "stepFourTitle": "Hassle free authentication",
+ "stepFourText": "Authenticate yourself with ease using the stored digital credential.",
+ "getStarted": "Get Started",
+ "goBack": "Go Back",
+ "back": "Back",
+ "skip": "Skip",
+ "next": "Next"
},
"ReceivedVcsTab": {
- "noReceivedVcsTitle": "No {{vcLabel}} available yet",
- "noReceivedVcsText": "Tap on Request below to receive {{vcLabel}}"
+ "receivedCards": "Received Cards",
+ "header": "Received Cards",
+ "noReceivedVcsTitle": "No card available yet",
+ "noReceivedVcsText": "Tap on Request below to receive card"
},
"ViewVcModal": {
+ "title": "ID Details",
+ "inProgress": "In Progress",
"cancel": "Cancel",
"lock": "Lock",
"unlock": "Unlock",
@@ -148,61 +301,96 @@
"editTag": "Rename",
"redirecting": "Redirecting...",
"success": {
- "unlocked": "{{vcLabel}} successfully unlocked",
- "locked": "{{vcLabel}} successfully locked",
+ "unlocked": "Card successfully unlocked",
+ "locked": "Card successfully locked",
"revoked": "VID {{vid}} has been revoked. Any credential containing the same will be removed automatically from the wallet"
}
},
"MainLayout": {
"home": "Home",
"scan": "Scan",
+ "history": "History",
"request": "Request",
- "profile": "Profile"
+ "settings": "Settings"
},
"PasscodeScreen": {
- "header": "Set a passcode to secure your application",
- "confirmPasscode": "Confirm your passcode",
+ "header": "Set Passcode",
+ "enterNewPassword": "Enter a new passcode",
+ "reEnterPassword": "Re-enter the new passcode",
+ "confirmPasscode": "Confirm passcode",
"enterPasscode": "Enter your passcode"
},
- "Credits": {
- "header": "Credits and legal notices",
- "back": "Back"
+ "AppMetaData": {
+ "header": "About Inji",
+ "version": "Version",
+ "useBle": "Powered by BLE"
},
- "ProfileScreen": {
- "name": "Name",
- "vcLabel": "VC Label",
- "language": "Language",
- "bioUnlock": "Biometric unlock",
- "authFactorUnlock": "Unlock auth factor",
- "credits": "Credits and legal notices",
- "logout": "Log-out",
- "revokeLabel": "Revoke VID",
- "revokeHeader": "REVOKE VID",
- "revokingVids": "You are about to revoke ({{count}}) VIDs.",
- "revokingVidsAfter": "This means you will no longer be able to use or view any of the IDs linked to those VID(s). \nAre you sure you want to proceed?",
- "empty": "Empty",
- "revokeSuccessful": "VID successfully revoked",
- "version": "Version"
+ "QrScreen": {
+ "title": "QR Login",
+ "alignQr": "Align the QR code within the frame to scan",
+ "confirmation": "Confirmation",
+ "checkDomain": "Also, check for a lock icon in the address bar.",
+ "domainHead": "https://",
+ "selectId": "Select an ID",
+ "noBindedVc": "There is no binded card available to verify",
+ "back": "Come back",
+ "confirm": "Confirm",
+ "verify": "Verify",
+ "faceAuth": "Face Authentication",
+ "consent": "Consent",
+ "loading": "Loading...",
+ "domainWarning": "Please confirm the domain of the website you are scanning the QR code from below",
+ "access": " is requesting access to",
+ "status": "Status",
+ "successMessage": "You are successfully logged in ",
+ "okay": "All right",
+ "allow": "Allow",
+ "cancel": "Cancel",
+ "essentialClaims": "Important Claims",
+ "voluntaryClaims": "Voluntary Claims",
+ "required": "It is necessary"
},
"ReceiveVcScreen": {
- "header": "{{vcLabel}} details",
- "save": "Save {{vcLabel}}",
+ "header": "Card details",
+ "save": "Save card",
"verifyAndSave": "Verify and save",
- "discard": "Discard"
+ "reject": "Reject",
+ "discard": "Discard",
+ "goToReceivedVCTab": "View Received card",
+ "saving": "Card is being saved",
+ "errors": {
+ "savingFailed": {
+ "title": "Failed to save the card",
+ "message": "Something went wrong while saving card to the store."
+ }
+ }
},
"RequestScreen": {
- "bluetoothDenied": "Please enable Bluetooth to be able to request {{vcLabel}}",
- "showQrCode": "Show this QR code to request {{vcLabel}}",
- "incomingVc": "Incoming {{vcLabel}}",
+ "receiveCard": "Receive Card",
+ "bluetoothDenied": "Please enable Bluetooth to be able to request card",
+ "bluetoothStateIos": "Bluetooth is turned OFF, please turn it ON from Control center",
+ "bluetoothStateAndroid": "Bluetooth is turned OFF, please turn it ON from Quick settings menu",
+ "showQrCode": "Display this QR code to request resident Card",
+ "incomingVc": "Incoming Card",
"request": "Request",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "Nearby Devices permission is required to be able to request Card",
+ "button": "Allow Permission"
+ },
+ "storageLimitReached": {
+ "title": "Insufficient Appdata",
+ "message": "You cannot add or receive cards since the Appdata is full. Clear Appdata to proceed."
+ }
+ },
"status": {
"accepted": {
"title": "Success!",
- "message": "{{vcLabel}} has been successfully received from {{sender}}"
+ "message": "Card has been successfully received from Wallet"
},
"rejected": {
"title": "Notice",
- "message": "You discarded {{sender}}'s {{vcLabel}}"
+ "message": "You discarded Wallet's Card"
},
"disconnected": {
"title": "Disconnected",
@@ -214,11 +402,16 @@
"timeoutHint": "It's taking too long to exchange device info..."
},
"connected": {
- "message": "Connected to the device. Waiting for {{vcLabel}}...",
+ "message": "Connected to the device. Waiting for card...",
"timeoutHint": "No data received yet. Is sending device still connected?"
},
"offline": {
"message": "Please connect to the internet to enable Online sharing mode"
+ },
+ "bleError": {
+ "title": "Failed to transfer!",
+ "message": "Something went wrong while transferring card. Please try again.",
+ "hint": "Error: {{code}}"
}
},
"online": "Online",
@@ -227,83 +420,149 @@
},
"ScanScreen": {
"header": "Scan QR Code",
- "noShareableVcs": "No shareable {{vcLabel}} are available.",
- "sharingVc": "Sharing {{vcLabel}}",
+ "noShareableVcs": "No shareable card are available.",
+ "sharingVc": "Sharing card",
+ "bluetoothStateIos": "Bluetooth is turned OFF, please turn it ON from Control center",
+ "bluetoothStateAndroid": "Bluetooth is turned OFF, please turn it ON from Quick settings menu",
+ "enableBluetoothMessage": "Please enable bluetooth permissions to support local sharing",
+ "enableBluetoothButtonText": "Allow bluetooth permissions",
+ "scanningGuide": "Hold the phone steady and scan the QR code",
"errors": {
"locationDisabled": {
- "message": "Location services must be enabled for the scanning functionality",
+ "message": "Location services must be enabled to share card",
"button": "Enable location services"
},
"locationDenied": {
- "message": "Location permission is required for the scanning functionality",
+ "message": "Location permission is required to share card",
"button": "Allow access to location"
+ },
+ "nearbyDevicesPermissionDenied": {
+ "message": "Nearby Devices permission is required to be able to share card",
+ "button": "Allow Permission"
+ },
+ "storageLimitReached": {
+ "title": "Insufficient Appdata",
+ "message": "You cannot share cards since the Appdata is full. Clear Appdata to proceed."
}
},
"status": {
- "connecting": "Connecting...",
+ "inProgress": "In progress",
+ "establishingConnection": "Establishing connection",
+ "sharingInProgress": "Sharing in Progress",
"connectingTimeout": "It's taking a while to establish the connection. Is the other device open for connections?",
"exchangingDeviceInfo": "Exchanging device info...",
"exchangingDeviceInfoTimeout": "It's taking a while to exchange device info. You may have to reconnect.",
"invalid": "Invalid QR Code",
"offline": "Please connect to the internet to scan QR codes using Online sharing mode",
- "sent": "{{ vcLabel }} has been sent...",
- "sentHint": "Waiting for receiver to save or discard your {{ vcLabel }}",
+ "sent": "Card has been sent...",
+ "sentHint": "Waiting for receiver to save or discard your Card",
"sharing": {
"title": "Sharing...",
- "hint": "Please wait for the receiving device to accept or reject the share.",
+ "hint": "Please wait while we share the chosen card.",
"timeoutHint": "It's taking longer than expected to share. There could be a problem with the connection."
},
"accepted": {
"title": "Success!",
- "message": "Your {{vcLabel}} has been successfully shared with {{receiver}}"
+ "message": "Your Card has been successfully shared with Verifier",
+ "gotohome": "Go to Home"
},
"rejected": {
"title": "Notice",
- "message": "Your {{vcLabel}} was discarded by {{receiver}}"
+ "message": "Your Card was discarded by Verifier"
+ },
+ "bleError": {
+ "title": "Failed to transfer",
+ "message": "Something went wrong while transferring Card. Please try again.",
+ "hint": "Error: {{code}}"
}
}
},
"SelectVcOverlay": {
- "header": "Share {{vcLabel}}",
- "chooseVc": "Choose the {{vcLabel}} you'd like to share with",
+ "header": "Share Card",
+ "chooseVc": "Choose the Card you'd like to share with",
"share": "Share",
"verifyAndShare": "Verify Identity & Share"
},
"SendVcScreen": {
"reasonForSharing": "Reason for sharing (optional)",
- "acceptRequest": "Accept request and choose {{vcLabel}}",
- "acceptRequestAndVerify": "Accept request and verify",
+ "acceptRequest": "Share",
+ "acceptRequestAndVerify": "Share with Selfie",
"reject": "Reject",
- "consentToPhotoVerification": "I give consent to have my photo taken for authentication"
+ "consentToPhotoVerification": "I give consent to have my photo taken for authentication",
+ "pleaseSelectAnId": "Please select an ID",
+ "status": {
+ "sharing": {
+ "title": "Sharing",
+ "hint": "Please wait for the receiving device to accept or decline the share.",
+ "timeoutHint": "VC shares take a bit longer. There may be a connection problem."
+ },
+ "accepted": {
+ "title": "Success!",
+ "message": "Your card has been successfully shared with {{receiver}}"
+ },
+ "rejected": {
+ "title": "Pay attention",
+ "message": "Your card has been declined by {{receiver}}"
+ }
+ }
},
"VerifyIdentityOverlay": {
+ "faceAuth": "Face Authentication",
"status": {
"verifyingIdentity": "Verifying identity..."
},
"errors": {
"invalidIdentity": {
"title": "Unable to verify identity",
- "message": "An error occurred and we couldn't scan your portrait. Try again, make sure your face is visible, devoid of any accessories.",
- "messageNoRetry": "An error occurred and we couldn't scan your portrait."
+ "message": "Face not recognised. Please try again.",
+ "messageNoRetry": "Face not recognised."
}
}
},
"WelcomeScreen": {
"title": "Open Source Identity Solution",
"getStarted": "Get started",
- "unlockApp": "Unlock application"
+ "unlockApp": "Unlock application",
+ "failedToReadKeys": "Failed to read keys",
+ "retryRead": "Want to retry?",
+ "ignore": "Ignore",
+ "errors": {
+ "decryptionFailed": "Failed to decrypt data",
+ "invalidateKeyError": {
+ "title": "Some Card(s) removed due to security concerns.",
+ "message": "Please redownload."
+ }
+ }
+ },
+ "SetupLanguage": {
+ "header": "Choose Language",
+ "description": "Select your preferred language",
+ "save": "Save Preference"
},
"common": {
"cancel": "Cancel",
+ "accept": "Accept",
"save": "Save",
"dismiss": "Dismiss",
"editLabel": "Edit {{label}}",
"tryAgain": "Try again",
+ "ignore": "Ignore",
"camera": {
"errors": {
"missingPermission": "This app uses the camera to scan the QR code of another device."
},
"allowAccess": "Allow access to the camera"
+ },
+ "errors": {
+ "genericError": "Something is wrong. Please try again later!"
+ },
+ "clipboard": {
+ "copy": "Copy",
+ "copied": "Copied"
+ },
+ "biometricPopup": {
+ "title": "Unlock App",
+ "description": "Please use fingerprint to unlock the app"
}
}
-}
\ No newline at end of file
+}
diff --git a/locales/fil.json b/locales/fil.json
index 639f3f8c..4b63ac91 100644
--- a/locales/fil.json
+++ b/locales/fil.json
@@ -10,13 +10,19 @@
"VC_RECEIVED_WITH_PRESENCE_VERIFIED": "natanggap. Na-verify ang presensya",
"VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "natanggap. Nabigo ang pag-verify ng presensya",
"PRESENCE_VERIFIED_AND_VC_SHARED": "na-verify at ibinahagi",
- "PRESENCE_VERIFICATION_FAILED": "nabigo ang pag-verify"
+ "PRESENCE_VERIFICATION_FAILED": "nabigo ang pag-verify",
+ "QRLOGIN_SUCCESFULL": "Matagumpay ang QRLogin",
+ "WALLET_BINDING_SUCCESSFULL": "Matagumpay ang pag-activate",
+ "WALLET_BINDING_FAILURE": "Nabigo ang pag-activate",
+ "VC_REMOVED":"Inalis sa wallet"
},
"DeviceInfoList": {
"requestedBy": "Hiniling ni",
"sentBy": "Ipinadala ni",
"deviceRefNumber": "Reference number ng device",
- "name": "Pangalan"
+ "name": "Pangalan",
+ "Verifier": "Verifier",
+ "Wallet": "Wallet"
},
"PasscodeVerify": {
"passcodeMismatchError": "Hindi tumugma ang passcode."
@@ -28,8 +34,9 @@
"verify": "I-verify"
},
"QrScanner": {
- "missingPermissionText": "Ginagamit ng app na ito ang camera upang i-scan ng QR code ng ibang device.",
- "allowCameraButton": "Payagan gamitin ang camera"
+ "cameraAccessDisabled": "Naka-disable ang access sa camera!",
+ "cameraPermissionGuideLabel": "Pumunta sa mga setting at manual na paganahin ang access ng camera.",
+ "flipCamera": "I-flip ang Camera"
},
"VcDetails": {
"generatedOn": "Nilikha noong",
@@ -45,23 +52,63 @@
"reasonForSharing": "Dahilan ng pagbabahagi",
"idType": "Uri ng ID",
"id": "Id",
+ "qrCodeHeader": "QR Code",
"nationalCard": "Pambansang Kard",
"uin": "UIN",
- "enableVerification": "I-activate",
- "profileAuthenticated": "Na-activate para sa online na pag-login",
- "offlineAuthDisabledHeader": "Nakabinbin ang pag-activate para sa online na pag-login",
- "offlineAuthDisabledMessage": "Mangyaring i-click ang pindutan sa ibaba upang i-activate ang kredensyal na ito upang magamit para sa online na pag-login.",
"vid": "VID",
+ "enableVerification": "I-activate",
+ "profileAuthenticated": "Na-activate para sa online na pag-login!",
+ "offlineAuthDisabledHeader": "Nakabinbin ang pag-activate para sa online na pag-login!",
+ "offlineAuthDisabledMessage": "Mangyaring i-click ang pindutan sa ibaba upang i-activate ang kredensyal na ito upang magamit para sa online na pag-login.",
"verificationEnabledSuccess": "Na-activate para sa online na pag-login",
"goback": "BUMALIK KA",
- "BindingWarning": "Na-activate mo na ang isang online na pag-log in para sa kredensyal na ito sa isa pang device. Hindi mo na magagamit ang device na iyon para sa pag-login kung i-activate mo itong muli sa device na ito.",
+ "BindingWarning": "Kung pinagana mo ang pag-verify para sa kredensyal na ito sa isa pang wallet, ma-override ito. Gusto mo bang magpatuloy?",
"yes_confirm": "Oo, Kinukumpirma ko",
"no": "Hindi",
"Alert": "Alerto",
- "ok": "Sige"
+ "ok": "Sige",
+ "credentialRegistry": "Credential Registry",
+ "errors": {
+ "savingFailed": {
+ "title": "Nabigong i-save ang Card",
+ "message": "Nagkaproblema habang sine-save ang Card sa tindahan."
+ },
+ "diskFullError": {
+ "title": "Nabigong i-save ang Card",
+ "message": "Wala nang mga Card na matatanggap o mai-save dahil puno na ang Data ng App."
+ }
+ }
+ },
+ "HomeScreenKebabPopUp": {
+ "title": "Higit pang mga Opsyon",
+ "unPinCard": "I-unpin ang Card",
+ "pinCard": "Pin Card",
+ "offlineAuthenticationDisabled!": "Nakabinbin ang pag-activate para sa online na pag-login!",
+ "offlineAuthDisabledMessage": "Mag-click dito upang paganahin ang mga kredensyal na ito na magamit para sa online na pagpapatotoo.",
+ "viewActivityLog": "Tingnan ang log ng aktibidad",
+ "removeFromWallet": "Alisin sa wallet",
+ "revokeId": "Bawiin ang ID",
+ "revokeMessage": "Bawiin ang virtual ID para sa profile na ito"
+ },
+ "WalletBinding": {
+ "inProgress": "Isinasagawa",
+ "profileAuthenticated": "Na-activate para sa online na pag-login!"
+ },
+ "BindingVcWarningOverlay": {
+ "alert": "Pakikumpirma",
+ "BindingWarning": "Kung na-enable mo ang pag-verify para sa kredensyal na ito sa isa pang wallet, ma-o-override ito. Gusto mo bang magpatuloy?",
+ "yesConfirm": "Oo, kinukumpirma ko",
+ "no": "Hindi"
+ },
+ "RemoveVcWarningOverlay": {
+ "alert": "Alerto",
+ "removeWarning": "Gusto mo ba talagang tanggalin ang card?",
+ "confirm": "Kumpirmahin",
+ "no": "Hindi"
},
"AuthScreen": {
"header": "Gusto mo bang gumamit ng biometrics upang i-unlock ang aplikasyon?",
+ "Description": "Gusto mo bang gumamit ng biometrics upang i-unlock ang application?",
"useBiometrics": "Gamitin ang biometrics",
"usePasscode": "Gumamit na lang ng passcode",
"errors": {
@@ -74,17 +121,57 @@
"BiometricScreen": {
"unlock": "I-unlock gamit ang biometrics"
},
- "HistoryTab": {
+ "HistoryScreen": {
"noHistory": "Wala pang kasaysayan",
"downloaded": "nakuha",
"shared": "ibinahagi",
"received": "natanggap",
"deleted": "tinanggal"
},
- "HomeScreen": {
- "myVcsTab": "Aking\n{{vcLabel}}",
- "receivedVcsTab": "Nakuhang\n{{vcLabel}}",
- "historyTab": "Pangyayari"
+ "SettingScreen": {
+ "header": "Mga setting",
+ "injiAsVerifierApp": "Inji bilang Verifier App",
+ "receiveCard": "Tumanggap ng Card",
+ "basicSettings": "Mga Pangunahing Setting",
+ "bioUnlock": "I-unlock gamit ang Biometrics",
+ "language": "Wika",
+ "aboutInji": "About Inji",
+ "credentialRegistry": "Credential Registry",
+ "errorMessage": "Maling URL ang inilagay. Mangyaring maglagay ng wastong URL upang magpatuloy.",
+ "injiTourGuide": "Inji Tour Guide",
+ "logout": "Mag-logout",
+ "resetInjiProps": "Nire-reset ang Inji Props..."
+ },
+ "AboutInji": {
+ "aboutInji": "Tungkol kay Inji",
+ "header": "TUNGKOL KAY INJI",
+ "appID": "App ID",
+ "aboutDetailes": "Ang Inji ay isang mobile app na maaaring gamitin bilang digital wallet para mag-imbak ng mga kredensyal. Pinapayagan din nito ang pag-verify ng pagkakakilanlan sa parehong offline at online na mga mode, sa anumang lugar at oras.",
+ "forMoreDetailes": "Para sa karagdagang detalye",
+ "clickHere": "Pindutin dito",
+ "version": "Bersyon",
+ "tuvaliVersion": "Tuvali-bersyon"
+ },
+ "HelpScreen": {
+ "header": "Tulong",
+ "whatIsDigitalCredential?": "Ano ang isang digital na kredensyal?",
+ "detail-1": "Ang digital na kredensyal ay ang digital na bersyon ng iyong pisikal na Identity card",
+ "whatCanDoWithDigitalCredential?": "Ano ang maaari nating gawin sa mga digital na kredensyal?",
+ "detail-2": "Maaari kang makakuha ng iba't ibang serbisyo ng Pamahalaan at pribadong gamit ang iyong mga digital na kredensyal.",
+ "howToAddCard?": "Paano magdagdag ng card?",
+ "detail-3": "Upang magdagdag ng card, mag-click sa '+' na button sa Home page at piliin ang naaangkop na opsyon.",
+ "howToRemoveCardFromWallet?": "Paano magbahagi ng card?",
+ "detail-4": "Mag-swipe pakaliwa sa card > mag-click sa Higit pa > Alisin sa Wallet",
+ "canWeAddMultipleCards?": "Maaari ba tayong magdagdag ng maraming card?",
+ "detail-5": "Oo, maaari kang magdagdag ng maraming card sa wallet sa pamamagitan ng pag-click sa '+' na button sa Home page.",
+ "howToShareCard?": "Paano magbahagi ng card?",
+ "detail-6": "Mag-click sa pindutang 'Ibahagi' at i-scan ang QR code mula sa humihiling na partido. Kapag naitatag na ang koneksyon, ibabahagi ang card.",
+ "howToActivateCardForOnlineLogin?": "Paano i-activate ang isang card para sa online na pag-login?",
+ "detail-7": "Matapos matagumpay na magdagdag ng card sa wallet, mag-click sa 'Activation pending for Online login' sa card. Sa pag-click sa 'I-activate', ang card ay handa nang gamitin para sa online na pag-login.",
+ "howToViewActivity?": "Paano tingnan ang mga log ng aktibidad?",
+ "detail-8": "Sa Home page, mag-click sa 'Kasaysayan' upang tingnan ang mga detalye ng aktibidad ng user.",
+ "whatCanDoBiometricsChanged?": "Ano ang mangyayari kapag binago ang biometric ng Android keystore?",
+ "detail-9": "Ang Android keystore ay nagtataglay ng mahalagang impormasyon tulad ng mga pribadong key para sa mga patunay ng pagkakakilanlan. Kapag binago mo ang iyong biometrics, hindi na ligtas ang mga lumang key. Upang panatilihing secure ang mga bagay, inaalis namin ang mga patunay ng pagkakakilanlan na nilagdaan ng mga lumang key na iyon. Maaari mo lamang i-download muli ang iyong mga patunay ng pagkakakilanlan, at lalagdaan ang mga ito gamit ang pinakabago, mas ligtas na mga susi."
},
"AddVcModal": {
"requestingCredential": "Humihiling ng kredensyal...",
@@ -95,93 +182,148 @@
},
"backend": {
"invalidOtp": "Di-wasto ang OTP",
+ "expiredOtp": "Nag-expire na ang OTP",
"invalidUin": "Di-wastong UIN",
"invalidVid": "Di-wastong VID",
- "missingUin": "Hindi mahanap ang iyong UIN",
- "missingVid": "Hindi mahanap ang iyong VID"
+ "missingUin": "Ang ipinasok na UIN ay na-deactivate/na-block. Mangyaring magpasok ng wastong UIN upang magpatuloy",
+ "missingVid": "Hindi mahanap ang iyong VID",
+ "noMessageAvailable": "Subukan pagkatapos ng ilang oras",
+ "whileGeneratingOtpErrorIsOccured": "habang ang pagbuo ng OTP error ay naganap",
+ "networkRequestFailed": "Nabigo ang kahilingan sa network",
+ "deactivatedVid": "Ang ipinasok na VID ay na-deactivate/nag-expire. Mangyaring magpasok ng wastong VID upang magpatuloy"
+ }
+ }
+ },
+ "GetVcModal": {
+ "retrievingId": "Kinukuha ang ID",
+ "errors": {
+ "input": {
+ "empty": "Hindi maaaring walang laman ang input",
+ "invalidFormat": "Ang input format ay hindi tama"
+ },
+ "backend": {
+ "invalidOtp": "Di-wasto ang OTP",
+ "expiredOtp": "Nag-expire na ang OTP",
+ "applicationProcessing": "Hindi pa handa ang AID",
+ "noMessageAvailable": "Subukan pagkatapos ng ilang oras",
+ "networkRequestFailed": "Nabigo ang kahilingan sa network",
+ "invalidAid": "Hindi available ang ipinasok na AID. Pakisuri ang iyong AID bago pumasok",
+ "timeout": "timeout"
}
}
},
"DownloadingVcModal": {
- "header": "Kinukuha ang iyong {{vcLabel}}",
- "bodyText": "Maaaring tumagal ito ng ilang oras, ipapaalam namin sayo kung pwede na kunin ang iyong {{vcLabel}}",
+ "header": "Kinukuha ang iyong card",
+ "bodyText": "Maaaring tumagal ito ng ilang oras, ipapaalam namin sayo kung pwede na kunin ang iyong card",
"backButton": "Bumalik"
},
+ "GetIdInputModal": {
+ "header": "Kunin ang iyong UIN/VID",
+ "applicationIdLabel": "Pakilagay ang iyong Application ID",
+ "enterApplicationId": "Ilagay ang Application ID",
+ "requestingOTP": "Humihiling ng OTP...",
+ "qstnMarkToolTip": "Available ang Application ID sa natanggap na acknowledgement pagkatapos ng enrollment.",
+ "getUIN": "Kumuha ng UIN/VID"
+ },
"IdInputModal": {
- "header": "Ilagay ang UIN o VID na ibinigay ng MOSIP upang matanggap ang iyong {{vcLabel}}",
- "generateVc": "Gumawa ng {{vcLabel}}",
- "enterId": "Ilagay ang iyong {{idType}}"
+ "header": "Kunin ang iyong ID",
+ "guideLabel": "Piliin ang uri ng ID at ilagay ang MOSIP na ibinigay na UIN o VID ng ID na nais mong makuha",
+ "generateVc": "Bumuo ng card",
+ "downloadID": "I-download ang ID",
+ "enterId": "Ipasok ang {{idType}}",
+ "noUIN/VID": "Walang UIN/VID? ",
+ "getItHere": "Kunin mo na",
+ "requestingOTP": "Humihiling ng OTP..."
},
"OtpVerificationModal": {
- "enterOtp": "Ilagay ang 6 na numerong verification code na ipinadala namin sayo",
- "header": "Pag-verify ng OTP"
+ "title": "Pag-verify ng OTP",
+ "otpSentMessage": "Ipinadala namin ang 6 na digit na code sa iyong rehistradong mobile number!",
+ "resendTheCode": "Maaari mong ipadala muli ang code sa ",
+ "resendCode": "Ipadala muli ang Code"
},
"MyVcsTab": {
- "addVcButton": "Magdagdag ng {{vcLabel}}",
- "generateVc": "Gumawa ng iyong {{vcLabel}}",
- "generateVcDescription": "Pindutin ang \"Magdagdag ng {{vcLabel}}\" sa ibaba upang makuha ang iyong {{vcLabel}}"
+ "bringYourDigitalID": "Dalhin ang Iyong Digital ID",
+ "generateVcDescription": "Upang i-download ang iyong card i-tap ang I-download card sa ibaba",
+ "downloadCard": "I-download ang Card",
+ "downloadingYourCard": "Ang pagda-download ng iyong card, maaari itong tumagal nang hanggang 5 minuto",
+ "errors": {
+ "savingFailed": {
+ "title": "Nabigong i-save ang Card",
+ "message": "Nagkaproblema habang sine-save ang Card sa tindahan."
+ },
+ "storageLimitReached": {
+ "title": "Hindi sapat na Appdata",
+ "message": "Hindi ka maaaring magdagdag o tumanggap ng mga card dahil puno na ang Appdata. I-clear ang Appdata para magpatuloy."
+ },
+ "vcIsTampered": {
+ "title": "Ang ilang mga patunay ng pagkakakilanlan ay pinakialaman",
+ "message": "Ang mga apektadong file ay tinanggal, mangyaring muling i-download."
+ },
+ "keystoreNotExists": {
+ "title": "Hindi nahanap ang Secure Key Storage",
+ "message": "Hindi secure ang key storage sa iyong telepono. Maaaring ma-leak ang iyong mga susi kung na-hack ang telepono.",
+ "riskOkayText": "OK, ipagsapalaran ko ito"
+ }
+ }
},
"OnboardingOverlay": {
- "stepOneTitle": "Mabuhay!",
- "stepOneText": "Panatilihing pribado ang iyong digital na kredensyal sa lahat ng pagkakataon. Upang makapagsimula, magdagdag ng {{vcLabel}} sa iyong profile.",
- "stepTwoTitle": "Pamamahala ng {{vcLabel}}",
- "stepTwoText": "Kapag nalikha na ang {{vcLabel}}, ito ay ligtas na nakatago sa iyong mobile at maaaring palitan ang pangalan o ibahagi anumang oras.",
- "stepThreeTitle": "Madaling pagbabahagi",
- "stepThreeText": "Ibahagi at tumanggap ng {{vcLabel}} nang mabilis gamit ang camera ng iyong mobile upang mag-scan ng mga QR code.",
- "stepThreeButton": "Magsimula at magdagdag ng {{vcLabel}}"
+ "stepOneTitle": "Ligtas na Pagbabahagi!",
+ "stepOneText": "Ibahagi at tumanggap ng card nang mabilis gamit ang camera ng iyong telepono upang mag-scan ng mga QR code",
+ "stepTwoTitle": "Pinagkakatiwalaang Digital Wallet",
+ "stepTwoText": "Panatilihin ang iyong digital na kredensyal sa iyo sa lahat ng oras",
+ "stepThreeTitle": "Mabilis na pagpasok",
+ "stepThreeText": "Kapag nabuo na, ang card ay ligtas na iniimbak sa iyong mobile.",
+ "stepFourTitle": "Walang problema sa pagpapatotoo",
+ "stepFourText": "I-authenticate ang iyong sarili nang madali gamit ang nakaimbak na digital na kredensyal.",
+ "getStarted": "Magsimula",
+ "goBack": "bumalik ka",
+ "back": "Bumalik",
+ "skip": "Laktawan",
+ "next": "Susunod"
},
"ReceivedVcsTab": {
- "noReceivedVcsTitle": "Wala pang {{vcLabel}}",
- "noReceivedVcsText": "Pindutin ang Humiling sa ibaba para makatanggap ng {{vcLabel}}"
+ "receivedCards": "Mga Natanggap na Card",
+ "header": "Mga Natanggap na Card",
+ "noReceivedVcsTitle": "Wala pang card",
+ "noReceivedVcsText": "Pindutin ang Humiling sa ibaba para makatanggap ng card"
},
"ViewVcModal": {
+ "title": "Mga Detalye ng ID",
+ "inProgress": "Isinasagawa",
"cancel": "Kanselahin",
- "lock": "Isara ang paggamit",
- "unlock": "Buksan ang paggamit",
+ "lock": "Lock",
+ "unlock": "I-unlock",
"rename": "Palitan ang pangalan",
"delete": "Tanggalin",
"revoke": "Bawiin",
- "revoking": "Ang iyong wallet ay naglalaman ng kredensyal na may VID {{vid}}. Ang pagkansela nito ay awtomatikong mag-aalis ng pareho sa wallet. Sigurado ka bang gusto mong magpatuloy?",
+ "revoking": "Ang iyong wallet ay naglalaman ng kredensyal na may VID {{vid}}. Ang pagbawi nito ay awtomatikong mag-aalis ng pareho sa wallet. Sigurado ka bang gusto mong magpatuloy?",
"requestingOtp": "Humihiling ng OTP...",
"editTag": "Palitan ang pangalan",
- "redirecting": "Redirecting...",
- "inProgress": "Naglo-load...",
+ "redirecting": "Nire-redirect...",
"success": {
- "unlocked": "Ang {{vcLabel}} ay matagumpay na na-unlock",
- "locked": "Ang {{vcLabel}} ay matagumpay na na-lock",
- "revoked": "Ang VID {{vid}} ay nakansela. Ang lahat ng mga detalye na naglalaman ng pareho ay awtomatikong aalisin wallet."
+ "unlocked": "Matagumpay na na-unlock ang card.",
+ "locked": "Matagumpay na na-lock ang card.",
+ "revoked": "Ang VID {{vid}} ay binawi. Awtomatikong aalisin sa wallet ang anumang kredensyal na naglalaman ng pareho"
}
},
"MainLayout": {
- "home": "Home",
+ "home": "Bahay",
"scan": "Scan",
- "request": "Request",
- "profile": "Profile"
+ "history": "Kasaysayan",
+ "request": "Hiling",
+ "settings": "mga setting"
},
"PasscodeScreen": {
- "header": "Magtakda ng passcode upang masigurado ang iyong aplikasyon",
- "confirmPasscode": "Kumpirmahin ang iyong passcode",
+ "header": "Itakda ang Passcode",
+ "enterNewPassword": "Maglagay ng bagong passcode",
+ "reEnterPassword": "Ipasok muli ang bagong passcode",
+ "confirmPasscode": "Kumpirmahin ang passcode",
"enterPasscode": "Ilagay ang iyong passcode"
},
- "Credits": {
- "header": "Mga kredito at legal na abiso",
- "back": "Bumalik"
- },
- "ProfileScreen": {
- "name": "Pangalan",
- "vcLabel": "Panawag sa VC",
- "language": "Wika",
- "bioUnlock": "Pagbukas gamit Biometric",
- "authFactorUnlock": "Pagbukas ng auth factor",
- "credits": "Mga kredito at legal na abiso",
- "logout": "Mag log-out",
- "revokeLabel": "Kanselahin ang VID",
- "revokeHeader": "KANSELAHIN ANG VID",
- "revokingVids": "Kakanselahin mo na ang ({{count}}) na mga VID.",
- "revokingVidsAfter": "Nangangahulugan ito na hindi mo na maa-access o matitingnan ang anumang mga ID na naka-link sa mga VID na ito. Sigurado ka bang gusto mong magpatuloy?",
- "empty": "Walang laman",
- "revokeSuccessful": "Matagumpay na nakansela ang VID",
- "version": "Bersyon"
+ "AppMetaData": {
+ "header": "Tungkol kay Inji",
+ "version": "Bersyon",
+ "useBle": "Pinapatakbo ng BLE"
},
"QrScreen": {
"title": "QR Login",
@@ -190,7 +332,7 @@
"checkDomain": "Gayundin, tingnan kung mayroong icon ng lock sa address bar.",
"domainHead": "https://",
"selectId": "Pumili ng ID",
- "noBindedVc": "Available sa Verifyct ID ang SeleNo Binded {{vcLabel}}",
+ "noBindedVc": "Available sa Verifyct ID ang SeleNo Binded card",
"back": "Bumalik ka",
"confirm": "Kumpirmahin",
"verify": "I-verify",
@@ -200,27 +342,59 @@
"domainWarning": "Pakikumpirma ang domain ng website kung saan mo ini-scan ang QR code mula sa ibaba",
"access": " ay humihiling ng access sa",
"status": "Katayuan",
- "successMessage":"Ikaw ay Matagumpay na Naka-log In ",
- "okay": "Sige"
+ "successMessage": "Ikaw ay Matagumpay na Naka-log In ",
+ "okay": "Sige",
+ "allow": "Payagan",
+ "cancel": "Kanselahin",
+ "essentialClaims": "Mahahalagang Claim",
+ "voluntaryClaims": "Mga Kusang-loob na Claim",
+ "required": "Kailangan"
},
"ReceiveVcScreen": {
- "header": "Mga detalye ng {{vcLabel}}",
- "acceptRequest": "Tanggapin ang kahilingan at tumanggap ng {{vcLabel}}",
- "reject": "Tanggihan"
+ "header": "Card mga detalye",
+ "save": "I-save ang card",
+ "verifyAndSave": "I-verify at i-save",
+ "reject": "Tanggihan",
+ "discard": "Itapon",
+ "goToReceivedVCTab": "Natanggap na View card",
+ "saving": "Sine-save ang card",
+ "errors": {
+ "savingFailed": {
+ "title": "Failed to save card",
+ "message": "Nagkaproblema habang sine-save ang card sa tindahan."
+ },
+ "diskFullError": {
+ "title": "Nabigong i-save ang cards",
+ "message": "Wala nang cards ang matatanggap o mai-save dahil puno na ang Data ng App."
+ }
+ }
},
"RequestScreen": {
- "bluetoothDenied": "Mangyaring paganahin ang Bluetooth upang makahiling ng {{vcLabel}}",
- "showQrCode": "Ipakita ang QR code na ito para makahiling ng {{vcLabel}}",
- "incomingVc": "Padating na {{vcLabel}}",
+ "receiveCard": "Tumanggap ng Card",
+ "bluetoothDenied": "Mangyaring paganahin ang Bluetooth upang makahiling ng card",
+ "bluetoothStateIos": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",
+ "bluetoothStateAndroid": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",
+ "showQrCode": "Ipakita ang QR code na ito para humiling ng resident card",
+ "incomingVc": "Padating na card",
"request": "Hilingin",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "Kinakailangan ang pahintulot ng Mga Kalapit na Device para makahiling ng Card",
+ "button": "Pahintulutan"
+ },
+ "storageLimitReached": {
+ "title": "Hindi sapat na Appdata",
+ "message": "Hindi ka maaaring magdagdag o tumanggap ng mga card dahil puno na ang Appdata. I-clear ang Appdata para magpatuloy."
+ }
+ },
"status": {
"accepted": {
"title": "Tagumpay!",
- "message": "Tagumpay na nakuha ang {{vcLabel}} mula kay {{sender}}"
+ "message": "Tagumpay na nakuha ang card mula kay wallet"
},
"rejected": {
"title": "Paunawa",
- "message": "Iwinaksi ang {{vcLabel}} ni {{sender}}"
+ "message": "Iwinaksi ang card ni wallet"
},
"disconnected": {
"title": "Nadiskonekta",
@@ -232,8 +406,16 @@
"timeoutHint": "Masyadong matagal ang pagpapalitan ng impormasyon ng device..."
},
"connected": {
- "message": "Nakakonektang device. Naghihintay para sa {{vcLabel}}...",
+ "message": "Nakakonektang device. Naghihintay para sa card...",
"timeoutHint": "Wala pang natanggap na VC. Nakakonekta pa rin ba ang pagpapadala ng device?"
+ },
+ "offline": {
+ "message": "Mangyaring kumonekta sa internet upang paganahin ang Online sharing mode"
+ },
+ "bleError": {
+ "title": "Nabigong ilipat!",
+ "message": "Nagkaproblema habang inililipat ang card. Pakisubukang muli.",
+ "hint": "Error: {{code}}"
}
},
"online": "Online",
@@ -242,8 +424,13 @@
},
"ScanScreen": {
"header": "I-scan ang QR Code",
- "noShareableVcs": "Walang magagamit na maibabahaging {{vcLabel}}.",
- "sharingVc": "Pagbabahagi ng {{vcLabel}}",
+ "noShareableVcs": "Walang magagamit na maibabahaging card..",
+ "sharingVc": "Pagbabahagi ng card",
+ "bluetoothStateIos": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",
+ "bluetoothStateAndroid": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",
+ "enableBluetoothMessage": "Mangyaring paganahin ang mga pahintulot ng bluetooth upang suportahan ang lokal na pagbabahagi",
+ "enableBluetoothButtonText": "Payagan ang mga pahintulot ng bluetooth",
+ "scanningGuide": "Panatilihin ang telepono at i-scan ang QR code",
"errors": {
"locationDisabled": {
"message": "Dapat na nakabukas ang Location services ng iyong mobile para maaaring makapag-scan",
@@ -252,65 +439,134 @@
"locationDenied": {
"message": "Kinakailangan ang pahintulot sa lokasyon ng iyong mobile para maaaring makapag-scan",
"button": "Payagan ng pahintulot sa lokasyon"
+ },
+ "nearbyDevicesPermissionDenied": {
+ "message": "Kinakailangan ang pahintulot ng Mga Kalapit na Device upang makapagbahagi ng card",
+ "button": "Pahintulutan"
+ },
+ "storageLimitReached": {
+ "title": "Hindi sapat na Appdata",
+ "message": "Hindi ka makakapagbahagi ng mga card dahil puno na ang Appdata. I-clear ang Appdata para magpatuloy."
}
},
"status": {
- "connecting": "Kumokonekta...",
- "connectingTimeout": "Medyo nagtatagal bago magtatag ng koneksyon. Bukas ba ang ibang device para sa mga koneksyon?",
+ "inProgress": "Isinasagawa",
+ "establishingConnection": "Pagtatatag ng Koneksyon",
+ "sharingInProgress": "Isinasagawa ang pagbabahagi",
+ "connectingTimeout": "Ito ay tumatagal ng ilang sandali upang maitaguyod ang koneksyon. Bukas ba ang ibang device para sa mga koneksyon?",
"exchangingDeviceInfo": "Nagpapalitan ng impormasyon ng device...",
- "exchangingDeviceInfoTimeout": "Medyo nagtatagal ang paglabas ng impormasyon ng device. Bukas ba ang ibang device para sa mga koneksyon?",
- "invalid": "Di-wasto ang QR Code",
- "offline": "Mangyaring kumonekta sa internet upang makapag-scan ng QR codes na gumagamit ng Online sharing mode",
- "sent": "Naibahagi na ang {{vcLabel}}...",
- "sentHint": "Iniintay ang nakatanggap na itabi o iwaksi ang iyong {{vcLabel}}"
+ "exchangingDeviceInfoTimeout": "Medyo nagtatagal ang palitan ng impormasyon ng device. Maaaring kailanganin mong kumonekta muli.",
+ "invalid": "Di-wastong QR Code",
+ "offline": "Mangyaring kumonekta sa internet upang i-scan ang mga QR code gamit ang Online sharing mode",
+ "sent": "Naipadala na ang card...",
+ "sentHint": "Naghihintay para sa receiver na i-save o itapon ang iyong card",
+ "sharing": {
+ "title": "Pagbabahagi...",
+ "hint": "Mangyaring maghintay habang ibinabahagi namin ang napiling card.",
+ "timeoutHint": "Mas tumatagal kaysa sa inaasahan ang pagbabahagi. Maaaring may problema sa koneksyon."
+ },
+ "accepted": {
+ "title": "Matagumpay na naibahagi ang ID",
+ "message": "Ang iyong card ay matagumpay na naibahagi sa verifier",
+ "gotohome": "Pumunta sa bahay"
+ },
+ "rejected": {
+ "title": "Pansinin",
+ "message": "Ang iyong card ay itinapon ng verifier"
+ },
+ "bleError": {
+ "title": "Nabigong ilipat!",
+ "message": "Nagkaproblema habang inililipat ang card. Pakisubukang muli.",
+ "hint": "Error: {{code}}"
+ }
}
},
"SelectVcOverlay": {
- "header": "Ibahagi ang {{vcLabel}}",
- "chooseVc": "Piliin ang {{vcLabel}} na gusto mong ibahagi",
+ "header": "Ibahagi ang card",
+ "chooseVc": "Piliin ang card na gusto mong ibahagi",
"share": "Ibahagi",
"verifyAndShare": "I-verify ang Pagkakakilanlan at Ibahagi"
},
"SendVcScreen": {
"reasonForSharing": "Dahilan ng pagbabahagi (opsyonal)",
- "acceptRequest": "Tanggapin ang kahilingan at piliin ang {{vcLabel}}",
+ "acceptRequest": "Tanggapin ang kahilingan at pumili ng card",
+ "acceptRequestAndVerify": "Ibahagi sa Selfie",
"reject": "Tanggihan",
+ "consentToPhotoVerification": "Nagbibigay ako ng pahintulot na kunin ang aking larawan para sa pagpapatunay",
+ "pleaseSelectAnId": "Mangyaring pumili ng ID",
"status": {
"sharing": {
"title": "Pagbabahagi",
+ "hint": "Pakihintay na tanggapin o tanggihan ng tumatanggap na device ang pagbabahagi.",
"timeoutHint": "Medyo natatagal ang pagbabahagi ng VC. Maaaring may problema sa koneksyon."
},
"accepted": {
"title": "Tagumpay!",
- "message": "Ang iyong {{vcLabel}} ay matagumpay na naibahagi kay {{receiver}}"
+ "message": "Ang iyong card ay matagumpay na naibahagi kay verifier"
},
"rejected": {
"title": "Pansinin",
- "message": "Ang iyong {{vcLabel}} ay tinanggihan ng {{receiver}}"
+ "message": "Ang iyong card ay tinanggihan ng verifier"
}
- },
- "consentToPhotoVerification": "Nagbibigay ako ng pahintulot na kunin ang aking larawan para sa pagpapatunay"
+ }
},
"VerifyIdentityOverlay": {
+ "faceAuth": "Face Authentication",
"status": {
"verifyingIdentity": "Bine-verify ang pagkakakilanlan..."
},
"errors": {
"invalidIdentity": {
"title": "Hindi ma-verify ang pagkakakilanlan",
- "message": "May naganap na error at hindi namin ma-scan ang iyong portrait. Subukang muli, tiyaking nakikita ang iyong mukha, walang anumang mga accessory."
+ "message": "Hindi nakikilala ang mukha. Pakisubukang muli.",
+ "messageNoRetry": "Face not recognised."
}
}
},
"WelcomeScreen": {
"title": "Open Source Identity Solution",
"getStarted": "Magsimula",
- "unlockApp": "Buksan ang aplikasyon"
+ "unlockApp": "Buksan ang aplikasyon",
+ "failedToReadKeys": "Nabigong basahin ang mga susi",
+ "retryRead": "Gustong subukang muli?",
+ "errors": {
+ "decryptionFailed": "Nabigong i-decrypt ang data",
+ "invalidateKeyError": {
+ "title": "Ang ilang (mga) patunay ng Pagkakakilanlan ay tinanggal dahil sa mga alalahanin sa seguridad.",
+ "message": "Mangyaring i-download muli."
+ }
+ },
+ "ignore": "Huwag pansinin"
+ },
+ "SetupLanguage": {
+ "header": "Piliin ang Wika",
+ "description": "Piliin ang iyong gustong wika",
+ "save": "I-save ang Kagustuhan"
},
"common": {
"cancel": "Kanselahin",
+ "accept": "Tanggapin",
"save": "I-save",
+ "dismiss": "Dismissed",
"editLabel": "Palitan ang {{label}}",
- "tryAgain": "Subukan muli"
+ "tryAgain": "Subukan muli",
+ "camera": {
+ "errors": {
+ "missingPermission": "Ginagamit ng app na ito ang camera upang i-scan ang QR code ng isa pang device."
+ },
+ "allowAccess": "Payagan ang access sa camera"
+ },
+ "ignore": "Huwag pansinin",
+ "errors": {
+ "genericError": "May mali. Subukang muli mamaya!"
+ },
+ "clipboard": {
+ "copy": "Kopya",
+ "copied": "Kinopya"
+ },
+ "biometricPopup": {
+ "title": "I-unlock ang App",
+ "description": "Mangyaring gumamit ng fingerprint upang i-unlock ang app"
+ }
}
-}
\ No newline at end of file
+}
diff --git a/locales/hin.json b/locales/hin.json
index 3d49d2f2..a4524d6a 100644
--- a/locales/hin.json
+++ b/locales/hin.json
@@ -1,337 +1,565 @@
-{
- "DeviceInfoList": {
- "requestedBy": "द्वारा अनुरोध किया गया",
- "sentBy": "द्वारा भेजा गया",
- "deviceRefNumber": "डिवाइस संदर्भ संख्या",
- "name": "नाम"
- },
- "PasscodeVerify": {
- "passcodeMismatchError": "पासकोड का मिलान नहीं हुआ।"
- },
- "FaceScanner": {},
- "OIDcAuth": {
- "title": "OIDC प्रमाणीकरण",
- "text": "OIDC प्रदाता UI के साथ प्रतिस्थापित करने के लिए",
- "verify": "सत्यापित करना"
- },
- "QrScanner": {
- "missingPermissionText": "यह ऐप किसी अन्य डिवाइस के क्यूआर कोड को स्कैन करने के लिए कैमरे का उपयोग करता है।",
- "allowCameraButton": "कैमरे तक पहुंच की अनुमति दें"
- },
- "VcDetails": {
- "generatedOn": "पर उत्पन्न हुआ",
- "status": "दर्जा",
- "valid": "वैध",
- "photo": "फ़ोटो",
- "fullName": "पूरा नाम",
- "gender": "लिंग",
- "dateOfBirth": "जन्म की तारीख",
- "phoneNumber": "फ़ोन नंबर",
- "email": "ईमेल",
- "address": "पता",
- "reasonForSharing": "साझा करने का कारण",
- "idType": "पहचान का प्रकार",
- "id": "पहचान",
- "nationalCard": "राष्ट्रीय कार्ड",
- "uin": "UIN",
- "enableVerification": "सक्रिय",
- "profileAuthenticated": "ऑनलाइन लॉगिन के लिए सक्रिय",
- "offlineAuthDisabledHeader": "ऑनलाइन लॉगिन के लिए सक्रियता लंबित है",
- "offlineAuthDisabledMessage": "ऑनलाइन लॉगिन के लिए उपयोग किए जाने वाले इस क्रेडेंशियल को सक्रिय करने के लिए कृपया नीचे दिए गए बटन पर क्लिक करें।",
- "vid": "VID",
- "verificationEnabledSuccess": "ऑनलाइन लॉगिन के लिए सक्रिय",
- "goback": "वापस जाओ",
- "BindingWarning": "आप इस क्रेडेंशियल के लिए किसी दूसरे डिवाइस पर ऑनलाइन लॉगिन पहले ही सक्रिय कर चुके हैं. यदि आप इसे इस डिवाइस पर फिर से सक्रिय करते हैं तो आप लॉगिन के लिए उस डिवाइस का उपयोग नहीं कर पाएंगे।",
- "yes_confirm": "हां, मैं पुष्टि करता हूं",
- "no": "नहीं",
- "Alert": "चेतावनी",
- "ok": "ठीक"
- },
- "AuthScreen": {
- "header": "क्या आप एप्लिकेशन को अनलॉक करने के लिए बायोमेट्रिक्स का उपयोग करना चाहेंगे?",
- "useBiometrics": "बायोमेट्रिक्स का उपयोग करें",
- "usePasscode": "मैं एक पासकोड का उपयोग करना चाहूँगा",
- "errors": {
- "unavailable": "डिवाइस बायोमेट्रिक्स का समर्थन नहीं करता",
- "unenrolled": "बायोमेट्रिक्स का उपयोग करने के लिए, कृपया अपने फ़िंगरप्रिंट को अपनी डिवाइस सेटिंग में दर्ज करें",
- "failed": "बायोमेट्रिक्स से प्रमाणित करने में विफल",
- "generic": "बायोमेट्रिक्स प्रमाणीकरण में त्रुटि प्रतीत होती है"
- }
- },
- "BiometricScreen": {
- "unlock": "फिंगरप्रिंट से अनलॉक करें"
- },
- "HistoryTab": {
- "noHistory": "अभी तक कोई इतिहास उपलब्ध नहीं है",
- "downloaded": "डाउनलोड किया गया",
- "shared": "साझा",
- "received": "प्राप्त",
- "deleted": "डिलीट"
- },
- "HomeScreen": {
- "myVcsTab": "मेरा\n{{vcLabel}}",
- "receivedVcsTab": "प्राप्त\n{{vcLabel}}",
- "historyTab": "इतिहास"
- },
- "AddVcModal": {
- "requestingCredential": "क्रेडेंशियल का अनुरोध कर रहा है...",
- "errors": {
- "input": {
- "empty": "इनपुट खाली नहीं हो सकता",
- "invalidFormat": "इनपुट फॉर्मेट गलत है"
- },
- "backend": {
- "invalidOtp": "OTP अमान्य है",
- "invalidUin": "UIN अमान्य",
- "invalidVid": "VID अमान्य",
- "missingUin": "UIN यूआईएन डेटाबेस में उपलब्ध नहीं है",
- "missingVid": "VID वीआईडी डेटाबेस में उपलब्ध नहीं है"
- }
- }
- },
- "DownloadingVcModal": {
- "header": "अपना{{vcLabel}}डाउनलोड कर रहा है",
- "bodyText": "इसमें कुछ समय लग सकता है, हम आपको सूचित करेंगे जब आपका {{vcLabel}} डाउनलोड हो जाएगा और उपलब्ध होगा",
- "backButton": "बैक होम"
- },
- "GetIdInputModal": {
- "header": "अपना यूआईएन या वीआईडी पुनर्प्राप्त करने के लिए, अपना ऐप्लिकेशन {{vcLabel}} नंबर दर्ज करें",
- "getUIN": "UIN/VID प्राप्त करें",
- "applicationId": "एप्लिकेशन {{vcLabel}} संख्या",
- "requestingOTP": "OTP का अनुरोध...",
- "qstnMarkToolTip": "आवेदन {{vcLabel}} नंबर नामांकन के बाद प्रदान की गई पावती पर मुद्रित होता है"
- },
- "IdInputModal": {
- "header": "जिस {{vcLabel}} को आप पुनः प्राप्त करना चाहते हैं, उसका MOSIP- प्रदान किया गया UIN या VID दर्ज करें",
- "generateVc": "जेनरेट {{vcLabel}}",
- "enterId": "अपना {{idType}} दर्ज करें",
- "noUIN/VID": "आपका UIN/VID नहीं है? इसे यहां लाओ",
- "requestingOTP": "OTP का अनुरोध..."
- },
- "OtpVerificationModal": {
- "enterOtp": "हमारे द्वारा भेजा गया 6 अंकों का सत्यापन कोड दर्ज करें",
- "header": "ओटीपी सत्यापन"
- },
- "MyVcsTab": {
- "addVcButton": "{{vcLabel}} जोड़ें",
- "generateVc": "अपना {{vcLabel}}जेनरेट करें",
- "generateVcDescription": "अपना {{vcLabel}} डाउनलोड करने के लिए नीचे \"जोड़ें {{vcLabel}}\" पर टैप करें"
- },
- "OnboardingOverlay": {
- "stepOneTitle": "स्वागत है!",
- "stepOneText": "अपना डिजिटल क्रेडेंशियल हमेशा अपने पास रखें। आरंभ करने के लिए, अपनी प्रोफ़ाइल में {{vcLabel}} जोड़ें।",
- "stepTwoTitle": "{{vcLabel}} प्रबंधन",
- "stepTwoText": "एक बार जनरेट हो जाने पर, {{vcLabel}} आपके मोबाइल पर सुरक्षित रूप से संगृहीत हो जाते हैं और उनका नाम बदला जा सकता है या किसी भी समय साझा किया जा सकता है।",
- "stepThreeTitle": "आसान साझा करना",
- "stepThreeText": "QR कोड स्कैन करने के लिए अपने फ़ोन कैमरे का उपयोग करके {{vcLabel}} switfly साझा करें और प्राप्त करें।",
- "stepThreeButton": "आरंभ करें और {{vcLabel}} जोड़ें"
- },
- "ReceivedVcsTab": {
- "noReceivedVcsTitle": "नहीं {{vcLabel}} अभी तक उपलब्ध नहीं है",
- "noReceivedVcsText": "प्राप्त करने के लिए नीचे दिए गए अनुरोध पर टैप करें {{vcLabel}}"
- },
- "ViewVcModal": {
- "cancel": "रद्द करना",
- "lock": "लॉक",
- "unlock": "अनलॉक",
- "rename": "नाम बदले",
- "delete": "हटाएं",
- "revoke": "निरस्त",
- "revoking": "आपके वॉलेट में VID {{vid}} के साथ एक क्रेडेंशियल है. ಇದನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳುವುದರಿಂದ ಅದನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ವ್ಯಾಲೆಟ್ನಿಂದ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ. क्या आप सुनिश्चित रूप से आगे बढ़ना चाहते हैं?",
- "requestingOtp": "OTP का अनुरोध...",
- "editTag": "टैग संपादित करें",
- "redirecting": "पुन: निर्देशित...",
- "inProgress": "लोड हो रहा है...",
- "success": {
- "unlocked": "{{vcLabel}} सफलतापूर्वक अनलॉक किया गया",
- "locked": "{{vcLabel}} सफलतापूर्वक लॉक हो गया",
- "revoked": "VID {{vid}} निरस्त कर दिया गया है. इसमें शामिल कोई भी क्रेडेंशियल वॉलेट से स्वचालित रूप से हटा दिया जाएगा"
- }
- },
- "MainLayout": {
- "home": "घर",
- "scan": "स्कैन",
- "request": "अनुरोध",
- "profile": "प्रोफाइल"
- },
- "PasscodeScreen": {
- "header": "अपना आवेदन सुरक्षित करने के लिए पासकोड सेट करें",
- "confirmPasscode": "अपना पासकोड कन्फर्म करें",
- "enterPasscode": "अपना पासकोड दर्ज करे"
- },
- "Credits": {
- "header": "क्रेडिट और कानूनी नोटिस",
- "back": "पीछे"
- },
- "ProfileScreen": {
- "name": "नाम",
- "vcLabel": "वीसी लेबल",
- "language": "भाषा",
- "bioUnlock": "बायोमेट्रिक अनलॉक",
- "authFactorUnlock": "अनलॉक ऑथ फैक्टर",
- "credits": "क्रेडिट और कानूनी नोटिस",
- "logout": "लॉग आउट",
- "revokeLabel": "VID रद्द करना",
- "revokeHeader": "VID रद्द करना",
- "revokingVids": "आप ({{count}}) VID's को निरस्त करने वाले हैं .",
- "revokingVidsAfter": "इसका अर्थ है कि अब आप उनसे लिंक की गई किसी भी आईडी का उपयोग या देखने में सक्षम नहीं होंगे VID(s). \nक्या आप सुनिश्चित रूप से आगे बढ़ना चाहते हैं?",
- "empty": "खाली",
- "revokeSuccessful": "VID को सफलतापूर्वक निरस्त कर दिया गया",
- "version": "संस्करण"
- },
- "QrScreen": {
- "title": "क्यूआर लॉगिन",
- "alignQr": "स्कैन करने के लिए फ्रेम के भीतर क्यूआर कोड को संरेखित करें",
- "confirmation": "पुष्टीकरण",
- "checkDomain": "यह भी जांचें कि एड्रेस बार पर लॉक आइकन है।",
- "domainHead": "https://",
- "selectId": "आईडी चुनें",
- "noBindedVc": "सत्यापित करने के लिए कोई आबद्ध {{vcLabel}} उपलब्ध नहीं है",
- "back": "वापस जाओ",
- "confirm": "पुष्टि करें",
- "verify": "सत्यापित करना",
- "faceAuth": "चेहरा प्रमाणीकरण",
- "consent": "अनुमति",
- "loading": "लोड हो रहा है...",
- "domainWarning": "कृपया उस वेबसाइट के डोमेन की पुष्टि करें जिसे आप नीचे दिए गए क्यूआर कोड से स्कैन कर रहे हैं",
- "access": " तक पहुंच का अनुरोध कर रहा है",
- "status": "दर्जा",
- "successMessage":"आपने सफलतापूर्वक लॉग इन कर लिया है ",
- "okay": "ठीक"
- },
- "ReceiveVcScreen": {
- "header": "{{vcLabel}} विवरण",
- "acceptRequest": "अनुरोध स्वीकार करें और {{vcLabel}} प्राप्त करें",
- "acceptRequestAndVerify": "अनुरोध स्वीकार करें और सत्यापित करें",
- "reject": "अस्वीकार"
- },
- "RequestScreen": {
- "bluetoothDenied": "कृपया ब्लूटूथ को सक्षम करें ताकि वह {{vcLabel}} का अनुरोध कर सके",
- "showQrCode": "{{vcLabel}} का अनुरोध करने के लिए यह QR कोड दिखाएं",
- "incomingVc": "इनकमिंग {{vcLabel}}",
- "request": "प्रार्थना",
- "status": {
- "accepted": {
- "title": "सफलता!",
- "message": "{{vcLabel}} {{sender}} से सफलतापूर्वक प्राप्त हो गया है"
- },
- "rejected": {
- "title": "सूचना",
- "message": "आपने {{sender}} के {{vcLabel}} को अस्वीकार कर दिया है"
- },
- "disconnected": {
- "title": "डिस्कनेक्ट किया गया",
- "message": "कनेक्शन बाधित हो गया था। कृपया पुन: प्रयास करें।"
- },
- "waitingConnection": "कनेक्शन की प्रतीक्षा कर रहा है...",
- "exchangingDeviceInfo": {
- "message": "डिवाइस की जानकारी का आदान-प्रदान करना...",
- "timeoutHint": "डिवाइस की जानकारी का आदान-प्रदान करने में बहुत अधिक समय लग रहा है..."
- },
- "connected": {
- "message": "डिवाइस से कनेक्ट किया गया। {{vcLabel}} के लिए प्रतीक्षारत...",
- "timeoutHint": "अभी तक कोई डेटा प्राप्त नहीं हुआ है. भेजने वाला उपकरण अभी भी जुड़ा हुआ है?"
- }
- },
- "online": "ऑनलाइन",
- "offline": "ऑफलाइन",
- "gotoSettings": "सेटिंग्स में जाओ"
- },
- "ScanScreen": {
- "header": "क्यूआर कोड स्कैन करे",
- "noShareableVcs": "कोई साझा करने योग्य {{vcLabel}} उपलब्ध नहीं है।",
- "sharingVc": "शेयरिंग {{vcLabel}}",
- "errors": {
- "locationDisabled": {
- "message": "स्थान सेवाओं को स्कैनिंग कार्यक्षमता के लिए सक्षम किया जाना चाहिए",
- "button": "स्थान सेवाएं सक्षम करें"
- },
- "locationDenied": {
- "message": "स्कैनिंग कार्यक्षमता के लिए स्थान अनुमति आवश्यक है",
- "button": "स्थान तक पहुंच की अनुमति दें"
- }
- },
- "status": {
- "connecting": "कनेक्टिंग...",
- "connectingTimeout": "कनेक्शन स्थापित करने में कुछ समय लग रहा है. क्या अन्य डिवाइस कनेक्शन के लिए खुला है?",
- "exchangingDeviceInfo": "डिवाइस की जानकारी का आदान-प्रदान...",
- "exchangingDeviceInfoTimeout": "It's taking a while to exchange device info. You may have to reconnect.",
- "invalid": "अमान्य क्यूआर कोड"
- }
- },
- "SelectVcOverlay": {
- "header": "शेयर {{vcLabel}}",
- "chooseVc": "वह {{vcLabel}} चुनें जिसके साथ आप साझा करना चाहते हैं",
- "share": "बाँट",
- "verifyAndShare": "पहचान सत्यापित करें और साझा करें"
- },
- "SendVcScreen": {
- "reasonForSharing": "साझा करने का कारण (वैकल्पिक)",
- "acceptRequest": "अनुरोध स्वीकार करें और चुनें {{vcLabel}}",
- "acceptRequestAndVerify": "अनुरोध स्वीकार करें और सत्यापित करें",
- "reject": "अस्वीकार",
- "status": {
- "sharing": {
- "title": "बंटवारे...",
- "hint": "शेयर को स्वीकार या अस्वीकार करने के लिए कृपया प्राप्त करने वाले डिवाइस की प्रतीक्षा करें.",
- "timeoutHint": "साझा करने में अपेक्षा से अधिक समय लग रहा है. कनेक्शन में कोई समस्या हो सकती है."
- },
- "accepted": {
- "title": "सफलता!",
- "message": "आपका {{vcLabel}} को {{रिसीवर}} के साथ सफलतापूर्वक साझा कर दिया गया है"
- },
- "rejected": {
- "title": "सूचना",
- "message": "आपके {{vcLabel}} को {{receiver}} ने अस्वीकार कर दिया था"
-
- }
- },
- "consentToPhotoVerification": "मैं प्रमाणीकरण के लिए अपनी फोटो लेने की सहमति देता हूं"
- },
- "VerifyIdentityOverlay": {
- "status": {
- "verifyingIdentity": "पहचान सत्यापित की जा रही है..."
- },
- "errors": {
- "invalidIdentity": {
- "title": "पहचान सत्यापित करने में असमर्थ",
- "message": "कोई गड़बड़ी हुई और हम आपका पोर्ट्रेट स्कैन नहीं कर सके. प्रयास करें, सुनिश्चित करें कि आपका चेहरा दिखाई दे रहा है, बिना किसी सामान के.",
- "messageNoRetry": "कोई गड़बड़ी हुई और हम आपका पोर्ट्रेट स्कैन नहीं कर सके."
- }
- }
- },
- "SendVcModal": {
- "reasonForSharing": "साझा करने का कारण (optional)",
- "acceptRequest": "अनुरोध स्वीकार करें और चुनें {{vcLabel}}",
- "reject": "अस्वीकार करे",
- "statusSharing": {
- "title": "साझा किया जा रहा है..."
- },
- "statusAccepted": {
- "title": "सफलता!",
- "message": "आपका {{vcLabel}} के साथ सफलतापूर्वक साझा कर दिया गया है {{receiver}}"
- },
- "statusRejected": {
- "title": "सूचना",
- "message": "आपका {{vcLabel}} ने अस्वीकार कर दिया था {{receiver}}"
- }
- },
- "WelcomeScreen": {
- "title": "ओपन सोर्स आइडेंटिटी सॉल्यूशन",
- "getStarted": "आरंभ करें",
- "unlockApp": "एप्लिकेशन अनलॉक करें"
- },
- "common": {
- "cancel": "रद्द करें",
- "save": "सहेजें",
- "dismiss": "नकार देना",
- "editLabel": "संपादित करें {{label}}",
- "tryAgain": "पुनः प्रयास करें",
- "camera": {
- "errors": {
- "missingPermission": "यह ऐप दूसरे डिवाइस के क्यूआर कोड को स्कैन करने के लिए कैमरे का इस्तेमाल करता है."
- },
- "allowAccess": "कैमरे तक पहुंच की अनुमति दें"
+{
+ "ActivityLogText": {
+ "VC_SHARED": "साझा",
+ "VC_RECEIVED": "प्राप्त किया",
+ "VC_RECEIVED_NOT_SAVED": "प्राप्त सहेजा नहीं गया था",
+ "VC_DELETED": "हटाए गए",
+ "VC_DOWNLOADED": "डाउनलोड की गई",
+ "VC_REVOKED": "निरस्त किया गया",
+ "VC_SHARED_WITH_VERIFICATION_CONSENT": "साझा किया। उपस्थिति सत्यापन के लिए सहमति दी जाती है",
+ "VC_RECEIVED_WITH_PRESENCE_VERIFIED": "प्राप्त किया। उपस्थिति सत्यापित",
+ "VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "प्राप्त किया। उपस्थिति सत्यापन विफल रहा",
+ "PRESENCE_VERIFIED_AND_VC_SHARED": "सत्यापित और साझा किया गया",
+ "PRESENCE_VERIFICATION_FAILED": "सत्यापन असफल",
+ "QRLOGIN_SUCCESFULL": "क्यूआरलॉगिन सफल",
+ "WALLET_BINDING_SUCCESSFULL": "सक्रियण सफल",
+ "WALLET_BINDING_FAILURE": "सक्रियकरण असफल",
+ "VC_REMOVED":"वॉलेट से हटाया गया"
+ },
+ "DeviceInfoList": {
+ "requestedBy": "द्वारा अनुरोध किया गया",
+ "sentBy": "द्वारा भेजा गया",
+ "deviceRefNumber": "डिवाइस संदर्भ संख्या",
+ "name": "नाम",
+ "Verifier": "सत्यापनकर्ता",
+ "Wallet": "वॉलेट"
+ },
+ "PasscodeVerify": {
+ "passcodeMismatchError": "पासकोड का मिलान नहीं हुआ।"
+ },
+ "FaceScanner": {},
+ "OIDcAuth": {
+ "title": "OIDC प्रमाणीकरण",
+ "text": "OIDC प्रदाता UI के साथ प्रतिस्थापित करने के लिए",
+ "verify": "सत्यापित करना"
+ },
+ "QrScanner": {
+ "cameraAccessDisabled": "कैमरा पहुंच अक्षम!",
+ "cameraPermissionGuideLabel": "सेटिंग्स में जाएं और कैमरा एक्सेस को मैन्युअल रूप से सक्षम करें।",
+ "flipCamera": "कैमरा पलटें"
+ },
+ "VcDetails": {
+ "generatedOn": "पर उत्पन्न हुआ",
+ "status": "दर्जा",
+ "valid": "वैध",
+ "photo": "फ़ोटो",
+ "fullName": "पूरा नाम",
+ "gender": "लिंग",
+ "dateOfBirth": "जन्म की तारीख",
+ "phoneNumber": "फ़ोन नंबर",
+ "email": "ईमेल",
+ "address": "पता",
+ "reasonForSharing": "साझा करने का कारण",
+ "idType": "पहचान का प्रकार",
+ "id": "पहचान",
+ "qrCodeHeader": "क्यू आर संहिता",
+ "nationalCard": "राष्ट्रीय कार्ड",
+ "uin": "UIN",
+ "vid": "VID",
+ "enableVerification": "सक्रिय",
+ "profileAuthenticated": "ऑनलाइन लॉगिन के लिए सक्रिय!",
+ "offlineAuthDisabledHeader": "ऑनलाइन लॉगिन के लिए सक्रियण लंबित है!",
+ "offlineAuthDisabledMessage": "ऑनलाइन लॉगिन के लिए उपयोग किए जाने वाले इस क्रेडेंशियल को सक्रिय करने के लिए कृपया नीचे दिए गए बटन पर क्लिक करें।",
+ "verificationEnabledSuccess": "ऑनलाइन लॉगिन के लिए सक्रिय",
+ "goback": "वापस जाओ",
+ "BindingWarning": "यदि आपने किसी अन्य वॉलेट पर इस क्रेडेंशियल के सत्यापन को सक्षम किया है, तो यह ओवरराइड हो जाएगा। क्या आपकी आगे बढ़ने की इच्छा है?",
+ "yes_confirm": "हां, मैं पुष्टि करता हूं",
+ "no": "नहीं",
+ "Alert": "चेतावनी",
+ "ok": "ठीक",
+ "credentialRegistry": "साख रजिस्ट्री",
+ "errors": {
+ "savingFailed": {
+ "title": "कार्ड सहेजने में विफल",
+ "message1": "कार्ड को स्टोर में सेव करते समय कोई गड़बड़ी हुई.",
+ "message": "स्टोर में कार्ड सहेजते समय कोई गड़बड़ी हुई।"
}
}
- }
\ No newline at end of file
+ },
+ "HomeScreenKebabPopUp": {
+ "title": "अधिक विकल्प",
+ "unPinCard": "अनपिन कार्ड",
+ "pinCard": "पिन कार्ड",
+ "offlineAuthenticationDisabled!": "ऑनलाइन लॉगिन के लिए सक्रियण लंबित है!",
+ "offlineAuthDisabledMessage": "ऑनलाइन प्रमाणीकरण के लिए इस क्रेडेंशियल का उपयोग सक्षम करने के लिए यहां क्लिक करें।",
+ "viewActivityLog": "गतिविधि लॉग देखें",
+ "removeFromWallet": "वॉलेट से हटाए",
+ "revokeId": "आईडी निरस्त करें",
+ "revokeMessage": "इस प्रोफ़ाइल के लिए वर्चुअल आईडी निरस्त करें"
+ },
+ "WalletBinding": {
+ "inProgress": "चालू",
+ "profileAuthenticated": "ऑनलाइन लॉगिन के लिए सक्रिय!"
+ },
+ "BindingVcWarningOverlay": {
+ "alert": "कृपया पुष्टि करें",
+ "BindingWarning": "यदि आपने किसी अन्य वॉलेट पर इस क्रेडेंशियल के सत्यापन को सक्षम किया है, तो यह ओवरराइड हो जाएगा। क्या आपकी आगे बढ़ने की इच्छा है?",
+ "yesConfirm": "हां, मैं पुष्टि करता हूं",
+ "no": "नहीं"
+ },
+ "RemoveVcWarningOverlay": {
+ "alert": "कृपया पुष्टि करें",
+ "removeWarning": "क्या आप यह कार्ड हटाना चाहते हैं",
+ "confirm": "हां, मैं पुष्टि करता हूं",
+ "no": "नहीं"
+ },
+ "AuthScreen": {
+ "header": "क्या आप एप्लिकेशन को अनलॉक करने के लिए बायोमेट्रिक्स का उपयोग करना चाहेंगे?",
+ "Description": "क्या आप एप्लिकेशन को अनलॉक करने के लिए बायोमेट्रिक्स का उपयोग करना चाहेंगे?",
+ "useBiometrics": "बायोमेट्रिक्स का उपयोग करें",
+ "usePasscode": "मैं एक पासकोड का उपयोग करना चाहूँगा",
+ "errors": {
+ "unavailable": "डिवाइस बायोमेट्रिक्स का समर्थन नहीं करता",
+ "unenrolled": "बायोमेट्रिक्स का उपयोग करने के लिए, कृपया अपने फ़िंगरप्रिंट को अपनी डिवाइस सेटिंग में दर्ज करें",
+ "failed": "बायोमेट्रिक्स से प्रमाणित करने में विफल",
+ "generic": "बायोमेट्रिक्स प्रमाणीकरण में त्रुटि प्रतीत होती है"
+ }
+ },
+ "BiometricScreen": {
+ "unlock": "फिंगरप्रिंट से अनलॉक करें"
+ },
+ "HistoryScreen": {
+ "noHistory": "अभी तक कोई इतिहास नहीं है",
+ "downloaded": "डाउनलोड",
+ "shared": "साझा",
+ "received": "प्राप्त",
+ "deleted": "हटाए गए"
+ },
+ "SettingScreen": {
+ "header": "समायोजन",
+ "injiAsVerifierApp": "सत्यापनकर्ता ऐप के रूप में इंजी",
+ "receiveCard": "कार्ड प्राप्त करें",
+ "basicSettings": "मूल सेटिंग्स",
+ "bioUnlock": "बायोमेट्रिक्स से अनलॉक करें",
+ "language": "भाषा",
+ "aboutInji": "इंजी के बारे में",
+ "credentialRegistry": "क्रेडेंशियल रजिस्ट्री",
+ "errorMessage": "गलत यूआरएल दर्ज किया गया। कृपया आगे बढ़ने के लिए एक वैध यूआरएल दर्ज करें।",
+ "injiTourGuide": "इंजी टूर गाइड",
+ "logout": "लॉग आउट",
+ "resetInjiProps": "इंजी प्रॉप्स को रीसेट किया जा रहा है..."
+ },
+ "AboutInji": {
+ "aboutInji": "इंजी के बारे में",
+ "header": "इंजी के बारे में",
+ "appID": "ऐप ID",
+ "aboutDetailes": "इंजी एक मोबाइल ऐप है जिसे क्रेडेंशियल स्टोर करने के लिए डिजिटल वॉलेट के रूप में इस्तेमाल किया जा सकता है। यह किसी भी स्थान और समय पर ऑफ़लाइन और ऑनलाइन दोनों तरीकों से पहचान के सत्यापन की अनुमति देता है।",
+ "forMoreDetailes": "अधिक जानकारी के लिए",
+ "clickHere": "यहाँ क्लिक करें",
+ "version": "संस्करण",
+ "tuvaliVersion": "तुवाली-संस्करण"
+ },
+ "HelpScreen": {
+ "header": "मदद",
+ "whatIsDigitalCredential?": "डिजिटल क्रेडेंशियल क्या है?",
+ "detail-1": "डिजिटल क्रेडेंशियल आपके भौतिक पहचान पत्र का डिजिटल संस्करण है",
+ "whatCanDoWithDigitalCredential?": "हम डिजिटल क्रेडेंशियल्स के साथ क्या कर सकते हैं?",
+ "detail-2": "आप अपने डिजिटल क्रेडेंशियल्स का उपयोग करके विभिन्न सरकारी और निजी सेवाओं का लाभ उठा सकते हैं।",
+ "howToAddCard?": "कार्ड कैसे जोड़ें?",
+ "detail-3": "कार्ड जोड़ने के लिए होम पेज पर '+' बटन पर क्लिक करें और उचित विकल्प चुनें।",
+ "howToRemoveCardFromWallet?": "कार्ड कैसे साझा करें?",
+ "detail-4": "कार्ड पर बाईं ओर स्वाइप करें > अधिक > वॉलेट से निकालें पर क्लिक करें",
+ "canWeAddMultipleCards?": "क्या हम अनेक कार्ड जोड़ सकते हैं?",
+ "detail-5": "हां, आप होम पेज पर '+' बटन पर क्लिक करके वॉलेट में कई कार्ड जोड़ सकते हैं।",
+ "howToShareCard?": "कार्ड कैसे साझा करें?",
+ "detail-6": "'शेयर' बटन पर क्लिक करें और अनुरोध करने वाले पक्ष से क्यूआर कोड स्कैन करें। एक बार कनेक्शन स्थापित हो जाने पर, कार्ड साझा किया जाएगा।",
+ "howToActivateCardForOnlineLogin?": "ऑनलाइन लॉगिन के लिए कार्ड कैसे सक्रिय करें?",
+ "detail-7": "वॉलेट में सफलतापूर्वक कार्ड जोड़ने के बाद, कार्ड पर 'ऑनलाइन लॉगिन के लिए सक्रियण लंबित' पर क्लिक करें। 'एक्टिवेट' पर क्लिक करने पर, कार्ड ऑनलाइन लॉगिन के लिए उपयोग के लिए तैयार हो जाएगा।",
+ "howToViewActivity?": "गतिविधि लॉग कैसे देखें?",
+ "detail-8": "होम पेज पर, उपयोगकर्ता की गतिविधि का विवरण देखने के लिए 'इतिहास' पर क्लिक करें।",
+ "whatCanDoBiometricsChanged?": "क्या होता है जब एंड्रॉइड कीस्टोर बायोमेट्रिक बदल दिया जाता है?",
+ "detail-9": "एंड्रॉइड कीस्टोर में पहचान प्रमाण के लिए निजी कुंजी जैसी महत्वपूर्ण जानकारी होती है। जब आप अपना बायोमेट्रिक्स बदलते हैं, तो पुरानी चाबियाँ सुरक्षित नहीं रह जाती हैं। चीजों को सुरक्षित रखने के लिए, हम उन पुरानी चाबियों द्वारा हस्ताक्षरित पहचान प्रमाण हटा देते हैं। आप बस अपने पहचान प्रमाण दोबारा डाउनलोड कर सकते हैं, और उन पर नवीनतम, सुरक्षित कुंजी के साथ हस्ताक्षर किए जाएंगे।"
+ },
+ "AddVcModal": {
+ "requestingCredential": "क्रेडेंशियल का अनुरोध कर रहा है...",
+ "errors": {
+ "input": {
+ "empty": "इनपुट खाली नहीं हो सकता",
+ "invalidFormat": "इनपुट फॉर्मेट गलत है"
+ },
+ "backend": {
+ "invalidOtp": "OTP अमान्य है",
+ "expiredOtp": "ओटीपी समाप्त हो गया है",
+ "invalidUin": "UIN अमान्य",
+ "invalidVid": "VID अमान्य",
+ "missingUin": "दर्ज किया गया UIN निष्क्रिय/अवरुद्ध है। आगे बढ़ने के लिए कृपया एक वैध UIN दर्ज करें",
+ "missingVid": "VID वीआईडी डेटाबेस में उपलब्ध नहीं है",
+ "noMessageAvailable": "कुछ देर बाद कोशिश करें",
+ "whileGeneratingOtpErrorIsOccured": "ओटीपी जनरेट करते समय एरर आ गया",
+ "networkRequestFailed": "नेटवर्क अनुरोध विफल रहा",
+ "deactivatedVid": "दर्ज किया गया VID निष्क्रिय/समाप्त हो गया है। आगे बढ़ने के लिए कृपया एक वैध VID दर्ज करें"
+ }
+ }
+ },
+ "GetVcModal": {
+ "retrievingId": "आईडी पुनः प्राप्त की जा रही है",
+ "errors": {
+ "input": {
+ "empty": "इनपुट खाली नहीं हो सकता",
+ "invalidFormat": "इनपुट फॉर्मेट गलत"
+ },
+ "backend": {
+ "invalidOtp": "ओटीपी अमान्य है",
+ "expiredOtp": "ओटीपी समाप्त हो गया है",
+ "applicationProcessing": "AID तैयार नहीं है",
+ "noMessageAvailable": "कुछ देर बाद कोशिश करें",
+ "networkRequestFailed": "नेटवर्क अनुरोध विफल रहा",
+ "invalidAid": "दर्ज सहायता उपलब्ध नहीं है। प्रवेश करने से पहले कृपया अपने सहायता की जाँच करें",
+ "timeOut": "समय समाप्त"
+ }
+ }
+ },
+ "DownloadingVcModal": {
+ "header": "अपना कार्ड डाउनलोड कर रहा है",
+ "bodyText": "इसमें कुछ समय लग सकता है, हम आपको सूचित करेंगे जब आपका कार्ड डाउनलोड हो जाएगा और उपलब्ध होगा",
+ "backButton": "बैक होम"
+ },
+ "GetIdInputModal": {
+ "header": "अपना UIN/VID पुनः प्राप्त करें",
+ "applicationIdLabel": "कृपया अपना आवेदन आईडी दर्ज करें",
+ "enterApplicationId": "एप्लिकेशन आईडी दर्ज करें",
+ "getUIN": "यूआईएन/वीआईडी प्राप्त करें",
+ "requestingOTP": "ओटीपी का अनुरोध...",
+ "qstnMarkToolTip": "आवेदन आईडी नामांकन के बाद प्राप्त पावती में उपलब्ध है।"
+ },
+ "IdInputModal": {
+ "header": "अपनी आईडी पुनर्प्राप्त करें",
+ "guideLabel": "आईडी प्रकार का चयन करें और एमओएसआईपी प्रदान की गई यूआईएन या उस आईडी का वीआईडी दर्ज करें जिसे आप पुनर्प्राप्त करना चाहते हैं",
+ "generateVc": "कार्ड जनरेट करें",
+ "downloadID": "डाउनलोड आईडी",
+ "enterId": "{{idType}} दर्ज करें",
+ "noUIN/VID": "यूआईएन/वीआईडी नहीं है? ",
+ "getItHere": "अब समझे",
+ "requestingOTP": "ओटीपी का अनुरोध..."
+ },
+ "OtpVerificationModal": {
+ "title": "ओटीपी सत्यापन",
+ "otpSentMessage": "हमने आपके पंजीकृत मोबाइल नंबर पर 6 अंकों का कोड भेज दिया है!",
+ "resendTheCode": "आप कोड को फिर से भेज सकते हैं ",
+ "resendCode": "पुन: कोड भेजे"
+ },
+ "MyVcsTab": {
+ "downloadCard": "डाउनलोड कार्ड",
+ "bringYourDigitalID": "अपनी डिजिटल आईडी लाओ",
+ "generateVcDescription": "अपना कार्ड डाउनलोड करने के लिए नीचे डाउनलोड कार्ड टैप करें",
+ "downloadingYourCard": "आपका कार्ड डाउनलोड करने में 5 मिनट तक का समय लग सकता है",
+ "errors": {
+ "savingFailed": {
+ "title": "कार्ड सहेजने में विफल",
+ "message1": "कार्ड को स्टोर में सेव करते समय कोई गड़बड़ी हुई.",
+ "message": "स्टोर में कार्ड सहेजते समय कोई गड़बड़ी हुई।"
+ },
+ "storageLimitReached": {
+ "title": "अपर्याप्त ऐपडाटा",
+ "message": "ऐपडेटा भरा होने के कारण आप कार्ड जोड़ या प्राप्त नहीं कर सकते। आगे बढ़ने के लिए ऐपडेटा साफ़ करें।"
+ },
+ "vcIsTampered": {
+ "title": "कुछ पहचान प्रमाणों से छेड़छाड़ की गई है",
+ "message": "प्रभावित फ़ाइलें हटा दी गई हैं, कृपया पुनः डाउनलोड करें।"
+ },
+ "keystoreNotExists": {
+ "title": "सुरक्षित कुंजी संग्रहण नहीं मिला",
+ "message": "आपके फ़ोन का कुंजी संग्रहण सुरक्षित नहीं है. फोन हैक होने पर आपकी चाबियां लीक हो सकती हैं।",
+ "riskOkayText": "ठीक है, मैं यह जोखिम उठाऊंगा"
+ }
+ }
+ },
+ "OnboardingOverlay": {
+ "stepOneTitle": "सुरक्षित साझाकरण!",
+ "stepOneText": "अपना डिजिटल क्रेडेंशियल हर समय अपने पास रखें। इंजी आपको उन्हें प्रभावी ढंग से प्रबंधित करने और उपयोग करने में मदद करता है। आरंभ करने के लिए, अपनी प्रोफ़ाइल में कार्ड जोड़ें।",
+ "stepTwoTitle": "विश्वसनीय डिजिटल वॉलेट",
+ "stepTwoText": "अपने सभी महत्वपूर्ण कार्डों को एक ही विश्वसनीय वॉलेट में रखें और रखें।",
+ "stepThreeTitle": "सुरक्षित साझाकरण",
+ "stepThreeText": "परेशानी मुक्त तरीके से अपने कार्ड सुरक्षित रूप से साझा करें और विभिन्न सेवाओं का लाभ उठाएं।",
+ "stepFourTitle": "परेशानी मुक्त प्रमाणीकरण",
+ "stepFourText": "संग्रहीत डिजिटल क्रेडेंशियल का उपयोग करके आसानी से स्वयं को प्रमाणित करें।",
+ "getStarted": "शुरू करें",
+ "goBack": "वापस जाओ",
+ "back": "पीछे",
+ "skip": "छोडना",
+ "next": "अगला"
+ },
+ "ReceivedVcsTab": {
+ "receivedCards": "प्राप्त कार्ड",
+ "header": "प्राप्त कार्ड",
+ "noReceivedVcsTitle": "नहीं कार्ड अभी तक उपलब्ध नहीं है",
+ "noReceivedVcsText": "प्राप्त करने के लिए नीचे दिए गए अनुरोध पर टैप करें कार्ड"
+ },
+ "ViewVcModal": {
+ "title": "आईडी विवरण",
+ "inProgress": "चालू",
+ "cancel": "रद्द करना",
+ "lock": "ताला",
+ "unlock": "अनलॉक",
+ "rename": "नाम बदलें",
+ "delete": "मिटाना",
+ "revoke": "रद्द करना",
+ "revoking": "आपके वॉलेट में VID {{vid}} के साथ एक क्रेडेंशियल है। इसे रद्द करने से यह अपने आप वॉलेट से हट जाएगा। क्या आप सुनिश्चित रूप से आगे बढ़ना चाहते हैं?",
+ "requestingOtp": "ओटीपी का अनुरोध...",
+ "editTag": "नाम बदलें",
+ "redirecting": "पुन: निर्देशित...",
+ "success": {
+ "unlocked": "कार्ड सफलतापूर्वक अनलॉक किया गया",
+ "locked": "कार्ड सफलतापूर्वक अनलॉक किया गया",
+ "revoked": "VID {{vid}} निरस्त कर दिया गया है। इसमें शामिल कोई भी क्रेडेंशियल वॉलेट से स्वचालित रूप से हटा दिया जाएगा"
+ }
+ },
+ "MainLayout": {
+ "home": "होम",
+ "scan": "स्कैन",
+ "history": "इतिहास",
+ "request": "अनुरोध",
+ "settings": "सेटिंग्स"
+ },
+ "PasscodeScreen": {
+ "header": "पास कोड सेट करो",
+ "enterNewPassword": "एक नया पासकोड दर्ज करें",
+ "reEnterPassword": "नया पासकोड पुनः दर्ज करें",
+ "confirmPasscode": "पासकोड की पुष्टि करें",
+ "enterPasscode": "अपना पासकोड प्रविष्ट करें"
+ },
+ "AppMetaData": {
+ "header": "इंजी के बारे में",
+ "version": "संस्करण",
+ "useBle": "BLE द्वारा संचालित"
+ },
+ "QrScreen": {
+ "title": "क्यूआर लॉगिन",
+ "alignQr": "स्कैन करने के लिए फ्रेम के भीतर क्यूआर कोड को संरेखित करें",
+ "confirmation": "पुष्टीकरण",
+ "checkDomain": "यह भी जांचें कि एड्रेस बार पर लॉक आइकन है।",
+ "domainHead": "https://",
+ "selectId": "आईडी चुनें",
+ "noBindedVc": "सत्यापित करने के लिए कोई आबद्ध कार्ड्स उपलब्ध नहीं है",
+ "back": "वापस जाओ",
+ "confirm": "पुष्टि करें",
+ "verify": "सत्यापित करना",
+ "faceAuth": "चेहरा प्रमाणीकरण",
+ "consent": "अनुमति",
+ "loading": "लोड हो रहा है...",
+ "domainWarning": "कृपया उस वेबसाइट के डोमेन की पुष्टि करें जिसे आप नीचे दिए गए क्यूआर कोड से स्कैन कर रहे हैं",
+ "access": " तक पहुंच का अनुरोध कर रहा है",
+ "status": "दर्जा",
+ "successMessage": "आपने सफलतापूर्वक लॉग इन कर लिया है ",
+ "okay": "ठीक",
+ "allow": "अनुमति देना",
+ "cancel": "रद्द करना",
+ "essentialClaims": "आवश्यक दावे",
+ "voluntaryClaims": "स्वैच्छिक दावे",
+ "required": "आवश्यक"
+ },
+ "ReceiveVcScreen": {
+ "header": "कार्ड विवरण",
+ "save": "कार्ड सहेजें",
+ "verifyAndSave": "सत्यापित करें और सहेजें",
+ "acceptRequest": "अनुरोध स्वीकार करें और कार्ड प्राप्त करें",
+ "acceptRequestAndVerify": "अनुरोध स्वीकार करें और सत्यापित करें",
+ "reject": "अस्वीकार",
+ "discard": "खारिज करना",
+ "goToReceivedVCTab": "प्राप्त कार्ड्स देखें",
+ "saving": "कार्ड सहेजा जा रहा है",
+ "errors": {
+ "savingFailed": {
+ "title": "कार्ड सहेजने में विफल",
+ "message": "कार्ड को स्टोर में सेव करते समय कोई गड़बड़ी हुई."
+ }
+ }
+ },
+ "RequestScreen": {
+ "receiveCard": "कार्ड प्राप्त करें",
+ "bluetoothDenied": "कृपया ब्लूटूथ को सक्षम करें ताकि वह कार्ड का अनुरोध कर सके",
+ "bluetoothStateIos": "ब्लूटूथ बंद है, कृपया इसे निsयंत्रण केंद्र से चालू करें",
+ "bluetoothStateAndroid": "ब्लूटूथ बंद है, कृपया इसे त्वरित सेटिंग मेनू से चालू करें",
+ "showQrCode": "निवासी कार्ड का अनुरोध करने के लिए यह क्यूआर कोड प्रदर्शित करें",
+ "incomingVc": "इनकमिंग कार्ड",
+ "request": "प्रार्थना",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "कार्ड का अनुरोध करने में सक्षम होने के लिए आस-पास के उपकरणों की अनुमति आवश्यक है",
+ "button": "अनुमति दें"
+ },
+ "storageLimitReached": {
+ "title": "अपर्याप्त ऐपडाटा",
+ "message": "ऐपडेटा भरा होने के कारण आप कार्ड जोड़ या प्राप्त नहीं कर सकते। आगे बढ़ने के लिए ऐपडेटा साफ़ करें।"
+ }
+ },
+ "status": {
+ "accepted": {
+ "title": "सफलता!",
+ "message": "कार्ड वॉलेट से सफलतापूर्वक प्राप्त हो गया है"
+ },
+ "rejected": {
+ "title": "सूचना",
+ "message": "आपने वॉलेट के कार्ड को अस्वीकार कर दिया है"
+ },
+ "disconnected": {
+ "title": "डिस्कनेक्ट किया गया",
+ "message": "कनेक्शन बाधित हो गया था। कृपया पुन: प्रयास करें।"
+ },
+ "waitingConnection": "कनेक्शन की प्रतीक्षा कर रहा है...",
+ "exchangingDeviceInfo": {
+ "message": "डिवाइस की जानकारी का आदान-प्रदान करना...",
+ "timeoutHint": "डिवाइस की जानकारी का आदान-प्रदान करने में बहुत अधिक समय लग रहा है..."
+ },
+ "connected": {
+ "message": "डिवाइस से कनेक्ट किया गया। कार्ड के लिए प्रतीक्षारत...",
+ "timeoutHint": "अभी तक कोई डेटा प्राप्त नहीं हुआ है. भेजने वाला उपकरण अभी भी जुड़ा हुआ है?"
+ },
+ "offline": {
+ "message": "ऑनलाइन साझाकरण मोड सक्षम करने के लिए कृपया इंटरनेट से कनेक्ट करें"
+ },
+ "bleError": {
+ "title": "स्थानांतरित करने में विफल",
+ "message": "कार्ड को स्थानांतरित करते समय कुछ गलत हो गया। कृपया पुन: प्रयास करें।",
+ "hint": "गलती: {{code}}"
+ }
+ },
+ "online": "ऑनलाइन",
+ "offline": "ऑफलाइन",
+ "gotoSettings": "सेटिंग्स में जाओ"
+ },
+ "ScanScreen": {
+ "header": "स्कैन क्यू आर कोड",
+ "noShareableVcs": "कोई साझा करने योग्य कार्ड उपलब्ध नहीं है।",
+ "sharingVc": "कार्ड साझा करना",
+ "bluetoothStateIos": "ब्लूटूथ बंद है, कृपया इसे नियंत्रण केंद्र से चालू करें",
+ "bluetoothStateAndroid": "ब्लूटूथ बंद है, कृपया इसे त्वरित सेटिंग मेनू से चालू करें",
+ "enableBluetoothMessage": "कृपया स्थानीय साझाकरण का समर्थन करने के लिए ब्लूटूथ अनुमतियाँ सक्षम करें",
+ "enableBluetoothButtonText": "ब्लूटूथ अनुमतियाँ दें",
+ "scanningGuide": "फ़ोन को स्थिर रखें और QR कोड को स्कैन करें",
+ "errors": {
+ "locationDisabled": {
+ "message": "स्थान सेवाओं को स्कैनिंग कार्यक्षमता के लिए सक्षम किया जाना चाहिए",
+ "button": "स्थान सेवाएं सक्षम करें"
+ },
+ "locationDenied": {
+ "message": "स्कैनिंग कार्यक्षमता के लिए स्थान अनुमति आवश्यक है",
+ "button": "स्थान तक पहुंच की अनुमति दें"
+ },
+ "nearbyDevicesPermissionDenied": {
+ "message": "कार्ड साझा करने में सक्षम होने के लिए आस-पास के उपकरणों की अनुमति आवश्यक है",
+ "button": "अनुमति दें"
+ },
+ "storageLimitReached": {
+ "title": "अपर्याप्त ऐपडाटा",
+ "message": "ऐपडेटा भरा होने के कारण आप कार्ड साझा नहीं कर सकते। आगे बढ़ने के लिए ऐपडेटा साफ़ करें।"
+ },
+ "status": {
+ "inProgress": "चालू",
+ "establishingConnection": "संपर्क स्थापित करना",
+ "sharingInProgress": "साझाकरण प्रगति पर है",
+ "connectingTimeout": "कनेक्शन स्थापित करने में कुछ समय लग रहा है। क्या अन्य डिवाइस कनेक्शन के लिए खुला है?",
+ "exchangingDeviceInfo": "डिवाइस की जानकारी का आदान-प्रदान करना...",
+ "exchangingDeviceInfoTimeout": "डिवाइस की जानकारी का आदान-प्रदान करने में कुछ समय लग रहा है। आपको फिर से कनेक्ट करना पड़ सकता है।",
+ "invalid": "अमान्य क्यूआर कोड",
+ "offline": "ऑनलाइन साझाकरण मोड का उपयोग करके क्यूआर कोड स्कैन करने के लिए कृपया इंटरनेट से कनेक्ट करें",
+ "sent": "कार्ड भेज दिया गया है...",
+ "sentHint": "आपके {{vcLabel }} को सहेजने या छोड़ने के लिए रिसीवर की प्रतीक्षा की जा रही है",
+ "sharing": {
+ "title": "शेयरिंग...",
+ "hint": "कृपया तब तक प्रतीक्षा करें जब तक हम चयनित कार्ड साझा नहीं करते।",
+ "timeoutHint": "साझा करने में अपेक्षा से अधिक समय लग रहा है। कनेक्शन में कोई समस्या हो सकती है।"
+ },
+ "accepted": {
+ "title": "आईडी सफलतापूर्वक साझा किया गया",
+ "message": "आपका कार्ड सफलतापूर्वक {{रिसीवर}} के साथ साझा किया गया",
+ "gotohome": "घर जाओ"
+ },
+ "rejected": {
+ "title": "सूचना",
+ "message": "आपका कार्ड {{रिसीवर}} द्वारा खारिज कर दिया गया था"
+ },
+ "bleError": {
+ "title": "स्थानांतरित करने में विफल!",
+ "message": "कार्ड को स्थानांतरित करते समय कुछ गलत हो गया। कृपया पुन: प्रयास करें।"
+ }
+ }
+ }
+ },
+ "SelectVcOverlay": {
+ "header": "शेयर कार्ड",
+ "chooseVc": "वह कार्ड चुनें जिसके साथ आप साझा करना चाहते हैं",
+ "share": "बाँट",
+ "verifyAndShare": "पहचान सत्यापित करें और साझा करें"
+ },
+ "SendVcScreen": {
+ "reasonForSharing": "साझा करने का कारण (वैकल्पिक)",
+ "acceptRequest": "शेयर करना",
+ "acceptRequestAndVerify": "सेल्फी के साथ शेयर करें",
+ "consentToPhotoVerification": "मैं सत्यापन के लिए अपना फोटो लेने की अनुमति देता हूं",
+ "pleaseSelectAnId": "कृपया एक आईडी चुनें",
+ "reject": "अस्वीकार",
+ "status": {
+ "sharing": {
+ "title": "बंटवारे...",
+ "hint": "शेयर को स्वीकार या अस्वीकार करने के लिए कृपया प्राप्त करने वाले डिवाइस की प्रतीक्षा करें.",
+ "timeoutHint": "साझा करने में अपेक्षा से अधिक समय लग रहा है. कनेक्शन में कोई समस्या हो सकती है."
+ },
+ "accepted": {
+ "title": "सफलता!",
+ "message": "आपका कार्ड को {{रिसीवर}} के साथ सफलतापूर्वक साझा कर दिया गया है"
+ },
+ "rejected": {
+ "title": "सूचना",
+ "message": "आपके कार्ड को सत्यापनकर्ता ने अस्वीकार कर दिया था"
+ }
+ }
+ },
+ "VerifyIdentityOverlay": {
+ "faceAuth": "चेहरा प्रमाणीकरण",
+ "status": {
+ "verifyingIdentity": "पहचान सत्यापित की जा रही है..."
+ },
+ "errors": {
+ "invalidIdentity": {
+ "title": "पहचान सत्यापित करने में असमर्थ",
+ "message": "चेहरा नहीं पहचाना। कृपया पुन: प्रयास करें।",
+ "messageNoRetry": "चेहरा नहीं पहचाना।"
+ }
+ }
+ },
+ "WelcomeScreen": {
+ "title": "ओपन सोर्स आइडेंटिटी सॉल्यूशन",
+ "getStarted": "आरंभ करें",
+ "unlockApp": "एप्लिकेशन अनलॉक करें",
+ "failedToReadKeys": "कुंजियाँ पढ़ने में विफल",
+ "retryRead": "पुनः प्रयास करना चाहते हैं?",
+ "errors": {
+ "decryptionFailed": "डेटा डिक्रिप्ट करने में विफल",
+ "invalidateKeyError": {
+ "title": "सुरक्षा चिंताओं के कारण कुछ पहचान प्रमाण हटा दिए गए हैं।",
+ "message": "कृपया पुनः डाउनलोड करें."
+ }
+ },
+ "ignore": "अनदेखा करना"
+ },
+ "SetupLanguage": {
+ "header": "भाषा चुनें",
+ "description": "अपनी पसंदीदा भाषा चुनें",
+ "save": "वरीयता सहेजें"
+ },
+ "common": {
+ "cancel": "रद्द करें",
+ "save": "सहेजें",
+ "dismiss": "नकार देना",
+ "editLabel": "संपादित करें {{label}}",
+ "tryAgain": "पुनः प्रयास करें",
+ "camera": {
+ "errors": {
+ "missingPermission": "यह ऐप दूसरे डिवाइस के क्यूआर कोड को स्कैन करने के लिए कैमरे का इस्तेमाल करता है."
+ },
+ "allowAccess": "कैमरे तक पहुंच की अनुमति दें"
+ },
+ "errors": {
+ "genericError": "कुछ गलत हो गया। कृपया कुछ समय बाद पुन: प्रयास करें!"
+ },
+ "clipboard": {
+ "copy": "प्रतिलिपि",
+ "copied": "कॉपी किया गया"
+ },
+ "biometricPopup": {
+ "title": "ऐप अनलॉक करें",
+ "description": "कृपया ऐप को अनलॉक करने के लिए फिंगरप्रिंट का उपयोग करें"
+ }
+ }
+}
diff --git a/locales/kan.json b/locales/kan.json
index ce9ce7fc..8deed0f6 100644
--- a/locales/kan.json
+++ b/locales/kan.json
@@ -1,337 +1,566 @@
-{
- "DeviceInfoList": {
- "requestedBy": "ವಿನಂತಿಸಿದವರು",
- "sentBy": "ಕಳುಹಿಸಿದವರು",
- "deviceRefNumber": "ಸಾಧನ ಉಲ್ಲೇಖ ಸಂಖ್ಯೆ",
- "name": "ಹೆಸರು"
- },
- "PasscodeVerify": {
- "passcodeMismatchError": "ಪಾಸ್ಕೋಡ್ ಹೊಂದಿಕೆಯಾಗಲಿಲ್ಲ."
- },
- "FaceScanner": {},
- "OIDcAuth": {
- "title": "OIDC ದೃಢೀಕರಣ",
- "text": "OIDC ಪೂರೈಕೆದಾರ UI ನೊಂದಿಗೆ ಬದಲಾಯಿಸಲು",
- "verify": "ಪರಿಶೀಲಿಸಿ"
- },
- "QrScanner": {
- "missingPermissionText": "ಈ ಅಪ್ಲಿಕೇಶನ್ ಇನ್ನೊಂದು ಸಾಧನದ QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತದೆ.",
- "allowCameraButton": "ಕ್ಯಾಮೆರಾಗೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"
- },
- "VcDetails": {
- "generatedOn": "ಜನರೇಟೆಡ್ ಆನ್",
- "status": "ಸ್ಥಿತಿ",
- "valid": "ಮಾನ್ಯ",
- "photo": "ಫೋಟೋ",
- "fullName": "ಪೂರ್ಣ ಹೆಸರು",
- "gender": "ಲಿಂಗ",
- "dateOfBirth": "ಹುಟ್ಟಿದ ದಿನಾಂಕ",
- "phoneNumber": "ಫೋನ್ ಸಂಖ್ಯೆ",
- "email": "ಇಮೇಲ್",
- "address": "ವಿಳಾಸ",
- "reasonForSharing": "ಹಂಚಿಕೆಗೆ ಕಾರಣ",
- "idType": "ಐಡಿಟೈಪ್",
- "id": "Id",
- "nationalCard": "ರಾಷ್ಟ್ರೀಯ ಕಾರ್ಡ್",
- "uin": "UIN",
- "enableVerification": "ಸಕ್ರಿಯಗೊಳಿಸಿ",
- "profileAuthenticated": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ",
- "offlineAuthDisabledHeader": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆ ಬಾಕಿ ಉಳಿದಿದೆ",
- "offlineAuthDisabledMessage": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಬಳಸಲು ಈ ರುಜುವಾತುಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ದಯವಿಟ್ಟು ಕೆಳಗಿನ ಬಟನ್ ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ.",
- "vid": "VID",
- "verificationEnabledSuccess": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ",
- "goback": "ಹಿಂದೆ ಹೋಗು",
- "BindingWarning": "ನೀವು ಈಗಾಗಲೇ ಇನ್ನೊಂದು ಸಾಧನದಲ್ಲಿ ಈ ರುಜುವಾತುಗಳಿಗಾಗಿ ಆನ್ಲೈನ್ ಲಾಗಿನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದೀರಿ. ಈ ಸಾಧನದಲ್ಲಿ ನೀವು ಅದನ್ನು ಮತ್ತೆ ಸಕ್ರಿಯಗೊಳಿಸಿದರೆ ಲಾಗಿನ್ಗಾಗಿ ಆ ಸಾಧನವನ್ನು ಬಳಸಲು ನಿಮಗೆ ಇನ್ನು ಮುಂದೆ ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ.",
- "yes_confirm": "ಹೌದು, ನಾನು ದೃಢೀಕರಿಸುತ್ತೇನೆ",
- "no": "ಸಂ",
- "Alert": "ಎಚ್ಚರಿಕೆ",
- "ok": "ಸರಿ"
- },
- "AuthScreen": {
- "header": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬಳಸಲು ನೀವು ಬಯಸುವಿರಾ?",
- "useBiometrics": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬಳಸಿ",
- "usePasscode": "ನಾನು ಪಾಸ್ಕೋಡ್ ಅನ್ನು ಬಳಸುತ್ತೇನೆ",
- "errors": {
- "unavailable": "ಸಾಧನವು ಬಯೋಮೆಟ್ರಿಕ್ಗಳನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ",
- "unenrolled": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅನ್ನು ಬಳಸಲು, ದಯವಿಟ್ಟು ನಿಮ್ಮ ಸಾಧನದ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ನೋಂದಾಯಿಸಿ",
- "failed": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ನೊಂದಿಗೆ ದೃಢೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ",
- "generic": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ದೃಢೀಕರಣದಲ್ಲಿ ದೋಷ ಕಂಡುಬರುತ್ತಿದೆ"
- }
- },
- "BiometricScreen": {
- "unlock": "ಫಿಂಗರ್ಪ್ರಿಂಟ್ನೊಂದಿಗೆ ಅನ್ಲಾಕ್"
- },
- "HistoryTab": {
- "noHistory": "ಇನ್ನೂ ಯಾವುದೇ ಇತಿಹಾಸ ಲಭ್ಯವಿಲ್ಲ",
- "downloaded": "ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗಿದೆ",
- "shared": "ಹಂಚಿಕೊಂಡಿದೆ",
- "received": "ಸ್ವೀಕರಿಸಲಾಗಿದೆ",
- "deleted": "ಅಳಿಸಲಾಗಿದೆ"
- },
- "HomeScreen": {
- "myVcsTab": "ನನ್ನ\n{{vcLabel}}",
- "receivedVcsTab": "ಸ್ವೀಕರಿಸಲಾಗಿದೆ\n{{vcLabel}}",
- "historyTab": "ಇತಿಹಾಸ"
- },
- "AddVcModal": {
- "requestingCredential": "ರುಜುವಾತುಗಳನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ...",
- "errors": {
- "input": {
- "empty": "ಇನ್ಪುಟ್ ಖಾಲಿ ಇರುವಂತಿಲ್ಲ",
- "invalidFormat": "ಇನ್ಪುಟ್ ಫಾರ್ಮ್ಯಾಟ್ ತಪ್ಪಾಗಿದೆ"
- },
- "backend": {
- "invalidOtp": "OTP ಅಮಾನ್ಯವಾಗಿದೆ",
- "invalidUin": "UIN ಅಮಾನ್ಯವಾಗಿದೆ",
- "invalidVid": "VID ಅಮಾನ್ಯವಾಗಿದೆ",
- "missingUin": "UIN ಡೇಟಾಬೇಸ್ನಲ್ಲಿ ಲಭ್ಯವಿಲ್ಲ",
- "missingVid": "VID ಡೇಟಾಬೇಸ್ನಲ್ಲಿ ಲಭ್ಯವಿಲ್ಲ"
- }
- }
- },
- "DownloadingVcModal": {
- "header": "ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ {{vcLabel}}",
- "bodyText": "ಇದು ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳಬಹುದು, ನಿಮ್ಮ {{vcLabel}} ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಿದಾಗ ಮತ್ತು ಲಭ್ಯವಿದ್ದಾಗ ನಾವು ನಿಮಗೆ ತಿಳಿಸುತ್ತೇವೆ",
- "backButton": "ಬ್ಯಾಕ್ ಹೋಮ್"
- },
- "GetIdInputModal": {
- "header": "ನಿಮ್ಮ UIN ಅಥವಾ VID ಅನ್ನು ಹಿಂಪಡೆಯಲು, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ {{vcLabel}} ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ",
- "getUIN": "UIN/VID ಪಡೆಯಿರಿ",
- "applicationId": "ಅಪ್ಲಿಕೇಶನ್ {{vcLabel}} ಸಂಖ್ಯೆ",
- "requestingOTP": "OTP ಯನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ...",
- "qstnMarkToolTip": "ಅರ್ಜಿ {{vcLabel}} ಸಂಖ್ಯೆಯನ್ನು ನೋಂದಣಿಯ ನಂತರ ಒದಗಿಸಲಾದ ಸ್ವೀಕೃತಿಯ ಮೇಲೆ ಮುದ್ರಿಸಲಾಗಿದೆ"
- },
- "IdInputModal": {
- "header": "ನೀವು ಹಿಂಪಡೆಯಲು ಬಯಸುವ {{vcLabel}} ನ MOSIP-ಒದಗಿಸಿದ UIN ಅಥವಾ VID ಅನ್ನು ನಮೂದಿಸ",
- "generateVc": "ರಚಿಸಿ {{vcLabel}}",
- "enterId": "ನಿಮ್ಮ {{idType}}ನಮೂದಿಸಿ",
- "noUIN/VID": "ನಿಮ್ಮ UIN/VID ಇಲ್ಲವೇ? ಇಲ್ಲಿ ಪಡೆಯಿರಿ",
- "requestingOTP": "OTP ಯನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ..."
- },
- "OtpVerificationModal": {
- "enterOtp": "ನಾವು ನಿಮಗೆ ಕಳುಹಿಸಿದ 6-ಅಂಕಿಯ ಪರಿಶೀಲನೆ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ",
- "header": "OTP ಪರಿಶೀಲನೆ"
- },
- "MyVcsTab": {
- "addVcButton": "ಸೇರಿಸಿ {{vcLabel}}",
- "generateVc": "ನಿಮ್ಮ {{vcLabel}} ಅನ್ನು ರಚಿಸಿ",
- "generateVcDescription": "ನಿಮ್ಮ \"ಸೇರಿಸಿ {{vcLabel}}\" ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ {{vcLabel}}"
- },
- "OnboardingOverlay": {
- "stepOneTitle": "ಸ್ವಾಗತ!",
- "stepOneText": "ನಿಮ್ಮ ಡಿಜಿಟಲ್ ರುಜುವಾತುಗಳನ್ನು ಯಾವಾಗಲೂ ನಿಮ್ಮೊಂದಿಗೆ ಇರಿಸಿಕೊಳ್ಳಿ. ಪ್ರಾರಂಭಿಸಲು, ನಿಮ್ಮ ಪ್ರೊಫೈಲ್ಗೆ {{vcLabel}} ಸೇರಿಸಿ.",
- "stepTwoTitle": "{{vcLabel}} ನಿರ್ವಹಣೆ",
- "stepTwoText": "ಒಮ್ಮೆ ರಚಿಸಿದ ನಂತರ, {{vcLabel}} ಅನ್ನು ನಿಮ್ಮ ಮೊಬೈಲ್ನಲ್ಲಿ ಸುರಕ್ಷಿತವಾಗಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ ಮತ್ತು ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಮರುಹೆಸರಿಸಬಹುದು ಅಥವಾ ಹಂಚಿಕೊಳ್ಳಬಹುದು.",
- "stepThreeTitle": "ಸುಲಭ ಹಂಚಿಕೆ",
- "stepThreeText": "QR ಕೋಡ್ಗಳನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ನಿಮ್ಮ ಫೋನ್ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಿಕೊಂಡು {{vcLabel}} switfly ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ ಮತ್ತು ಸ್ವೀಕರಿಸಿ.",
- "stepThreeButton": "ಪ್ರಾರಂಭಿಸಿ ಮತ್ತು {{vcLabel}} ಸೇರಿಸಿ"
- },
- "ReceivedVcsTab": {
- "noReceivedVcsTitle": "ಇನ್ನೂ ಯಾವುದೇ {{vcLabel}} ಲಭ್ಯವಿಲ್ಲ",
- "noReceivedVcsText": "{{vcLabel}} ಸ್ವೀಕರಿಸಲು ಕೆಳಗಿನ ವಿನಂತಿಯ ಮೇಲೆ ಟ್ಯಾಪ್ ಮಾಡಿ"
- },
- "ViewVcModal": {
- "cancel": "ರದ್ದುಮಾಡು",
- "lock": "ಲಾಕ್",
- "unlock": "ಅನ್ಲಾಕ್",
- "rename": "ಮರುಹೆಸರಿಸು",
- "delete": "ಅಳಿಸು",
- "revoke": "ಹಿಂತೆಗೆದುಕೊಳ್ಳಿ",
- "revoking": "ನಿಮ್ಮ ವ್ಯಾಲೆಟ್ VID {{vid}} ಜೊತೆಗೆ ರುಜುವಾತುಗಳನ್ನು ಒಳಗೊಂಡಿದೆ. ಇದನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳುವುದರಿಂದ ಅದನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ವ್ಯಾಲೆಟ್ನಿಂದ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ. ನೀವು ಮುಂದುವರೆಯಲು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?",
- "requestingOtp": "ಒಟಿಪಿಯನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ...",
- "editTag": "ಟ್ಯಾಗ್ ಸಂಪಾದಿಸು",
- "redirecting": "Redirecting...",
- "inProgress": "ಲೋಡ್ ಆಗುತ್ತಿದೆ...",
- "success": {
- "unlocked": "{{vcLabel}} ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ",
- "locked": "{{vcLabel}} successfully locked",
- "revoked": "VID {{vid}} ಅನ್ನು ಹಿಂಪಡೆಯಲಾಗಿದೆ. ಅದೇ ಒಳಗೊಂಡಿರುವ ಯಾವುದೇ ರುಜುವಾತುಗಳನ್ನು ವ್ಯಾಲೆಟ್ನಿಂದ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ"
- }
- },
- "MainLayout": {
- "home": "ಲೇಔಟ್",
- "scan": "ಮನೆ",
- "request": "ವಿನಂತಿ",
- "profile": "ಪ್ರೊಫೈಲ್"
- },
- "PasscodeScreen": {
- "header": "ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸುರಕ್ಷಿತವಾಗಿರಿಸಲು ಪಾಸ್ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ",
- "confirmPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ಅನ್ನು ದೃಢೀಕರಿಸಿ",
- "enterPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ನಮೂದಿಸಿ"
- },
- "Credits": {
- "header": "ಕ್ರೆಡಿಟ್ಗಳು ಮತ್ತು ಕಾನೂನು ಸೂಚನೆಗಳು",
- "back": "ಹಿಂದೆ"
- },
- "ProfileScreen": {
- "name": "ಹೆಸರು",
- "vcLabel": "VC ಲೇಬಲ್",
- "language": "ಭಾಷೆ",
- "bioUnlock": "ಬಯೋಮೆಟ್ರಿಕ್ ಅನ್ಲಾಕ್",
- "authFactorUnlock": "ಅನ್ಲಾಕ್ ದೃಢೀಕರಣ ಅಂಶ",
- "credits": "ಕ್ರೆಡಿಟ್ಸ್ ಮತ್ತು ಲೀಗಲ್ ನೋಟಿಸ್",
- "logout": "ಲಾಗ್-ಔಟ್",
- "revokeLabel": "ರದ್ದು VID",
- "revokeHeader": "ರದ್ದು VID",
- "revokingVids": "ನೀವು ಹಿಂತೆಗೆದುಕೊಳ್ಳಲಿದ್ದೀರಿ ({{count}}) VIDs.",
- "revokingVidsAfter": "ಇದರರ್ಥ ನೀವು ಇನ್ನು ಮುಂದೆ ಅವುಗಳಿಗೆ ಲಿಂಕ್ ಮಾಡಲಾದ ಯಾವುದೇ ID ಗಳನ್ನು ಬಳಸಲು ಅಥವಾ ವೀಕ್ಷಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ VID(s). \nನೀವು ಮುಂದುವರೆಯಲು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?",
- "empty": "ಖಾಲಿ",
- "revokeSuccessful": "VID ಯಶಸ್ವಿಯಾಗಿ ಹಿಂಪಡೆಯಲಾಗಿದೆ",
- "version": "ಆವೃತ್ತಿ"
- },
- "QrScreen": {
- "title": "QR ಲಾಗಿನ್",
- "alignQr": "ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಚೌಕಟ್ಟಿನೊಳಗೆ QR ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ",
- "confirmation": "ದೃಢೀಕರಣ",
- "checkDomain": "ಅಲ್ಲದೆ, ವಿಳಾಸ ಪಟ್ಟಿಯಲ್ಲಿ ಲಾಕ್ ಐಕಾನ್ ಇದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ.",
- "domainHead": "https://",
- "selectId": "ID ಆಯ್ಕೆಮಾಡಿ",
- "noBindedVc": "ಪರಿಶೀಲಿಸಲು ಯಾವುದೇ ಬೈಂಡೆಡ್ {{vcLabel}} ಲಭ್ಯವಿಲ್ಲ",
- "back": "ಹಿಂದೆ ಹೋಗು",
- "confirm": "ದೃಢೀಕರಿಸಿ",
- "verify": "ಪರಿಶೀಲಿಸಿ",
- "faceAuth": "ಮುಖದ ದೃಢೀಕರಣ",
- "consent": "ಒಪ್ಪಿಗೆ",
- "loading": "ಲೋಡ್ ಆಗುತ್ತಿದೆ...",
- "domainWarning": "ಕೆಳಗಿನಂತೆ ನೀವು QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡುತ್ತಿರುವ ವೆಬ್ಸೈಟ್ನ ಡೊಮೇನ್ ಅನ್ನು ದಯವಿಟ್ಟು ಖಚಿತಪಡಿಸಿ",
- "access": " ಗೆ ಪ್ರವೇಶವನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ",
- "status": "ಸ್ಥಿತಿ",
- "successMessage":"ನೀವು ಯಶಸ್ವಿಯಾಗಿ ಲಾಗ್ ಇನ್ ಆಗಿರುವಿರಿ ",
- "okay": "ಸರಿ"
- },
- "ReceiveVcScreen": {
- "header": "{{vcLabel}} ವಿವರಗಳು",
- "acceptRequest": "ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ ಮತ್ತು {{vcLabel}} ಸ್ವೀಕರಿಸಿ",
- "acceptRequestAndVerify": "ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ ಮತ್ತು ಪರಿಶೀಲಿಸಿ",
- "reject": "ತಿರಸ್ಕರಿಸಿ"
- },
- "RequestScreen": {
- "bluetoothDenied": "ವಿನಂತಿಸಲು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ{{vcLabel}}",
- "showQrCode": "ವಿನಂತಿಸಲು ಈ QR ಕೋಡ್ ಅನ್ನು ತೋರಿಸಿ {{vcLabel}}",
- "incomingVc": "ಒಳಬರುವ {{vcLabel}}",
- "request": "ವಿನಂತಿ",
- "status": {
- "accepted": {
- "title": "ಯಶಸ್ಸು!",
- "message": "{{vcLabel}}ಅನ್ನು {{sender}} ಅವರಿಂದ ಯಶಸ್ವಿಯಾಗಿ ಸ್ವೀಕರಿಸಲಾಗಿದೆ"
- },
- "rejected": {
- "title": "ಸೂಚನೆ",
- "message": "ನೀವು {{sender}} ಅವರ {{vcLabel}} ಅನ್ನು ತಿರಸ್ಕರಿಸಿದ್ದೀರಿ"
- },
- "disconnected": {
- "title": "ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ",
- "message": "ಸಂಪರ್ಕದಲ್ಲಿ ಅಡಚಣೆ ಉಂಟಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."
- },
- "waitingConnection": "ಸಂಪರ್ಕಕ್ಕಾಗಿ ಕಾಯಲಾಗುತ್ತಿದೆ...",
- "exchangingDeviceInfo": {
- "message": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ...",
- "timeoutHint": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲು ಇದು ತುಂಬಾ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತಿದೆ..."
- },
- "connected": {
- "message": "ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ. {{vcLabel}} ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ...",
- "timeoutHint": "ಇನ್ನೂ ಯಾವುದೇ ಡೇಟಾವನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿಲ್ಲ. ಸಾಧನವನ್ನು ಕಳುಹಿಸುವುದು ಇನ್ನೂ ಸಂಪರ್ಕಗೊಂಡಿದೆಯೇ?"
- }
- },
- "online": "ಆನ್ಲೈನ್",
- "offline": "ಆಫ್ಲೈನ್",
- "gotoSettings": "ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ"
- },
- "ScanScreen": {
- "header": "ಸ್ಕ್ಯಾನ್ ಕ್ಯೂಆರ್ ಕೋಡ್",
- "noShareableVcs": "ಯಾವುದೇ ಹಂಚಿಕೊಳ್ಳಬಹುದಾದ {{vcLabel}} ಲಭ್ಯವಿಲ್ಲ.",
- "sharingVc": "ಹಂಚಿಕೆ {{vcLabel}}",
- "errors": {
- "locationDisabled": {
- "message": "ಸ್ಕ್ಯಾನಿಂಗ್ ಕಾರ್ಯಕ್ಕಾಗಿ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು",
- "button": "ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"
- },
- "locationDenied": {
- "message": "ಸ್ಕ್ಯಾನಿಂಗ್ ಕಾರ್ಯಕ್ಕಾಗಿ ಸ್ಥಳ ಅನುಮತಿ ಅಗತ್ಯವಿದೆ",
- "button": "ಸ್ಥಳಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"
- }
- },
- "status": {
- "connecting": "ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ...",
- "connectingTimeout": "ಸಂಪರ್ಕವನ್ನು ಸ್ಥಾಪಿಸಲು ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ. ಇತರ ಸಾಧನವು ಸಂಪರ್ಕಗಳಿಗಾಗಿ ತೆರೆದಿದೆಯೇ?",
- "exchangingDeviceInfo": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ...",
- "exchangingDeviceInfoTimeout": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲು ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತಿದೆ. ನೀವು ಮರುಸಂಪರ್ಕಿಸಬೇಕಾಗಬಹುದು.",
- "invalid": "ಅಮಾನ್ಯ QR ಕೋಡ್"
- }
- },
- "SelectVcOverlay": {
- "header": "ಹಂಚಿಕೊಳ್ಳಿ {{vcLabel}}",
- "chooseVc": "ನೀವು ಹಂಚಿಕೊಳ್ಳಲು ಬಯಸುವ {{vcLabel}} ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಿ",
- "share": "ಹಂಚಿಕೊಳ್ಳಿ",
- "verifyAndShare": "ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳಿ"
- },
- "SendVcScreen": {
- "reasonForSharing": "ಹಂಚಿಕೆಗೆ ಕಾರಣ (ಐಚ್ಛಿಕ)",
- "acceptRequest": "ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ ಮತ್ತು ಆಯ್ಕೆಮಾಡಿ {{vcLabel}}",
- "acceptRequestAndVerify": "ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ ಮತ್ತು ಪರಿಶೀಲಿಸಿ",
- "reject": "ತಿರಸ್ಕರಿಸಿ",
- "status": {
- "sharing": {
- "title": "ಹಂಚಿಕೆ...",
- "hint": "ಸ್ವೀಕರಿಸುವ ಸಾಧನವು ಹಂಚಿಕೆಯನ್ನು ಸ್ವೀಕರಿಸಲು ಅಥವಾ ತಿರಸ್ಕರಿಸಲು ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ.",
- "timeoutHint": "ಹಂಚಿಕೊಳ್ಳಲು ನಿರೀಕ್ಷಿಸಿದ್ದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತಿದೆ. ಸಂಪರ್ಕದಲ್ಲಿ ಸಮಸ್ಯೆ ಇರಬಹುದು."
- },
- "accepted": {
- "title": "ಯಶಸ್ಸು!",
- "message": "ನಿಮ್ಮ {{vcLabel}}ನ್ನು {{receiver}} ಅವರೊಂದಿಗೆ ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ"
-
- },
- "rejected": {
- "title": "ಗಮನಿಸಿ",
- "message": "Your {{vcLabel}}ನ್ನು {{receiver}} ತಿರಸ್ಕರಿಸಿದ್ದಾರೆ "
- }
- },
- "consentToPhotoVerification": "ದೃಢೀಕರಣಕ್ಕಾಗಿ ನನ್ನ ಫೋಟೋ ತೆಗೆಯಲು ನಾನು ಒಪ್ಪಿಗೆ ನೀಡುತ್ತೇನೆ"
- },
- "VerifyIdentityOverlay": {
- "status": {
- "verifyingIdentity": "ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ..."
- },
- "errors": {
- "invalidIdentity": {
- "title": "ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ",
- "message": "ದೋಷ ಸಂಭವಿಸಿದೆ ಮತ್ತು ನಿಮ್ಮ ಭಾವಚಿತ್ರವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ನಮಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ, ನಿಮ್ಮ ಮುಖವು ಗೋಚರಿಸುತ್ತಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ, ಯಾವುದೇ ಪರಿಕರಗಳಿಲ್ಲ.",
- "messageNoRetry": "ದೋಷ ಸಂಭವಿಸಿದೆ ಮತ್ತು ನಿಮ್ಮ ಭಾವಚಿತ್ರವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ನಮಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ."
- }
- }
- },
- "SendVcModal": {
- "reasonForSharing": "ಹಂಚಿಕೆಗೆ ಕಾರಣ (ಐಚ್ಛಿಕ)",
- "acceptRequest": "ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ ಮತ್ತು {{vcLabel}} ಆಯ್ಕೆಮಾಡಿ",
- "reject": "ತಿರಸ್ಕರಿಸಿ",
- "statusSharing": {
- "title": "ಹಂಚಿಕೆ..."
- },
- "statusAccepted": {
- "title": "ಯಶಸ್ಸು!",
- "message": "ನಿಮ್ಮ {{vcLabel}} ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ {{receiver}}ಜೊತೆಗೆ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ"
- },
- "statusRejected": {
- "title": "ಸೂಚನೆ",
- "message": "ನಿಮ್ಮ {{vcLabel}}ಅನ್ನು {{receiver}}ತಿರಸ್ಕರಿಸಿದ್ದಾರೆ"
- }
- },
- "WelcomeScreen": {
- "title": "ಓಪನ್ ಸೋರ್ಸ್ ಐಡೆಂಟಿಟಿ ಸೊಲ್ಯೂಷನ್",
- "getStarted": "ಪ್ರಾರಂಭಿಸಿ",
- "unlockApp": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಿ"
- },
- "common": {
- "cancel": "ರದ್ದು",
- "save": "ಉಳಿಸು",
- "dismiss": "ವಜಾಗೊಳಿಸಿ",
- "editLabel": "ಸಂಪಾದಿಸು {{label}}",
- "tryAgain": "ಮತ್ತೆ ಪ್ರಯತ್ನಿಸು",
- "camera": {
- "errors": {
- "missingPermission": "ಮತ್ತೊಂದು ಸಾಧನದ QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತದೆ."
- },
- "allowAccess": "ಕ್ಯಾಮರಾಗೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"
+{
+ "ActivityLogText": {
+ "VC_SHARED": "ಹಂಚಿಕೊಂಡಿದ್ದಾರೆ",
+ "VC_RECEIVED": "ಸ್ವೀಕರಿಸಿದರು",
+ "VC_RECEIVED_NOT_SAVED": "ಸ್ವೀಕರಿಸಿದ ಉಳಿಸಲಾಗಿಲ್ಲ",
+ "VC_DELETED": "ಅಳಿಸಲಾಗಿದೆ",
+ "VC_DOWNLOADED": "ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗಿದೆ",
+ "VC_REVOKED": "ಹಿಂಪಡೆಯಲಾಗಿದೆ",
+ "VC_SHARED_WITH_VERIFICATION_CONSENT": "ಹಂಚಿಕೊಂಡಿದ್ದಾರೆ. ಉಪಸ್ಥಿತಿ ಪರಿಶೀಲನೆಗೆ ಒಪ್ಪಿಗೆ ನೀಡಲಾಗಿದೆ",
+ "VC_RECEIVED_WITH_PRESENCE_VERIFIED": "ಸ್ವೀಕರಿಸಿದರು. ಉಪಸ್ಥಿತಿಯನ್ನು ಪರಿಶೀಲಿಸಲಾಗಿದೆ",
+ "VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "ಸ್ವೀಕರಿಸಿದರು. ಉಪಸ್ಥಿತಿ ಪರಿಶೀಲನೆ ವಿಫಲವಾಗಿದೆ",
+ "PRESENCE_VERIFIED_AND_VC_SHARED": "ಪರಿಶೀಲಿಸಲಾಗಿದೆ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ",
+ "PRESENCE_VERIFICATION_FAILED": "ಪರಿಶೀಲನೆ ವಿಫಲವಾಗಿದೆ",
+ "QRLOGIN_SUCCESFULL": "QRಲಾಗಿನ್ ಯಶಸ್ವಿಯಾಗಿದೆ",
+ "WALLET_BINDING_SUCCESSFULL": "ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿದೆ",
+ "WALLET_BINDING_FAILURE": "ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆ ವಿಫಲವಾಗಿದೆ",
+ "VC_REMOVED":"ಕೈಚೀಲದಿಂದ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"
+ },
+ "DeviceInfoList": {
+ "requestedBy": "ವಿನಂತಿಸಿದವರು",
+ "sentBy": "ಕಳುಹಿಸಿದವರು",
+ "deviceRefNumber": "ಸಾಧನ ಉಲ್ಲೇಖ ಸಂಖ್ಯೆ",
+ "name": "ಹೆಸರು",
+ "Verifier": "ಪರಿಶೀಲಕ",
+ "Wallet": "ವಾಲೆಟ್"
+ },
+ "PasscodeVerify": {
+ "passcodeMismatchError": "ಪಾಸ್ಕೋಡ್ ಹೊಂದಿಕೆಯಾಗಲಿಲ್ಲ."
+ },
+ "FaceScanner": {},
+ "OIDcAuth": {
+ "title": "OIDC ದೃಢೀಕರಣ",
+ "text": "OIDC ಪೂರೈಕೆದಾರ UI ನೊಂದಿಗೆ ಬದಲಾಯಿಸಲು",
+ "verify": "ಪರಿಶೀಲಿಸಿ"
+ },
+ "QrScanner": {
+ "cameraAccessDisabled": "ಕ್ಯಾಮರಾ ಪ್ರವೇಶವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ!",
+ "cameraPermissionGuideLabel": "ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ ಮತ್ತು ಕ್ಯಾಮರಾ ಪ್ರವೇಶವನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸಿ.",
+ "flipCamera": "ಫ್ಲಿಪ್ ಕ್ಯಾಮೆರಾ"
+ },
+ "VcDetails": {
+ "generatedOn": "ಜನರೇಟೆಡ್ ಆನ್",
+ "status": "ಸ್ಥಿತಿ",
+ "valid": "ಮಾನ್ಯ",
+ "photo": "ಫೋಟೋ",
+ "fullName": "ಪೂರ್ಣ ಹೆಸರು",
+ "gender": "ಲಿಂಗ",
+ "dateOfBirth": "ಹುಟ್ಟಿದ ದಿನಾಂಕ",
+ "phoneNumber": "ಫೋನ್ ಸಂಖ್ಯೆ",
+ "email": "ಇಮೇಲ್",
+ "address": "ವಿಳಾಸ",
+ "reasonForSharing": "ಹಂಚಿಕೆಗೆ ಕಾರಣ",
+ "idType": "ಐಡಿಟೈಪ್",
+ "id": "ಐಡಿ",
+ "qrCodeHeader": "QR ಕೋಡ್",
+ "nationalCard": "ರಾಷ್ಟ್ರೀಯ ಕಾರ್ಡ್",
+ "uin": "UIN",
+ "vid": "VID",
+ "enableVerification": "ಸಕ್ರಿಯಗೊಳಿಸಿ",
+ "profileAuthenticated": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ!",
+ "offlineAuthDisabledHeader": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆ ಬಾಕಿ ಉಳಿದಿದೆ!",
+ "offlineAuthDisabledMessage": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಬಳಸಲು ಈ ರುಜುವಾತುಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ದಯವಿಟ್ಟು ಕೆಳಗಿನ ಬಟನ್ ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ.",
+ "verificationEnabledSuccess": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ",
+ "goback": "ಹಿಂದೆ ಹೋಗು",
+ "BindingWarning": "ನೀವು ಇನ್ನೊಂದು ವ್ಯಾಲೆಟ್ನಲ್ಲಿ ಈ ರುಜುವಾತುಗಳಿಗಾಗಿ ಪರಿಶೀಲನೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದರೆ, ಅದನ್ನು ಅತಿಕ್ರಮಿಸಲಾಗುತ್ತದೆ. ನೀವು ಮುಂದುವರೆಯಲು ಬಯಸುವಿರಾ?",
+ "yes_confirm": "ಹೌದು, ನಾನು ದೃಢೀಕರಿಸುತ್ತೇನೆ",
+ "no": "ಸಂ",
+ "Alert": "ಎಚ್ಚರಿಕೆ",
+ "ok": "ಸರಿ",
+ "credentialRegistry": "ರುಜುವಾತುಗಳ ನೋಂದಣಿ",
+ "errors": {
+ "savingFailed": {
+ "title": "ಕಾರ್ಡ್ ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ",
+ "message": "ಸ್ಟೋರ್ನಲ್ಲಿ ಕಾರ್ಡ್ ಉಳಿಸುವಾಗ ಏನೋ ತಪ್ಪಾಗಿದೆ."
}
}
- }
\ No newline at end of file
+ },
+ "HomeScreenKebabPopUp": {
+ "title": "ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು",
+ "unPinCard": "ಅನ್ಪಿನ್ ಕಾರ್ಡ್",
+ "pinCard": "ಪಿನ್ ಕಾರ್ಡ್",
+ "offlineAuthenticationDisabled!": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆ ಬಾಕಿ ಉಳಿದಿದೆ!",
+ "offlineAuthDisabledMessage": "ಆನ್ಲೈನ್ ದೃಢೀಕರಣಕ್ಕಾಗಿ ಬಳಸಲು ಈ ರುಜುವಾತುಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಇಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ.",
+ "viewActivityLog": "ಚಟುವಟಿಕೆ ಲಾಗ್ ಅನ್ನು ವೀಕ್ಷಿಸಿ",
+ "removeFromWallet": "ಕೈಚೀಲದಿಂದ ತೆಗೆದುಹಾಕಿ",
+ "revokeId": "ID ಹಿಂತೆಗೆದುಕೊಳ್ಳಿ",
+ "revokeMessage": "ಈ ಪ್ರೊಫೈಲ್ಗಾಗಿ ವರ್ಚುವಲ್ ಐಡಿಯನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳಿ"
+ },
+ "WalletBinding": {
+ "inProgress": "ಪ್ರಗತಿಯಲ್ಲಿದೆ",
+ "profileAuthenticated": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ!"
+ },
+ "BindingVcWarningOverlay": {
+ "alert": "ದಯವಿಟ್ಟು ದ್ರುಡೀಕರಿಸಿ",
+ "BindingWarning": "ನೀವು ಇನ್ನೊಂದು ವ್ಯಾಲೆಟ್ನಲ್ಲಿ ಈ ರುಜುವಾತುಗಳಿಗಾಗಿ ಪರಿಶೀಲನೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದರೆ, ಅದನ್ನು ಅತಿಕ್ರಮಿಸಲಾಗುತ್ತದೆ. ನೀವು ಮುಂದುವರೆಯಲು ಬಯಸುವಿರಾ?",
+ "yesConfirm": "ಹೌದು, ನಾನು ದೃಢೀಕರಿಸುತ್ತೇನೆ",
+ "no": "ಸಂ"
+ },
+ "RemoveVcWarningOverlay": {
+ "alert": "ದಯವಿಟ್ಟು ದ್ರುಡೀಕರಿಸಿ",
+ "removeWarning": "ನೀವು ಈ ಕಾರ್ಡ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲು ಬಯಸುವಿರಾ",
+ "confirm": "ಹೌದು, ನಾನು ದೃಢೀಕರಿಸುತ್ತೇನೆ",
+ "no": "ಸಂ"
+ },
+ "AuthScreen": {
+ "header": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬಳಸಲು ನೀವು ಬಯಸುವಿರಾ?",
+ "Description": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬಳಸಲು ನೀವು ಬಯಸುವಿರಾ?",
+ "useBiometrics": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬಳಸಿ",
+ "usePasscode": "ನಾನು ಪಾಸ್ಕೋಡ್ ಅನ್ನು ಬಳಸುತ್ತೇನೆ",
+ "errors": {
+ "unavailable": "ಸಾಧನವು ಬಯೋಮೆಟ್ರಿಕ್ಗಳನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ",
+ "unenrolled": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅನ್ನು ಬಳಸಲು, ದಯವಿಟ್ಟು ನಿಮ್ಮ ಸಾಧನದ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ನೋಂದಾಯಿಸಿ",
+ "failed": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ನೊಂದಿಗೆ ದೃಢೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ",
+ "generic": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ದೃಢೀಕರಣದಲ್ಲಿ ದೋಷ ಕಂಡುಬರುತ್ತಿದೆ"
+ }
+ },
+ "BiometricScreen": {
+ "unlock": "ಫಿಂಗರ್ಪ್ರಿಂಟ್ನೊಂದಿಗೆ ಅನ್ಲಾಕ್"
+ },
+ "HistoryScreen": {
+ "noHistory": "ಇನ್ನೂ ಇತಿಹಾಸವಿಲ್ಲ",
+ "downloaded": "ಸಿಕ್ಕಿತು",
+ "shared": "ಹಂಚಿಕೊಂಡಿದ್ದಾರೆ",
+ "received": "ಸ್ವೀಕರಿಸಿದರು",
+ "deleted": "ತೆಗೆದುಹಾಕಲಾಗಿದೆ"
+ },
+ "SettingScreen": {
+ "header": "ಸಂಯೋಜನೆಗಳು",
+ "injiAsVerifierApp": "ವೆರಿಫೈಯರ್ ಆಪ್ ಆಗಿ ಇಂಜಿ",
+ "receiveCard": "ಕಾರ್ಡ್ ಸ್ವೀಕರಿಸಿ",
+ "basicSettings": "ಮೂಲ ಸೆಟ್ಟಿಂಗ್ಗಳು",
+ "bioUnlock": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ನೊಂದಿಗೆ ಅನ್ಲಾಕ್ ಮಾಡಿ",
+ "language": "ಭಾಷೆ",
+ "aboutInji": "ಇಂಜಿ ಬಗ್ಗೆ",
+ "credentialRegistry": "ರುಜುವಾತು ನೋಂದಣಿ",
+ "errorMessage": "ತಪ್ಪಾದ URL ನಮೂದಿಸಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಮುಂದುವರೆಯಲು ಮಾನ್ಯ URL ಅನ್ನು ನಮೂದಿಸಿ.",
+ "injiTourGuide": "ಇಂಜಿ ಪ್ರವಾಸ ಮಾರ್ಗದರ್ಶಿ",
+ "logout": "ಲಾಗ್ ಔಟ್",
+ "resetInjiProps": "ಇಂಜಿ ಪ್ರಾಪ್ಸ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತಿದೆ..."
+ },
+ "AboutInji": {
+ "aboutInji": "ಇಂಜಿ ಬಗ್ಗೆ",
+ "header": "ಇಂಜಿ ಬಗ್ಗೆ",
+ "appID": "ಆಪ್ ID",
+ "aboutDetailes": "ಇಂಜಿ ಎನ್ನುವುದು ರುಜುವಾತುಗಳನ್ನು ಸಂಗ್ರಹಿಸಲು ಡಿಜಿಟಲ್ ವ್ಯಾಲೆಟ್ ಆಗಿ ಬಳಸಬಹುದಾದ ಮೊಬೈಲ್ ಅಪ್ಲಿಕೇಶನ್ ಆಗಿದೆ. ಇದು ಯಾವುದೇ ಸ್ಥಳ ಮತ್ತು ಸಮಯದಲ್ಲಿ ಆಫ್ಲೈನ್ ಮತ್ತು ಆನ್ಲೈನ್ ಮೋಡ್ಗಳಲ್ಲಿ ಗುರುತಿನ ಪರಿಶೀಲನೆಯನ್ನು ಅನುಮತಿಸುತ್ತದೆ.",
+ "forMoreDetailes": "ಹೆಚ್ಚಿನ ವಿವರಗಳಿಗಾಗಿ",
+ "clickHere": "ಇಲ್ಲಿ ಕ್ಲಿಕ್ ಮಾಡಿ",
+ "version": "ಆವೃತ್ತಿ",
+ "tuvaliVersion": "ಟುವಾಲಿ-ಆವೃತ್ತಿ"
+ },
+ "HelpScreen": {
+ "header": "ಸಹಾಯ",
+ "whatIsDigitalCredential?": "ಡಿಜಿಟಲ್ ರುಜುವಾತು ಎಂದರೇನು?",
+ "detail-1": "ಡಿಜಿಟಲ್ ರುಜುವಾತು ನಿಮ್ಮ ಭೌತಿಕ ಗುರುತಿನ ಚೀಟಿಯ ಡಿಜಿಟಲ್ ಆವೃತ್ತಿಯಾಗಿದೆ",
+ "whatCanDoWithDigitalCredential?": "ಡಿಜಿಟಲ್ ರುಜುವಾತುಗಳೊಂದಿಗೆ ನಾವು ಏನು ಮಾಡಬಹುದು?",
+ "detail-2": "ನಿಮ್ಮ ಡಿಜಿಟಲ್ ರುಜುವಾತುಗಳನ್ನು ಬಳಸಿಕೊಂಡು ನೀವು ವಿವಿಧ ಸರ್ಕಾರಿ ಮತ್ತು ಖಾಸಗಿ ಸೇವೆಗಳನ್ನು ಪಡೆಯಬಹುದು.",
+ "howToAddCard?": "ಕಾರ್ಡ್ ಅನ್ನು ಹೇಗೆ ಸೇರಿಸುವುದು?",
+ "detail-3": "ಕಾರ್ಡ್ ಸೇರಿಸಲು, ಮುಖಪುಟದಲ್ಲಿ '+' ಬಟನ್ ಕ್ಲಿಕ್ ಮಾಡಿ ಮತ್ತು ಸೂಕ್ತವಾದ ಆಯ್ಕೆಯನ್ನು ಆರಿಸಿ.",
+ "howToRemoveCardFromWallet?": "ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳುವುದು ಹೇಗೆ?",
+ "detail-4": "ಕಾರ್ಡ್ನಲ್ಲಿ ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ > ಇನ್ನಷ್ಟು ಕ್ಲಿಕ್ ಮಾಡಿ > ವಾಲೆಟ್ನಿಂದ ತೆಗೆದುಹಾಕಿ",
+ "canWeAddMultipleCards?": "ನಾವು ಬಹು ಕಾರ್ಡ್ಗಳನ್ನು ಸೇರಿಸಬಹುದೇ?",
+ "detail-5": "ಹೌದು, ಮುಖಪುಟದಲ್ಲಿ '+' ಬಟನ್ ಕ್ಲಿಕ್ ಮಾಡುವ ಮೂಲಕ ನೀವು ಬಹು ಕಾರ್ಡ್ಗಳನ್ನು ವ್ಯಾಲೆಟ್ಗೆ ಸೇರಿಸಬಹುದು.",
+ "howToShareCard?": "ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳುವುದು ಹೇಗೆ?",
+ "detail-6": "'ಹಂಚಿಕೊಳ್ಳಿ' ಬಟನ್ ಕ್ಲಿಕ್ ಮಾಡಿ ಮತ್ತು ವಿನಂತಿಸಿದ ಪಕ್ಷದಿಂದ QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ. ಸಂಪರ್ಕವನ್ನು ಸ್ಥಾಪಿಸಿದ ನಂತರ, ಕಾರ್ಡ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.",
+ "howToActivateCardForOnlineLogin?": "ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಕಾರ್ಡ್ ಅನ್ನು ಹೇಗೆ ಸಕ್ರಿಯಗೊಳಿಸುವುದು?",
+ "detail-7": "ವ್ಯಾಲೆಟ್ಗೆ ಕಾರ್ಡ್ ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಸೇರಿಸಿದ ನಂತರ, ಕಾರ್ಡ್ನಲ್ಲಿರುವ 'ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗಾಗಿ ಆಕ್ಟಿವೇಶನ್ ಪೆಂಡಿಂಗ್' ಅನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ. 'ಸಕ್ರಿಯಗೊಳಿಸು' ಕ್ಲಿಕ್ ಮಾಡಿದಾಗ, ಕಾರ್ಡ್ ಆನ್ಲೈನ್ ಲಾಗಿನ್ಗೆ ಬಳಸಲು ಸಿದ್ಧವಾಗುತ್ತದೆ.",
+ "howToViewActivity?": "ಚಟುವಟಿಕೆ ಲಾಗ್ಗಳನ್ನು ವೀಕ್ಷಿಸುವುದು ಹೇಗೆ?",
+ "detail-8": "ಮುಖಪುಟದಲ್ಲಿ, ಬಳಕೆದಾರರ ಚಟುವಟಿಕೆಯ ವಿವರಗಳನ್ನು ವೀಕ್ಷಿಸಲು 'ಇತಿಹಾಸ' ಕ್ಲಿಕ್ ಮಾಡಿ.",
+ "whatCanDoBiometricsChanged?": "ಆಂಡ್ರಾಯ್ಡ್ ಕೀಸ್ಟೋರ್ ಬಯೋಮೆಟ್ರಿಕ್ ಅನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಏನಾಗುತ್ತದೆ?",
+ "detail-9": "ಆಂಡ್ರಾಯ್ಡ್ ಕೀಸ್ಟೋರ್ ಗುರುತಿನ ಪುರಾವೆಗಳಿಗಾಗಿ ಖಾಸಗಿ ಕೀಗಳಂತಹ ಪ್ರಮುಖ ಮಾಹಿತಿಯನ್ನು ಹೊಂದಿದೆ. ನಿಮ್ಮ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅನ್ನು ನೀವು ಬದಲಾಯಿಸಿದಾಗ, ಹಳೆಯ ಕೀಗಳು ಇನ್ನು ಮುಂದೆ ಸುರಕ್ಷಿತವಾಗಿರುವುದಿಲ್ಲ. ವಿಷಯಗಳನ್ನು ಸುರಕ್ಷಿತವಾಗಿರಿಸಲು, ಆ ಹಳೆಯ ಕೀಗಳಿಂದ ಸಹಿ ಮಾಡಿದ ಗುರುತಿನ ಪುರಾವೆಗಳನ್ನು ನಾವು ತೆಗೆದುಹಾಕುತ್ತೇವೆ. ನಿಮ್ಮ ಗುರುತಿನ ಪುರಾವೆಗಳನ್ನು ನೀವು ಸರಳವಾಗಿ ಡೌನ್ಲೋಡ್ ಮಾಡಬಹುದು ಮತ್ತು ಅವುಗಳನ್ನು ಇತ್ತೀಚಿನ, ಸುರಕ್ಷಿತ ಕೀಗಳೊಂದಿಗೆ ಸಹಿ ಮಾಡಲಾಗುತ್ತದೆ."
+ },
+ "AddVcModal": {
+ "requestingCredential": "ರುಜುವಾತುಗಳನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ...",
+ "errors": {
+ "input": {
+ "empty": "ಇನ್ಪುಟ್ ಖಾಲಿ ಇರುವಂತಿಲ್ಲ",
+ "invalidFormat": "ಇನ್ಪುಟ್ ಫಾರ್ಮ್ಯಾಟ್ ತಪ್ಪಾಗಿದೆ"
+ },
+ "backend": {
+ "invalidOtp": "OTP ಅಮಾನ್ಯವಾಗಿದೆ",
+ "expiredOtp": "OTP ಅವಧಿ ಮುಗಿದಿದೆ",
+ "invalidUin": "UIN ಅಮಾನ್ಯವಾಗಿದೆ",
+ "invalidVid": "VID ಅಮಾನ್ಯವಾಗಿದೆ",
+ "missingUin": "ನಮೂದಿಸಿದ UIN ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ/ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ದಯವಿಟ್ಟು ಮಾನ್ಯವಾದ UIN ಅನ್ನು ನಮೂದಿಸಿ",
+ "missingVid": "VID ಡೇಟಾಬೇಸ್ನಲ್ಲಿ ಲಭ್ಯವಿಲ್ಲ",
+ "noMessageAvailable": "ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಪ್ರಯತ್ನಿಸಿ",
+ "whileGeneratingOtpErrorIsOccured": "OTP ರಚಿಸುವಾಗ ದೋಷ ಸಂಭವಿಸಿದೆ",
+ "networkRequestFailed": "ನೆಟ್ವರ್ಕ್ ವಿನಂತಿ ವಿಫಲವಾಗಿದೆ",
+ "deactivatedVid": "ನಮೂದಿಸಿದ VID ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ/ಅವಧಿ ಮೀರಿದೆ. ಮುಂದುವರೆಯಲು ದಯವಿಟ್ಟು ಮಾನ್ಯವಾದ VID ಅನ್ನು ನಮೂದಿಸಿ"
+ }
+ }
+ },
+ "GetVcModal": {
+ "retrievingId": "ID ಮರುಪಡೆಯಲಾಗುತ್ತಿದೆ",
+ "errors": {
+ "input": {
+ "empty": "ಇನ್ಪುಟ್ ಖಾಲಿ ಇರುವಂತಿಲ್ಲ",
+ "invalidFormat": "ಇನ್ಪುಟ್ ಫಾರ್ಮ್ಯಾಟ್ ತಪ್ಪಾಗಿದೆ"
+ },
+ "backend": {
+ "invalidOtp": "OTP ಅಮಾನ್ಯವಾಗಿದೆ",
+ "expiredOtp": "OTP ಅವಧಿ ಮುಗಿದಿದೆ",
+ "applicationProcessing": "AID ಸಿದ್ಧವಾಗಿಲ್ಲ",
+ "noMessageAvailable": "ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಪ್ರಯತ್ನಿಸಿ",
+ "networkRequestFailed": "ನೆಟ್ವರ್ಕ್ ವಿನಂತಿ ವಿಫಲವಾಗಿದೆ",
+ "invalidAid": "ನಮೂದಿಸಿದ AID ಲಭ್ಯವಿಲ್ಲ. ಪ್ರವೇಶಿಸುವ ಮೊದಲು ದಯವಿಟ್ಟು ನಿಮ್ಮ AID ಅನ್ನು ಪರಿಶೀಲಿಸಿ",
+ "timeout": "ಸಮಯ ಮೀರಿದೆ"
+ }
+ }
+ },
+ "DownloadingVcModal": {
+ "header": "ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ ಕಾರ್ಡ್",
+ "bodyText": "ಇದು ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳಬಹುದು, ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಿದಾಗ ಮತ್ತು ಲಭ್ಯವಿದ್ದಾಗ ನಾವು ನಿಮಗೆ ತಿಳಿಸುತ್ತೇವೆ",
+ "backButton": "ಬ್ಯಾಕ್ ಹೋಮ್"
+ },
+ "GetIdInputModal": {
+ "header": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಹಿಂಪಡೆಯಿರಿ",
+ "applicationIdLabel": "ದಯವಿಟ್ಟು ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಐಡಿಯನ್ನು ನಮೂದಿಸಿ",
+ "enterApplicationId": "ಅಪ್ಲಿಕೇಶನ್ ID ನಮೂದಿಸಿ",
+ "requestingOTP": "OTP ಯನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ...",
+ "qstnMarkToolTip": "ನೋಂದಣಿಯ ನಂತರ ಸ್ವೀಕರಿಸಿದ ಸ್ವೀಕೃತಿಯಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ID ಲಭ್ಯವಿದೆ.",
+ "getUIN": "UIN/VID ಪಡೆಯಿರಿ"
+ },
+ "IdInputModal": {
+ "header": "ನಿಮ್ಮ ಐಡಿಯನ್ನು ಹಿಂಪಡೆಯಿರಿ",
+ "guideLabel": "ID ಪ್ರಕಾರವನ್ನು ಆಯ್ಕೆಮಾಡಿ ಮತ್ತು MOSIP ಒದಗಿಸಿದ UIN ಅಥವಾ ನೀವು ಹಿಂಪಡೆಯಲು ಬಯಸುವ ID ಯ VID ಅನ್ನು ನಮೂದಿಸಿ",
+ "generateVc": "ಕಾರ್ಡ್ ಅನ್ನು ರಚಿಸಿ",
+ "downloadID": "ಐಡಿ ಡೌನ್ಲೋಡ್ ಮಾಡಿ",
+ "enterId": "{{idType}} ನಮೂದಿಸಿ",
+ "noUIN/VID": "UIN/VID ಇಲ್ಲವೇ? ",
+ "getItHere": "ಈಗಲೇ ತಾ",
+ "requestingOTP": "OTP ಯನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ..."
+ },
+ "OtpVerificationModal": {
+ "title": "OTP ಪರಿಶೀಲನೆ",
+ "otpSentMessage": "ನಿಮ್ಮ ನೋಂದಾಯಿತ ಮೊಬೈಲ್ ಸಂಖ್ಯೆಗೆ ನಾವು 6 ಅಂಕಿಗಳ ಕೋಡ್ ಅನ್ನು ಕಳುಹಿಸಿದ್ದೇವೆ!",
+ "resendTheCode": "ನೀವು ಕೋಡ್ ಅನ್ನು ಮತ್ತೆ ಕಳುಹಿಸಬಹುದು ",
+ "resendCode": "ಕೋಡ್ ಅನ್ನು ಮರುಕಳುಹಿಸಿ"
+ },
+ "MyVcsTab": {
+ "downloadCard": "ಕಾರ್ಡ್ ಡೌನ್ಲೋಡ್ ಮಾಡಿ",
+ "bringYourDigitalID": "ನಿಮ್ಮ ಡಿಜಿಟಲ್ ಐಡಿ ತನ್ನಿ",
+ "generateVcDescription": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಕೆಳಗಿನ ಡೌನ್ಲೋಡ್ ಕಾರ್ಡ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ",
+ "downloadingYourCard": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ, ಇದು 5 ನಿಮಿಷಗಳವರೆಗೆ ತೆಗೆದುಕೊಳ್ಳಬಹುದು",
+ "errors": {
+ "savingFailed": {
+ "title": "ಕಾರ್ಡ್ ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ",
+ "message": "ಸ್ಟೋರ್ನಲ್ಲಿ ಕಾರ್ಡ್ ಉಳಿಸುವಾಗ ಏನೋ ತಪ್ಪಾಗಿದೆ."
+ },
+ "storageLimitReached": {
+ "title": "ಸಾಕಷ್ಟಿಲ್ಲ ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು",
+ "message": "ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾ ತುಂಬಿರುವುದರಿಂದ ನೀವು ಕಾರ್ಡ್ಗಳನ್ನು ಸೇರಿಸಲು ಅಥವಾ ಸ್ವೀಕರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮುಂದುವರೆಯಲು ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ."
+ },
+ "vcIsTampered": {
+ "title": "ಕೆಲವು ಗುರುತಿನ ಪುರಾವೆಗಳನ್ನು ಹಾಳುಮಾಡಲಾಗಿದೆ",
+ "message": "ಬಾಧಿತ ಫೈಲ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ, ದಯವಿಟ್ಟು ಮರು-ಡೌನ್ಲೋಡ್ ಮಾಡಿ."
+ },
+ "keystoreNotExists": {
+ "title": "ಸುರಕ್ಷಿತ ಕೀ ಸಂಗ್ರಹಣೆ ಕಂಡುಬಂದಿಲ್ಲ",
+ "message": "ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿರುವ ಕೀ ಸಂಗ್ರಹಣೆಯು ಸುರಕ್ಷಿತವಾಗಿಲ್ಲ. ಫೋನ್ ಹ್ಯಾಕ್ ಆಗಿದ್ದರೆ ನಿಮ್ಮ ಕೀಗಳು ಸೋರಿಕೆಯಾಗಬಹುದು.",
+ "riskOkayText": "ಸರಿ, ನಾನು ಅದನ್ನು ಅಪಾಯಕ್ಕೆ ತೆಗೆದುಕೊಳ್ಳುತ್ತೇನೆ"
+ }
+ }
+ },
+ "OnboardingOverlay": {
+ "stepOneTitle": "ಸುರಕ್ಷಿತ ಹಂಚಿಕೆ!",
+ "stepOneText": "ನಿಮ್ಮ ಡಿಜಿಟಲ್ ರುಜುವಾತುಗಳನ್ನು ಯಾವಾಗಲೂ ನಿಮ್ಮೊಂದಿಗೆ ಇರಿಸಿಕೊಳ್ಳಿ. ಅವುಗಳನ್ನು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ನಿರ್ವಹಿಸಲು ಮತ್ತು ಬಳಸಲು ಇಂಜಿ ನಿಮಗೆ ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಪ್ರಾರಂಭಿಸಲು, ನಿಮ್ಮ ಪ್ರೊಫೈಲ್ಗೆ ಕಾರ್ಡ್ಗಳನ್ನು ಸೇರಿಸಿ.",
+ "stepTwoTitle": "ವಿಶ್ವಾಸಾರ್ಹ ಡಿಜಿಟಲ್ ವಾಲೆಟ್",
+ "stepTwoText": "ನಿಮ್ಮ ಎಲ್ಲಾ ಪ್ರಮುಖ ಕಾರ್ಡ್ಗಳನ್ನು ಒಂದೇ ವಿಶ್ವಾಸಾರ್ಹ ವ್ಯಾಲೆಟ್ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಿ ಮತ್ತು ಒಯ್ಯಿರಿ.",
+ "stepThreeTitle": "ಸುರಕ್ಷಿತ ಹಂಚಿಕೆ",
+ "stepThreeText": "ನಿಮ್ಮ ಕಾರ್ಡ್ಗಳನ್ನು ಜಗಳ ಮುಕ್ತ ರೀತಿಯಲ್ಲಿ ಸುರಕ್ಷಿತವಾಗಿ ಹಂಚಿಕೊಳ್ಳಿ ಮತ್ತು ವಿವಿಧ ಸೇವೆಗಳನ್ನು ಪಡೆದುಕೊಳ್ಳಿ.",
+ "stepFourTitle": "ಜಗಳ ಮುಕ್ತ ದೃಢೀಕರಣ",
+ "stepFourText": "ಸಂಗ್ರಹಿಸಿದ ಡಿಜಿಟಲ್ ರುಜುವಾತುಗಳನ್ನು ಬಳಸಿಕೊಂಡು ಸುಲಭವಾಗಿ ನಿಮ್ಮನ್ನು ದೃಢೀಕರಿಸಿ.",
+ "getStarted": "ಪ್ರಾರಂಭಿಸಿ",
+ "goBack": "ಹಿಂದೆ ಹೋಗು",
+ "back": "ಹಿಂದೆ",
+ "skip": "ಬಿಟ್ಟುಬಿಡಿ",
+ "next": "ಮುಂದೆ"
+ },
+ "ReceivedVcsTab": {
+ "receivedCards": "ಕಾರ್ಡ್ಗಳನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿದೆ",
+ "header": "ಕಾರ್ಡ್ಗಳನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿದೆ",
+ "noReceivedVcsTitle": "ಇನ್ನೂ ಯಾವುದೇ ಕಾರ್ಡ್ ಲಭ್ಯವಿಲ್ಲ",
+ "noReceivedVcsText": "ಕಾರ್ಡ್ ಸ್ವೀಕರಿಸಲು ಕೆಳಗಿನ ವಿನಂತಿಯ ಮೇಲೆ ಟ್ಯಾಪ್ ಮಾಡಿ"
+ },
+ "ViewVcModal": {
+ "title": "ID ವಿವರಗಳು",
+ "inProgress": "ಪ್ರಗತಿಯಲ್ಲಿದೆ",
+ "cancel": "ರದ್ದುಮಾಡು",
+ "lock": "ಲಾಕ್",
+ "unlock": "ಅನ್ಲಾಕ್",
+ "rename": "ಮರುಹೆಸರಿಸು",
+ "delete": "ಅಳಿಸು",
+ "revoke": "ಹಿಂತೆಗೆದುಕೊಳ್ಳಿ",
+ "revoking": "ನಿಮ್ಮ ವ್ಯಾಲೆಟ್ VID {{vid}} ಜೊತೆಗೆ ರುಜುವಾತುಗಳನ್ನು ಒಳಗೊಂಡಿದೆ. ಇದನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳುವುದರಿಂದ ಅದನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ವ್ಯಾಲೆಟ್ನಿಂದ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ. ನೀವು ಮುಂದುವರೆಯಲು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?",
+ "requestingOtp": "ಒಟಿಪಿಯನ್ನು ವಿನಂತಿಸಲಾಗುತ್ತಿದೆ...",
+ "editTag": "ಟ್ಯಾಗ್ ಸಂಪಾದಿಸು",
+ "redirecting": "ಮರುನಿರ್ದೇಶಿಸಲಾಗುತ್ತಿದೆ...",
+ "success": {
+ "unlocked": "ಕಾರ್ಡ್ ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗಿದೆ",
+ "locked": "ಕಾರ್ಡ್ ಯಶಸ್ವಿಯಾಗಿ ಲಾಕ್ ಆಗಿದೆ",
+ "revoked": "VID {{vid}} ಅನ್ನು ಹಿಂಪಡೆಯಲಾಗಿದೆ. ಅದೇ ಒಳಗೊಂಡಿರುವ ಯಾವುದೇ ರುಜುವಾತುಗಳನ್ನು ವ್ಯಾಲೆಟ್ನಿಂದ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ"
+ }
+ },
+ "MainLayout": {
+ "home": "ಲೇಔಟ್",
+ "scan": "ಮನೆ",
+ "history": "ಇತಿಹಾಸ",
+ "request": "ವಿನಂತಿ",
+ "settings": "ಸೆಟ್ಟಿಂಗ್ಗಳು"
+ },
+ "PasscodeScreen": {
+ "header": "ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸುರಕ್ಷಿತವಾಗಿರಿಸಲು ಪಾಸ್ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ",
+ "enterNewPassword": "ಹೊಸ ಪಾಸ್ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ",
+ "reEnterPassword": "ಹೊಸ ಪಾಸ್ಕೋಡ್ ಅನ್ನು ಮರು-ನಮೂದಿಸಿ",
+ "confirmPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ಅನ್ನು ದೃಢೀಕರಿಸಿ",
+ "enterPasscode": "ನಿಮ್ಮ ಪಾಸ್ಕೋಡ್ ನಮೂದಿಸಿ"
+ },
+ "AppMetaData": {
+ "header": "ಇಂಜಿ ಬಗ್ಗೆ",
+ "version": "ಆವೃತ್ತಿ",
+ "useBle": "BLE ನಿಂದ ನಡೆಸಲ್ಪಡುತ್ತಿದೆ"
+ },
+ "QrScreen": {
+ "title": "QR ಲಾಗಿನ್",
+ "alignQr": "ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಚೌಕಟ್ಟಿನೊಳಗೆ QR ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ",
+ "confirmation": "ದೃಢೀಕರಣ",
+ "checkDomain": "ಅಲ್ಲದೆ, ವಿಳಾಸ ಪಟ್ಟಿಯಲ್ಲಿ ಲಾಕ್ ಐಕಾನ್ ಇದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ.",
+ "domainHead": "https://",
+ "selectId": "ID ಆಯ್ಕೆಮಾಡಿ",
+ "noBindedVc": "ಪರಿಶೀಲಿಸಲು ಯಾವುದೇ ಬೈಂಡೆಡ್ ಕಾರ್ಡ್ ಲಭ್ಯವಿಲ್ಲ",
+ "back": "ಹಿಂದೆ ಹೋಗು",
+ "confirm": "ದೃಢೀಕರಿಸಿ",
+ "verify": "ಪರಿಶೀಲಿಸಿ",
+ "faceAuth": "ಮುಖದ ದೃಢೀಕರಣ",
+ "consent": "ಒಪ್ಪಿಗೆ",
+ "loading": "ಲೋಡ್ ಆಗುತ್ತಿದೆ...",
+ "domainWarning": "ಕೆಳಗಿನಂತೆ ನೀವು QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡುತ್ತಿರುವ ವೆಬ್ಸೈಟ್ನ ಡೊಮೇನ್ ಅನ್ನು ದಯವಿಟ್ಟು ಖಚಿತಪಡಿಸಿ",
+ "access": " ಗೆ ಪ್ರವೇಶವನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ",
+ "status": "ಸ್ಥಿತಿ",
+ "successMessage": "ನೀವು ಯಶಸ್ವಿಯಾಗಿ ಲಾಗ್ ಇನ್ ಆಗಿರುವಿರಿ ",
+ "okay": "ಸರಿ",
+ "allow": "ಅನುಮತಿಸಿ",
+ "cancel": "ರದ್ದುಮಾಡು",
+ "essentialClaims": "ಅಗತ್ಯ ಹಕ್ಕುಗಳು",
+ "voluntaryClaims": "ಸ್ವಯಂಪ್ರೇರಿತ ಹಕ್ಕುಗಳು",
+ "required": "ಅಗತ್ಯವಿದೆ"
+ },
+ "ReceiveVcScreen": {
+ "header": "ಕಾರ್ಡ್ ವಿವರಗಳು",
+ "save": "ಕಾರ್ಡ್ ಉಳಿಸಿ",
+ "verifyAndSave": "ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಉಳಿಸಿ",
+ "acceptRequest": "ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ ಮತ್ತು ಕಾರ್ಡ್ ಸ್ವೀಕರಿಸಿ",
+ "acceptRequestAndVerify": "ವಿನಂತಿಯನ್ನು ಸ್ವೀಕರಿಸಿ ಮತ್ತು ಪರಿಶೀಲಿಸಿ",
+ "reject": "ತಿರಸ್ಕರಿಸಿ",
+ "discard": "ತಿರಸ್ಕರಿಸು",
+ "goToReceivedVCTab": "ಸ್ವೀಕರಿಸಿದ ಕಾರ್ಡ್ ವೀಕ್ಷಿಸಿ",
+ "saving": "ಕಾರ್ಡ್ ಅನ್ನು ಉಳಿಸಲಾಗುತ್ತಿದೆ",
+ "errors": {
+ "savingFailed": {
+ "title": "ಕಾರ್ಡ್ ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ",
+ "message": "ಸ್ಟೋರ್ನಲ್ಲಿ ಕಾರ್ಡ್ ಉಳಿಸುವಾಗ ಏನೋ ತಪ್ಪಾಗಿದೆ."
+ }
+ }
+ },
+ "RequestScreen": {
+ "receiveCard": "ಕಾರ್ಡ್ ಸ್ವೀಕರಿಸಿ",
+ "bluetoothDenied": "ವಿನಂತಿಸಲು ಬ್ಲೂಟೂತ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿಕಾರ್ಡ್",
+ "bluetoothStateIos": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ಅದನ್ನು ನಿಯಂತ್ರಣ ಕೇಂದ್ರದಿಂದ ಆನ್ ಮಾಡಿ",
+ "bluetoothStateAndroid": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳ ಮೆನುವಿನಿಂದ ಅದನ್ನು ಆನ್ ಮಾಡಿ",
+ "showQrCode": "ನಿವಾಸಿ ಕಾರ್ಡ್ ಅನ್ನು ವಿನಂತಿಸಲು ಈ QR ಕೋಡ್ ಅನ್ನು ಪ್ರದರ್ಶಿಸಿ",
+ "incomingVc": "ಒಳಬರುವ ಕಾರ್ಡ್",
+ "request": "ವಿನಂತಿ",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "ಕಾರ್ಡ್ಗಳು ಅನ್ನು ವಿನಂತಿಸಲು ಸಾಧ್ಯವಾಗಲು ಸಮೀಪದ ಸಾಧನಗಳ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ",
+ "button": "ಅನುಮತಿಯನ್ನು ಅನುಮತಿಸಿ"
+ },
+ "storageLimitReached": {
+ "title": "ಸಾಕಷ್ಟಿಲ್ಲ ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು",
+ "message": "ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾ ತುಂಬಿರುವುದರಿಂದ ನೀವು ಕಾರ್ಡ್ಗಳನ್ನು ಸೇರಿಸಲು ಅಥವಾ ಸ್ವೀಕರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮುಂದುವರೆಯಲು ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ."
+ }
+ },
+ "status": {
+ "accepted": {
+ "title": "ಯಶಸ್ಸು!",
+ "message": "ಕಾರ್ಡ್ಅನ್ನು ವಾಲೆಟ್ ಅವರಿಂದ ಯಶಸ್ವಿಯಾಗಿ ಸ್ವೀಕರಿಸಲಾಗಿದೆ"
+ },
+ "rejected": {
+ "title": "ಸೂಚನೆ",
+ "message": "ನೀವು ವಾಲೆಟ್ ಅವರ ಕಾರ್ಡ್ ಅನ್ನು ತಿರಸ್ಕರಿಸಿದ್ದೀರಿ"
+ },
+ "disconnected": {
+ "title": "ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ",
+ "message": "ಸಂಪರ್ಕದಲ್ಲಿ ಅಡಚಣೆ ಉಂಟಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."
+ },
+ "waitingConnection": "ಸಂಪರ್ಕಕ್ಕಾಗಿ ಕಾಯಲಾಗುತ್ತಿದೆ...",
+ "exchangingDeviceInfo": {
+ "message": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ...",
+ "timeoutHint": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲು ಇದು ತುಂಬಾ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತಿದೆ..."
+ },
+ "connected": {
+ "message": "ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ. ಕಾರ್ಡ್ ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ...",
+ "timeoutHint": "ಇನ್ನೂ ಯಾವುದೇ ಡೇಟಾವನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿಲ್ಲ. ಸಾಧನವನ್ನು ಕಳುಹಿಸುವುದು ಇನ್ನೂ ಸಂಪರ್ಕಗೊಂಡಿದೆಯೇ?"
+ },
+ "offline": {
+ "message": "ಆನ್ಲೈನ್ ಹಂಚಿಕೆ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ದಯವಿಟ್ಟು ಇಂಟರ್ನೆಟ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ"
+ },
+ "bleError": {
+ "title": "ವರ್ಗಾಯಿಸಲು ವಿಫಲವಾಗಿದೆ",
+ "message": "ಕಾರ್ಡ್ ಅನ್ನು ವರ್ಗಾಯಿಸುವಾಗ ಏನೋ ತಪ್ಪಾಗಿದೆ. ದಯವಿಟ್ಟು ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.",
+ "hint": "ದೋಷ: {{code}}"
+ }
+ },
+ "online": "ಆನ್ಲೈನ್",
+ "offline": "ಆಫ್ಲೈನ್",
+ "gotoSettings": "ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ"
+ },
+ "ScanScreen": {
+ "header": "QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ",
+ "noShareableVcs": "ಯಾವುದೇ ಹಂಚಿಕೊಳ್ಳಬಹುದಾದ ಕಾರ್ಡ್ ಲಭ್ಯವಿಲ್ಲ.",
+ "sharingVc": "ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ",
+ "bluetoothStateIos": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ಅದನ್ನು ನಿಯಂತ್ರಣ ಕೇಂದ್ರದಿಂದ ಆನ್ ಮಾಡಿ",
+ "bluetoothStateAndroid": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳ ಮೆನುವಿನಿಂದ ಅದನ್ನು ಆನ್ ಮಾಡಿ",
+ "enableBluetoothMessage": "ದಯವಿಟ್ಟು ಸ್ಥಳೀಯ ಹಂಚಿಕೆಯನ್ನು ಬೆಂಬಲಿಸಲು ಬ್ಲೂಟೂತ್ ಅನುಮತಿಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ",
+ "enableBluetoothButtonText": "ಬ್ಲೂಟೂತ್ ಅನುಮತಿಗಳನ್ನು ಅನುಮತಿಸಿ",
+ "scanningGuide": "ಫೋನ್ ಅನ್ನು ಸ್ಥಿರವಾಗಿ ಹಿಡಿದುಕೊಳ್ಳಿ ಮತ್ತು QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ",
+ "errors": {
+ "locationDisabled": {
+ "message": "ಸ್ಕ್ಯಾನಿಂಗ್ ಕಾರ್ಯಕ್ಕಾಗಿ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು",
+ "button": "ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"
+ },
+ "locationDenied": {
+ "message": "ಸ್ಕ್ಯಾನಿಂಗ್ ಕಾರ್ಯಕ್ಕಾಗಿ ಸ್ಥಳ ಅನುಮತಿ ಅಗತ್ಯವಿದೆ",
+ "button": "ಸ್ಥಳಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"
+ },
+ "nearbyDevicesPermissionDenied": {
+ "message": "ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳಲು ಸಾಧ್ಯವಾಗಲು ಸಮೀಪದ ಸಾಧನಗಳ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ",
+ "button": "ಅನುಮತಿಯನ್ನು ಅನುಮತಿಸಿ"
+ },
+ "storageLimitReached": {
+ "title": "ಸಾಕಷ್ಟಿಲ್ಲ ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು",
+ "message": "ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾ ತುಂಬಿರುವ ಕಾರಣ ನೀವು ಕಾರ್ಡ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮುಂದುವರೆಯಲು ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ."
+ }
+ },
+ "status": {
+ "inProgress": "ಪ್ರಗತಿಯಲ್ಲಿದೆ",
+ "establishingConnection": "ಸಂಪರ್ಕವನ್ನು ಸ್ಥಾಪಿಸುವುದು",
+ "sharingInProgress": "ಹಂಚಿಕೆ ಪ್ರಗತಿಯಲ್ಲಿದೆ",
+ "connectingTimeout": "ಸಂಪರ್ಕವನ್ನು ಸ್ಥಾಪಿಸಲು ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ. ಇತರ ಸಾಧನವು ಸಂಪರ್ಕಗಳಿಗಾಗಿ ತೆರೆದಿದೆಯೇ?",
+ "exchangingDeviceInfo": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ...",
+ "exchangingDeviceInfoTimeout": "ಸಾಧನದ ಮಾಹಿತಿಯನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳಲು ಸ್ವಲ್ಪ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತಿದೆ. ನೀವು ಮರುಸಂಪರ್ಕಿಸಬೇಕಾಗಬಹುದು.",
+ "invalid": "ಅಮಾನ್ಯವಾದ QR ಕೋಡ್",
+ "offline": "ಆನ್ಲೈನ್ ಹಂಚಿಕೆ ಮೋಡ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು QR ಕೋಡ್ಗಳನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ದಯವಿಟ್ಟು ಇಂಟರ್ನೆಟ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ",
+ "sent": "ಕಾರ್ಡ್ ಅನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ...",
+ "sentHint": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಉಳಿಸಲು ಅಥವಾ ತ್ಯಜಿಸಲು ರಿಸೀವರ್ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ",
+ "sharing": {
+ "title": "ಹಂಚಿಕೆ...",
+ "hint": "ನಾವು ಆಯ್ಕೆಮಾಡಿದ ಕಾರ್ಡ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುವವರೆಗೆ ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ.",
+ "timeoutHint": "ಹಂಚಿಕೊಳ್ಳಲು ನಿರೀಕ್ಷಿಸಿದ್ದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತಿದೆ. ಸಂಪರ್ಕದಲ್ಲಿ ಸಮಸ್ಯೆ ಇರಬಹುದು."
+ },
+ "accepted": {
+ "title": "ಐಡಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ",
+ "message": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು {{ರಿಸೀವರ್}} ಜೊತೆಗೆ ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ",
+ "gotohome": "ಮನೆಗೆ ಹೋಗು"
+ },
+ "rejected": {
+ "title": "ಗಮನಿಸಿ",
+ "message": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು {{ರಿಸೀವರ್}} ತಿರಸ್ಕರಿಸಿದ್ದಾರೆ"
+ },
+ "bleError": {
+ "title": "ವರ್ಗಾಯಿಸಲು ವಿಫಲವಾಗಿದೆ",
+ "message": "ಕಾರ್ಡ್ ಅನ್ನು ವರ್ಗಾಯಿಸುವಾಗ ಏನೋ ತಪ್ಪಾಗಿದೆ. ದಯವಿಟ್ಟು ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.",
+ "hint": "ದೋಷ: {{code}}"
+ }
+ }
+ },
+ "SelectVcOverlay": {
+ "header": "ಹಂಚಿಕೊಳ್ಳಿ ಕಾರ್ಡ್",
+ "chooseVc": "ನೀವು ಹಂಚಿಕೊಳ್ಳಲು ಬಯಸುವ ಕಾರ್ಡ್ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಿ",
+ "share": "ಹಂಚಿಕೊಳ್ಳಿ",
+ "verifyAndShare": "ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳಿ"
+ },
+ "SendVcScreen": {
+ "reasonForSharing": "ಹಂಚಿಕೆಗೆ ಕಾರಣ (ಐಚ್ಛಿಕ)",
+ "acceptRequest": "ಹಂಚಿಕೊಳ್ಳಿ",
+ "acceptRequestAndVerify": "ಸೆಲ್ಫಿಯೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಿ",
+ "reject": "ತಿರಸ್ಕರಿಸಿ",
+ "consentToPhotoVerification": "ದೃಢೀಕರಣಕ್ಕಾಗಿ ನನ್ನ ಫೋಟೋ ತೆಗೆಯಲು ನಾನು ಒಪ್ಪಿಗೆ ನೀಡುತ್ತೇನೆ",
+ "pleaseSelectAnId": "ದಯವಿಟ್ಟು ಐಡಿ ಆಯ್ಕೆಮಾಡಿ",
+ "status": {
+ "sharing": {
+ "title": "ಹಂಚಿಕೆ...",
+ "hint": "ಸ್ವೀಕರಿಸುವ ಸಾಧನವು ಹಂಚಿಕೆಯನ್ನು ಸ್ವೀಕರಿಸಲು ಅಥವಾ ತಿರಸ್ಕರಿಸಲು ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ.",
+ "timeoutHint": "ಹಂಚಿಕೊಳ್ಳಲು ನಿರೀಕ್ಷಿಸಿದ್ದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತಿದೆ. ಸಂಪರ್ಕದಲ್ಲಿ ಸಮಸ್ಯೆ ಇರಬಹುದು."
+ },
+ "accepted": {
+ "title": "ಯಶಸ್ಸು!",
+ "message": "ನಿಮ್ಮ ಕಾರ್ಡ್ನ್ನು ಪರಿಶೀಲಕ ಅವರೊಂದಿಗೆ ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ"
+ },
+ "rejected": {
+ "title": "ಗಮನಿಸಿ",
+ "message": "ನಿಮ್ಮ ಕಾರ್ಡ್ನ್ನು ಪರಿಶೀಲಕ ತಿರಸ್ಕರಿಸಿದ್ದಾರೆ "
+ }
+ }
+ },
+ "VerifyIdentityOverlay": {
+ "faceAuth": "ಮುಖದ ದೃಢೀಕರಣ",
+ "status": {
+ "verifyingIdentity": "ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ..."
+ },
+ "errors": {
+ "invalidIdentity": {
+ "title": "ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ",
+ "message": "ಮುಖ ಗುರುತಿಸಲಾಗಿಲ್ಲ. ದಯವಿಟ್ಟು ಪುನಃ ಪ್ರಯತ್ನಿಸಿ.",
+ "messageNoRetry": "ಮುಖ ಗುರುತಿಸಲಾಗಿಲ್ಲ."
+ }
+ }
+ },
+ "WelcomeScreen": {
+ "title": "ಓಪನ್ ಸೋರ್ಸ್ ಐಡೆಂಟಿಟಿ ಸೊಲ್ಯೂಷನ್",
+ "getStarted": "ಪ್ರಾರಂಭಿಸಿ",
+ "unlockApp": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಿ",
+ "failedToReadKeys": "ಕೀಗಳನ್ನು ಓದಲು ವಿಫಲವಾಗಿದೆ",
+ "retryRead": "ಮರುಪ್ರಯತ್ನಿಸಲು ಬಯಸುವಿರಾ?",
+ "errors": {
+ "decryptionFailed": "ಡೇಟಾವನ್ನು ಡೀಕ್ರಿಪ್ಟ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ",
+ "invalidateKeyError": {
+ "title": "ಭದ್ರತೆಯ ಕಾರಣದಿಂದ ಕೆಲವು ಗುರುತಿನ ಪುರಾವೆ(ಗಳನ್ನು) ಅಳಿಸಲಾಗಿದೆ.",
+ "message": "ದಯವಿಟ್ಟು ಮರುಡೌನ್ಲೋಡ್ ಮಾಡಿ."
+ }
+ },
+ "ignore": "ನಿರ್ಲಕ್ಷಿಸಿ"
+ },
+ "SetupLanguage": {
+ "header": "ಭಾಷೆಯನ್ನು ಆರಿಸಿ",
+ "description": "ನಿಮ್ಮ ಆದ್ಯತೆಯ ಭಾಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ",
+ "save": "ಆದ್ಯತೆಯನ್ನು ಉಳಿಸಿ"
+ },
+ "common": {
+ "cancel": "ರದ್ದು",
+ "accept": "ಒಪ್ಪಿಕೊಳ್ಳಿ",
+ "save": "ಉಳಿಸು",
+ "dismiss": "ವಜಾಗೊಳಿಸಿ",
+ "editLabel": "ಸಂಪಾದಿಸು {{label}}",
+ "tryAgain": "ಮತ್ತೆ ಪ್ರಯತ್ನಿಸು",
+ "ignore": "ನಿರ್ಲಕ್ಷಿಸಿ",
+ "camera": {
+ "errors": {
+ "missingPermission": "ಮತ್ತೊಂದು ಸಾಧನದ QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತದೆ."
+ },
+ "allowAccess": "ಕ್ಯಾಮರಾಗೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"
+ },
+ "errors": {
+ "genericError": "ಏನೋ ತಪ್ಪಾಗಿದೆ. ದಯವಿಟ್ಟು ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ!"
+ },
+ "clipboard": {
+ "copy": "ನಕಲು ಮಾಡಿ",
+ "copied": "ನಕಲು ಮಾಡಲಾಗಿದೆ"
+ },
+ "biometricPopup": {
+ "title": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಿ",
+ "description": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಬಳಸಿ"
+ }
+ }
+}
diff --git a/locales/spa.json b/locales/spa.json
new file mode 100644
index 00000000..285a37bb
--- /dev/null
+++ b/locales/spa.json
@@ -0,0 +1,468 @@
+{
+ "ActivityLogText": {
+ "VC_SHARED": "compartido",
+ "VC_RECEIVED": "recibido",
+ "VC_RECEIVED_NOT_SAVED": "recibido no guardado",
+ "VC_DELETED": "eliminado",
+ "VC_DOWNLOADED": "descargado",
+ "VC_REVOKED": "revocado",
+ "VC_SHARED_WITH_VERIFICATION_CONSENT": "compartido. Se ha dado consentimiento para verificación de presencia",
+ "VC_RECEIVED_WITH_PRESENCE_VERIFIED": "recibido. Presencia verificada",
+ "VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "recibido. Falló la verificación de presencia",
+ "PRESENCE_VERIFIED_AND_VC_SHARED": "verificado y compartido",
+ "PRESENCE_VERIFICATION_FAILED": "falló la verificación",
+ "QRLOGIN_SUCCESFULL": "Inicio de sesión QR exitoso",
+ "WALLET_BINDING_SUCCESSFULL": "Activación exitosa",
+ "WALLET_BINDING_FAILURE": "Activación fallida",
+ "VC_REMOVED": "Eliminado de la billetera"
+ },
+ "DeviceInfoList": {
+ "requestedBy": "Solicitado por",
+ "sentBy": "Enviado por",
+ "deviceRefNumber": "Número de referencia del dispositivo",
+ "name": "Nombre",
+ "Verifier": "Verificador",
+ "Wallet": "Billetera"
+ },
+ "FaceScanner": {},
+ "OIDcAuth": {
+ "title": "Autenticación OIDC",
+ "text": "Se reemplazará con la interfaz de usuario del proveedor OIDC",
+ "verify": "Verificar"
+ },
+ "PasscodeVerify": {
+ "passcodeMismatchError": "El código de acceso no coincide."
+ },
+ "QrScanner": {
+ "cameraAccessDisabled": "¡Acceso a la cámara deshabilitado!",
+ "cameraPermissionGuideLabel": "Vaya a la configuración y habilite el acceso a la cámara manualmente.",
+ "flipCamera": "Voltear cámara"
+ },
+ "VcDetails": {
+ "generatedOn": "Generado el",
+ "status": "Estado",
+ "valid": "Válido",
+ "photo": "Foto",
+ "fullName": "Nombre completo",
+ "gender": "Género",
+ "dateOfBirth": "Fecha de nacimiento",
+ "phoneNumber": "Número de teléfono",
+ "email": "Correo electrónico",
+ "address": "Dirección",
+ "reasonForSharing": "Motivo de compartir",
+ "idType": "Tipo de identificación",
+ "id": "Identificación",
+ "nationalCard": "Tarjeta nacional",
+ "uin": "UIN",
+ "enableVerification": "Activar",
+ "profileAuthenticated": "Activado para inicio de sesión en línea",
+ "offlineAuthDisabledHeader": "Activación pendiente para inicio de sesión en línea",
+ "offlineAuthDisabledMessage": "Por favor, haz clic en el botón de abajo para activar esta credencial para su uso en inicio de sesión en línea.",
+ "vid": "VID",
+ "verificationEnabledSuccess": "Activado para inicio de sesión en línea",
+ "goback": "VOLVER",
+ "BindingWarning": "Si has activado la verificación para esta credencial en otra billetera, se sobrescribirá. ¿Deseas continuar?",
+ "yes_confirm": "Sí, confirmo",
+ "no": "No",
+ "Alert": "Alerta",
+ "ok": "Aceptar",
+ "credentialRegistry": "Registro de credenciales",
+ "errors": {
+ "savingFailed": {
+ "title": "Error al guardar la tarjeta",
+ "message": "Se produjo un error al guardar la tarjeta en el almacenamiento."
+ },
+ "diskFullError": {
+ "title": "Error al guardar la tarjeta",
+ "message": "No se pueden recibir ni guardar más tarjetas, ya que los datos de la aplicación están llenos."
+ }
+ }
+ },
+ "RemoveVcWarningOverlay": {
+ "alert": "Por favor confirmar",
+ "RemoveWarning": "¿Quieres eliminar esta tarjeta?",
+ "confirm": "si, lo confirmo",
+ "no": "No"
+ },
+ "AuthScreen": {
+ "header": "¿Te gustaría usar la biometría para desbloquear la aplicación?",
+ "useBiometrics": "Usar biometría",
+ "usePasscode": "Prefiero usar un código de acceso",
+ "errors": {
+ "unavailable": "El dispositivo no admite la biometría",
+ "unenrolled": "Para usar la biometría, por favor registra tus datos biométricos en la configuración de tu dispositivo",
+ "failed": "No se pudo autenticar con la biometría",
+ "generic": "Parece haber un error en la autenticación biométrica"
+ }
+ },
+ "BiometricScreen": {
+ "unlock": "Desbloquear con biometría"
+ },
+ "HistoryTab": {
+ "noHistory": "Aún no hay historial disponible",
+ "downloaded": "descargado",
+ "shared": "compartido",
+ "received": "recibido",
+ "deleted": "eliminado"
+ },
+ "HomeScreen": {
+ "myVcsTab": "Mis\nTarjetas",
+ "receivedVcsTab": "Tarjetas\nRecibidas",
+ "historyTab": "Historial"
+ },
+ "AddVcModal": {
+ "requestingCredential": "Solicitando credencial...",
+ "errors": {
+ "input": {
+ "empty": "El campo no puede estar vacío",
+ "invalidFormat": "El formato del campo es incorrecto"
+ },
+ "backend": {
+ "invalidOtp": "El OTP es inválido",
+ "expiredOtp": "El OTP ha expirado",
+ "invalidUin": "UIN inválido",
+ "invalidVid": "VID inválido",
+ "missingUin": "UIN no disponible en la base de datos",
+ "missingVid": "VID no disponible en la base de datos",
+ "noMessageAvailable": "Inténtalo de nuevo más tarde",
+ "whileGeneratingOtpErrorIsOccured": "Se produjo un error al generar el OTP",
+ "networkRequestFailed": "Error en la solicitud de red"
+ }
+ }
+ },
+ "GetVcModal": {
+ "errors": {
+ "input": {
+ "empty": "El campo no puede estar vacío",
+ "invalidFormat": "El formato del campo es incorrecto"
+ },
+ "backend": {
+ "invalidOtp": "El OTP es inválido",
+ "expiredOtp": "El OTP ha expirado",
+ "applicationProcessing": "El AID no está listo",
+ "noMessageAvailable": "Inténtalo de nuevo más tarde",
+ "networkRequestFailed": "Error en la solicitud de red",
+ "invalidAid": "El AID ingresado no está disponible. Por favor, verifica tu AID antes de ingresar",
+ "timeOut": "Tiempo de espera agotado"
+ }
+ }
+ },
+ "DownloadingVcModal": {
+ "header": "Descargando tu Tarjeta",
+ "bodyText": "Esto puede llevar algún tiempo. Te notificaremos cuando tu Tarjeta se haya descargado y esté disponible.",
+ "backButton": "Volver a inicio"
+ },
+ "GetIdInputModal": {
+ "header": "Ingresa tu ID de aplicación para obtener tu UIN",
+ "getUIN": "Obtener UIN/VID",
+ "applicationId": "ID de aplicación",
+ "requestingOTP": "Solicitando OTP...",
+ "qstnMarkToolTip": "El ID de aplicación está disponible en el acuse de recibo recibido después de la inscripción."
+ },
+ "IdInputModal": {
+ "header": "Ingresa tu UIN/VID para descargar tu Tarjeta",
+ "generateVc": "Generar mi Tarjeta",
+ "enterId": "Ingresa tu {{idType}}",
+ "noUIN/VID": "¿No tienes tu UIN/VID? Obténlo aquí",
+ "requestingOTP": "Solicitando OTP..."
+ },
+ "OtpVerificationModal": {
+ "enterOtp": "Ingresa el código de verificación de 6 dígitos que te hemos enviado",
+ "header": "Verificación de OTP"
+ },
+ "MyVcsTab": {
+ "addVcButton": "Agregar Tarjeta",
+ "generateVc": "Genera tus Tarjetas",
+ "generateVcDescription": "Toca en \"Agregar Tarjeta\" a continuación para descargar tu Tarjeta",
+ "errors": {
+ "savingFailed": {
+ "title": "Error al guardar la Tarjeta",
+ "message": "Hubo un error al guardar la Tarjeta en el almacenamiento."
+ },
+ "diskFullError": {
+ "title": "Error al guardar la Tarjeta",
+ "message": "No se pueden recibir ni guardar más Tarjetas, ya que los datos de la aplicación están llenos."
+ },
+ "vcIsTampered": {
+ "title": "Algunas pruebas de identidad están manipuladas",
+ "message": "Los archivos afectados se eliminan, vuelva a descargarlos."
+ },
+ "storageLimitReached": {
+ "title": "Datos de aplicación insuficientes",
+ "message": "No puede agregar ni recibir tarjetas porque los datos de la aplicación están llenos. Borre Appdata para continuar."
+ },
+ "keystoreNotExists": {
+ "title": "Almacenamiento seguro de claves no encontrado",
+ "message": "El almacenamiento de claves en su teléfono no está protegido. Sus claves podrían filtrarse si el teléfono es pirateado.",
+ "riskOkayText": "Está bien, me arriesgaré."
+ }
+ }
+ },
+ "OnboardingOverlay": {
+ "stepOneTitle": "¡Bienvenido!",
+ "stepOneText": "Mantén tu credencial digital contigo en todo momento. Para comenzar, agrega Tarjetas a tu perfil.",
+ "stepTwoTitle": "Gestión de Tarjetas",
+ "stepTwoText": "Una vez generadas, las Tarjetas se almacenan de forma segura en tu dispositivo móvil y se pueden cambiar el nombre o compartir en cualquier momento.",
+ "stepThreeTitle": "Compartir fácilmente",
+ "stepThreeText": "Comparte y recibe Tarjetas rápidamente utilizando la cámara de tu teléfono para escanear códigos QR.",
+ "stepThreeButton": "Comienza y agrega una Tarjeta",
+ "ReceivedVcsTab": {
+ "noReceivedVcsTitle": "Aún no hay Tarjetas disponibles",
+ "noReceivedVcsText": "Toca en Solicitar a continuación para recibir una Tarjeta"
+ }
+ },
+ "ViewVcModal": {
+ "cancel": "Cancelar",
+ "lock": "Bloquear",
+ "unlock": "Desbloquear",
+ "rename": "Renombrar",
+ "delete": "Eliminar",
+ "revoke": "Revocar",
+ "revoking": "Tu billetera contiene una credencial con VID {{vid}}. Revocar esto eliminará automáticamente la misma de la billetera. ¿Estás seguro de que deseas continuar?",
+ "requestingOtp": "Solicitando OTP...",
+ "editTag": "Renombrar",
+ "redirecting": "Redirigiendo...",
+ "inProgress": "Cargando...",
+ "success": {
+ "unlocked": "Tarjeta desbloqueada exitosamente",
+ "locked": "Tarjeta bloqueada exitosamente",
+ "revoked": "VID {{vid}} ha sido revocado. Cualquier credencial que contenga el mismo se eliminará automáticamente de la billetera."
+ }
+ },
+ "MainLayout": {
+ "home": "Inicio",
+ "scan": "Escanear",
+ "request": "Solicitar",
+ "settings": "Configuración"
+ },
+ "PasscodeScreen": {
+ "header": "Establece un código de acceso para proteger tu aplicación",
+ "confirmPasscode": "Confirma tu código de acceso",
+ "enterPasscode": "Ingresa tu código de acceso"
+ },
+ "AppMetaData": {
+ "header": "Acerca de Inji",
+ "version": "Versión",
+ "useBle": "Impulsado por BLE"
+ },
+ "SettingScreen": {
+ "header": "Ajustes",
+ "injiAsVerifierApp": "Inji como aplicación verificadora",
+ "basicSettings": "Ajustes básicos",
+ "bioUnlock": "Desbloquear con biométrico",
+ "language": "Idioma",
+ "aboutInji": "Acerca de Inji",
+ "credentialRegistry": "Registro de Credenciales",
+ "injiTourGuide": "Guía turístico Inji",
+ "logout": "Cerrar sesión",
+ "resetInjiProps": "Restableciendo accesorios Inji..."
+ },
+ "QrScreen": {
+ "title": "Inicio de sesión con código QR",
+ "alignQr": "Alinea el código QR dentro del marco para escanearlo",
+ "confirmation": "Confirmación",
+ "checkDomain": "Además, verifica que haya un icono de candado en la barra de direcciones.",
+ "domainHead": "https://",
+ "selectId": "Seleccionar ID",
+ "noBindedVc": "No hay Tarjetas Vinculadas disponibles para verificar",
+ "back": "Volver",
+ "confirm": "Confirmar",
+ "verify": "Verificar",
+ "faceAuth": "Autenticación Facial",
+ "consent": "Consentimiento",
+ "loading": "Cargando...",
+ "domainWarning": "Por favor, confirma que el dominio del sitio web desde el cual estás escaneando el código QR es el siguiente",
+ "access": "está solicitando acceso a",
+ "status": "Estado",
+ "successMessage": "Has iniciado sesión correctamente en",
+ "okay": "Aceptar",
+ "allow": "Permitir",
+ "cancel": "Cancelar",
+ "essentialClaims": "Reclamos Esenciales",
+ "voluntaryClaims": "Reclamos Voluntarios",
+ "required": "Requerido"
+ },
+ "ReceiveVcScreen": {
+ "header": "Detalles de la tarjeta",
+ "save": "Guardar tarjeta",
+ "verifyAndSave": "Verificar y guardar",
+ "reject": "Rechazar",
+ "discard": "Descartar",
+ "goToReceivedVCTab": "Ver tarjetas recibidas",
+ "saving": "Guardando",
+ "errors": {
+ "savingFailed": {
+ "title": "Error al guardar la tarjeta",
+ "message": "Ocurrió un error al guardar la tarjeta en el almacenamiento."
+ },
+ "diskFullError": {
+ "title": "Error al guardar la tarjeta",
+ "message": "No se pueden recibir ni guardar más tarjetas porque los datos de la aplicación están llenos."
+ }
+ }
+ },
+ "RequestScreen": {
+ "receiveCard": "Recibir tarjeta",
+ "bluetoothDenied": "Por favor, activa el Bluetooth para poder solicitar la tarjeta",
+ "bluetoothStateAndroid": "Por favor, activa el Bluetooth desde la configuración rápida para admitir el intercambio local",
+ "bluetoothStateIos": "Por favor, activa el Bluetooth desde el centro de control para admitir el intercambio local",
+ "showQrCode": "Muestra este código QR para solicitar la tarjeta de residente",
+ "incomingVc": "Tarjeta entrante",
+ "request": "Solicitar",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "Se requiere el permiso de Dispositivos cercanos para poder solicitar la tarjeta",
+ "button": "Permitir permiso"
+ },
+ "storageLimitReached": {
+ "title": "Datos de aplicación insuficientes",
+ "message": "No puede agregar ni recibir tarjetas porque los datos de la aplicación están llenos. Borre Appdata para continuar."
+ }
+ },
+ "status": {
+ "accepted": {
+ "title": "¡Éxito!",
+ "message": "La tarjeta se ha recibido correctamente desde la billetera"
+ },
+ "rejected": {
+ "title": "Aviso",
+ "message": "Has descartado la tarjeta de la billetera"
+ },
+ "disconnected": {
+ "title": "Desconectado",
+ "message": "La conexión se interrumpió. Por favor, inténtalo de nuevo."
+ },
+ "waitingConnection": "Esperando conexión...",
+ "exchangingDeviceInfo": {
+ "message": "Intercambiando información del dispositivo...",
+ "timeoutHint": "Está tomando demasiado tiempo intercambiar la información del dispositivo..."
+ },
+ "connected": {
+ "message": "Conectado al dispositivo. Esperando la tarjeta...",
+ "timeoutHint": "Todavía no se ha recibido ningún dato. ¿El dispositivo emisor aún está conectado?"
+ },
+ "offline": {
+ "message": "Por favor, conéctate a internet para habilitar el modo de intercambio en línea"
+ },
+ "bleError": {
+ "title": "Error al transferir",
+ "message": "Ocurrió un error al transferir la tarjeta. Por favor, inténtalo de nuevo.",
+ "hint": "Error: {{code}}"
+ }
+ },
+ "online": "En línea",
+ "offline": "Desconectado",
+ "gotoSettings": "Ir a configuración"
+ },
+ "ScanScreen": {
+ "header": "Escanear código QR",
+ "noShareableVcs": "No hay tarjetas compartibles disponibles.",
+ "sharingVc": "Compartiendo tarjeta",
+ "bluetoothStateAndroid": "Por favor, activa el Bluetooth desde la configuración rápida para admitir el intercambio local",
+ "bluetoothStateIos": "Por favor, activa el Bluetooth desde el centro de control para admitir el intercambio local",
+ "enableBluetoothMessage": "Por favor, habilita los permisos de Bluetooth para admitir el intercambio local",
+ "enableBluetoothButtonText": "Permitir permisos de Bluetooth",
+ "errors": {
+ "locationDisabled": {
+ "message": "Los servicios de ubicación deben estar habilitados para compartir la tarjeta",
+ "button": "Habilitar servicios de ubicación"
+ },
+ "locationDenied": {
+ "message": "Se requiere permiso de ubicación para compartir la tarjeta",
+ "button": "Permitir acceso a la ubicación"
+ },
+ "nearbyDevicesPermissionDenied": {
+ "message": "Se requiere el permiso de Dispositivos cercanos para poder compartir la tarjeta",
+ "button": "Permitir permiso"
+ },
+ "storageLimitReached": {
+ "title": "Datos de aplicación insuficientes",
+ "message": "No puede compartir tarjetas porque los datos de la aplicación están llenos. Borre Appdata para continuar."
+ }
+ },
+ "status": {
+ "connecting": "Conectando...",
+ "connectingTimeout": "Está tomando tiempo establecer la conexión. ¿El otro dispositivo está abierto para conexiones?",
+ "exchangingDeviceInfo": "Intercambiando información del dispositivo...",
+ "exchangingDeviceInfoTimeout": "Está tomando tiempo intercambiar la información del dispositivo. Es posible que tengas que reconectar.",
+ "invalid": "Código QR inválido",
+ "offline": "Por favor, conéctate a internet para escanear códigos QR usando el modo de intercambio en línea",
+ "sent": "La tarjeta ha sido enviada...",
+ "sentHint": "Esperando a que el receptor guarde o descarte tu tarjeta",
+ "sharing": {
+ "title": "Compartiendo...",
+ "hint": "Espere mientras compartimos la tarjeta elegida.",
+ "timeoutHint": "Está tomando más tiempo del esperado para compartir. Puede haber un problema con la conexión."
+ },
+ "accepted": {
+ "title": "¡Éxito!",
+ "message": "Tu tarjeta ha sido compartida exitosamente con el Verificador"
+ },
+ "rejected": {
+ "title": "Aviso",
+ "message": "Tu tarjeta ha sido descartada por el Verificador"
+ },
+ "bleError": {
+ "title": "Error al transferir",
+ "message": "Ocurrió un error al transferir la tarjeta. Por favor, inténtalo de nuevo.",
+ "hint": "Error: {{code}}"
+ }
+ }
+ },
+ "SelectVcOverlay": {
+ "header": "Compartir tarjeta",
+ "chooseVc": "Selecciona la tarjeta que deseas compartir",
+ "share": "Compartir",
+ "verifyAndShare": "Verificar identidad y compartir"
+ },
+ "SendVcScreen": {
+ "reasonForSharing": "Motivo de compartir (opcional)",
+ "acceptRequest": "Compartir",
+ "acceptRequestAndVerify": "Compartir con selfie",
+ "reject": "Rechazar",
+ "consentToPhotoVerification": "Doy mi consentimiento para que se tome mi foto para la autenticación"
+ },
+ "VerifyIdentityOverlay": {
+ "status": {
+ "verifyingIdentity": "Verificando identidad..."
+ },
+ "errors": {
+ "invalidIdentity": {
+ "title": "No se puede verificar la identidad",
+ "message": "No se reconoce el rostro. Por favor, inténtalo de nuevo.",
+ "messageNoRetry": "No se reconoce el rostro."
+ }
+ }
+ },
+ "WelcomeScreen": {
+ "title": "Solución de identidad de código abierto",
+ "getStarted": "Empezar",
+ "unlockApp": "Desbloquear aplicación",
+ "errors": {
+ "invalidateKeyError": {
+ "title": "Algunas pruebas de identidad se eliminan debido a problemas de seguridad.",
+ "message": "Vuelva a descargar."
+ }
+ }
+ },
+ "common": {
+ "cancel": "Cancelar",
+ "save": "Guardar",
+ "dismiss": "Cerrar",
+ "editLabel": "Editar {{label}}",
+ "tryAgain": "Intentar de nuevo",
+ "camera": {
+ "errors": {
+ "missingPermission": "Esta aplicación utiliza la cámara para escanear el código QR de otro dispositivo."
+ },
+ "allowAccess": "Permitir acceso a la cámara"
+ },
+ "errors": {
+ "genericError": "Algo salió mal. ¡Por favor, inténtalo de nuevo después de un tiempo!"
+ },
+ "biometricPopup": {
+ "title": "Desbloquear aplicación",
+ "description": "Utilice la huella digital para desbloquear la aplicación."
+ }
+ }
+}
\ No newline at end of file
diff --git a/locales/tam.json b/locales/tam.json
index 278c4349..1703e170 100644
--- a/locales/tam.json
+++ b/locales/tam.json
@@ -1,336 +1,566 @@
-{
- "DeviceInfoList": {
- "requestedBy": "கோரியவர்",
- "sentBy": "அனுப்பியவர்",
- "deviceRefNumber": "சாதன குறிப்பு எண்",
- "name": "பெயர்"
- },
- "PasscodeVerify": {
- "passcodeMismatchError": "கடவுக்குறியீடு பொருந்தவில்லை."
- },
- "FaceScanner": {},
- "OIDcAuth": {
- "title": "OIDC அங்கீகாரம்",
- "text": "OIDC வழங்குநர் UI உடன் மாற்றப்பட வேண்டும்",
- "verify": "சரிபார்க்கவும்"
- },
- "QrScanner": {
- "missingPermissionText": "இந்தப் பயன்பாடு மற்றொரு சாதனத்தின் QR குறியீட்டை ஸ்கேன் செய்ய கேமராவைப் பயன்படுத்துகிறது.",
- "allowCameraButton": "கேமராவை அணுக அனுமதி"
- },
- "VcDetails": {
- "generatedOn": "உருவாக்கப்பட்டது",
- "status": "நிலை",
- "valid": "செல்லுபடியாகும்",
- "photo": "புகைப்படம்",
- "fullName": "முழு பெயர்",
- "gender": "பாலினம்",
- "dateOfBirth": "பிறந்த தேதி",
- "phoneNumber": "தொலைபேசி எண்",
- "email": "மின்னஞ்சல்",
- "address": "முகவரி",
- "reasonForSharing": "பகிர்வதற்கான காரணம்",
- "idType": "ஐடி வகை",
- "id": "Id",
- "nationalCard": "தேசிய அட்டை್",
- "uin": "UIN",
- "enableVerification": "செயல்படுத்த",
- "profileAuthenticated": "ஆன்லைன் உள்நுழைவுக்காக செயல்படுத்தப்பட்டது",
- "offlineAuthDisabledHeader": "ஆன்லைன் உள்நுழைவுக்கான செயல்படுத்தல் நிலுவையில் உள்ளது",
- "offlineAuthDisabledMessage": "இந்த நற்சான்றிதழை ஆன்லைன் உள்நுழைவுக்குப் பயன்படுத்த, கீழே உள்ள பொத்தானைக் கிளிக் செய்யவும்.",
- "vid": "VID",
- "verificationEnabledSuccess": "ஆன்லைன் உள்நுழைவுக்காக செயல்படுத்தப்பட்டது",
- "goback": "திரும்பி செல்",
- "BindingWarning": "இந்த நற்சான்றிதழுக்கான ஆன்லைன் உள்நுழைவை வேறொரு சாதனத்தில் ஏற்கனவே செயல்படுத்தியுள்ளீர்கள். இந்தச் சாதனத்தில் மீண்டும் அதைச் செயல்படுத்தினால், உள்நுழைவதற்கு அந்தச் சாதனத்தை இனி உங்களால் பயன்படுத்த முடியாது.",
- "yes_confirm": "ஆம், நான் உறுதி செய்கிறேன்",
- "no": "இல்லை",
- "Alert": "எச்சரிக்கை",
- "ok": "சரி"
- },
- "AuthScreen": {
- "header": "பயன்பாட்டைத் திறக்க பயோமெட்ரிக்ஸைப் பயன்படுத்த விரும்புகிறீர்களா?",
- "useBiometrics": "பயோமெட்ரிக்ஸைப் பயன்படுத்து",
- "usePasscode": "நான் கடவுக்குறியீட்டைப் பயன்படுத்த விரும்புகிறேன்",
- "errors": {
- "unavailable": "சாதனம் பயோமெட்ரிக்ஸை ஆதரிக்காது",
- "unenrolled": "பயோமெட்ரிக்ஸைப் பயன்படுத்த, உங்கள் சாதன அமைப்புகளில் உங்கள் கைரேகையைப் பதிவு செய்யவும்",
- "failed": "பயோமெட்ரிக்ஸ் மூலம் அங்கீகரிக்க முடியவில்லை",
- "generic": "பயோமெட்ரிக்ஸ் அங்கீகாரத்தில் பிழை இருப்பதாகத் தெரிகிறது"
- }
- },
- "BiometricScreen": {
- "unlock": "கைரேகை மூலம் திற"
- },
- "HistoryTab": {
- "noHistory": "இன்னும் வரலாறு கிடைக்கவில்லை",
- "downloaded": "பதிவிறக்கம்",
- "shared": "பகிரப்பட்டது",
- "received": "பெறப்பட்டது",
- "deleted": "நீக்கப்பட்டது"
- },
- "HomeScreen": {
- "myVcsTab": "எனது\n{{vcLabel}}",
- "receivedVcsTab": "பெறப்பட்டது\n{{vcLabel}}",
- "historyTab": "வரலாறு"
- },
- "AddVcModal": {
- "requestingCredential": "நற்சான்றிதழைக் கோருகிறது...",
- "errors": {
- "input": {
- "empty": "உள்ளீடு காலியாக இருக்க முடியாது",
- "invalidFormat": "உள்ளீட்டு வடிவம் தவறானது"
- },
- "backend": {
- "invalidOtp": "OTP தவறானது",
- "invalidUin": "UIN தவறானது",
- "invalidVid": "VID தவறானது",
- "missingUin": "UIN தரவுத்தளத்தில் இல்லை",
- "missingVid": "VID தரவுத்தளத்தில் இல்லை"
- }
- }
- },
- "DownloadingVcModal": {
- "header": "உங்கள் {{vcLabel}}ஐப் பதிவிறக்குகிறது",
- "bodyText": "இதற்கு சிறிது நேரம் ஆகலாம், உங்கள் {{vcLabel}} பதிவிறக்கம் செய்யப்பட்டு கிடைக்கும்போது உங்களுக்கு அறிவிப்போம்",
- "backButton": "பேக் ஹோம்"
- },
- "GetIdInputModal": {
- "header": "உங்கள் UIN அல்லது VID ஐ மீட்டெடுக்க, உங்கள் விண்ணப்ப {{vcLabel}} எண்ணை உள்ளிடவும்",
- "getUIN": "UIN/VIDஐப் பெறுங்கள்",
- "applicationId": "விண்ணப்பம் {{vcLabel}} எண்",
- "requestingOTP": "OTP ஐக் கோருகிறது...",
- "qstnMarkToolTip": "விண்ணப்பம் {{vcLabel}} எண் பதிவுசெய்த பிறகு வழங்கப்படும் ஒப்புகையில் அச்சிடப்பட்டுள்ளது"
- },
- "IdInputModal": {
- "header": "நீங்கள் மீட்டெடுக்க விரும்பும் {{vcLabel}} இன் MOSIP வழங்கிய UIN அல்லது VID ஐ உள்ளிடவும்",
- "generateVc": "உருவாக்கு {{vcLabel}}",
- "enterId": "உங்கள் {{idType}}ஐ உள்ளிடவும்",
- "noUIN/VID": "உங்கள் UIN/VID இல்லையா? இங்கே பெறுங்கள்",
- "requestingOTP": "OTP ஐக் கோருகிறது..."
- },
- "OtpVerificationModal": {
- "enterOtp": "நாங்கள் உங்களுக்கு அனுப்பிய 6 இலக்க சரிபார்ப்புக் குறியீட்டை உள்ளிடவும்",
- "header": "OTP சரிபார்ப்பு"
- },
- "MyVcsTab": {
- "addVcButton": "{{vcLabel}} சேர்",
- "generateVc": "உங்கள் {{vcLabel}}ஐ உருவாக்கவும்",
- "generateVcDescription": "உங்கள் \"சேர் {{vcLabel}}\" என்பதைத் தட்டவும் {{vcLabel}}"
- },
- "OnboardingOverlay": {
- "stepOneTitle": "வரவேற்கிறேன்!",
- "stepOneText": "உங்கள் டிஜிட்டல் நற்சான்றிதழை எப்போதும் உங்களுடன் வைத்திருக்கவும். தொடங்குவதற்கு, உங்கள் சுயவிவரத்தில் {{vcLabel}}ஐச் சேர்க்கவும்.",
- "stepTwoTitle": "{{vcLabel}} மேலாண்மை",
- "stepTwoText": "உருவாக்கப்பட்டவுடன், {{vcLabel}} உங்கள் மொபைலில் பாதுகாப்பாகச் சேமிக்கப்பட்டு, எந்த நேரத்திலும் மறுபெயரிடலாம் அல்லது பகிரலாம்.",
- "stepThreeTitle": "எளிதான பகிர்வு",
- "stepThreeText": "QR குறியீடுகளை ஸ்கேன் செய்ய உங்கள் ஃபோன் கேமராவைப் பயன்படுத்தி {{vcLabel}} switflyயைப் பகிரவும் மற்றும் பெறவும்.",
- "stepThreeButton": "தொடங்கவும் {{vcLabel}}ஐச் சேர்க்கவும்"
- },
- "ReceivedVcsTab": {
- "noReceivedVcsTitle": "இன்னும் {{vcLabel}} கிடைக்கவில்லை",
- "noReceivedVcsText": "{{vcLabel}} பெறுவதற்கு கீழே உள்ள கோரிக்கையைத் தட்டவும்"
- },
- "ViewVcModal": {
- "cancel": "ரத்து செய்",
- "lock": "பூட்டு",
- "unlock": "திறத்தல்",
- "rename": "மறுபெயரிடு",
- "delete": "நீக்கு",
- "revoke": "திரும்பப்பெறு",
- "revoking": "உங்கள் பணப்பையில் VID {{vid}} உடன் நற்சான்றிதழ் உள்ளது. இதைத் திரும்பப் பெறுவது வாலட்டில் இருந்து தானாகவே அகற்றப்படும்.நீங்கள் நிச்சயமாக தொடர விரும்புகிறீர்களா?",
- "requestingOtp": "ஓடிபியைக் கோருகிறது...",
- "editTag": "திருத்து குறி",
- "redirecting": "வழிமாற்று...",
- "inProgress": "ஏற்றுகிறது...",
- "success": {
- "unlocked": "{{vcLabel}} வெற்றிகரமாக திறக்கப்பட்டது",
- "locked": "{{vcLabel}} வெற்றிகரமாக பூட்டப்பட்டது",
- "revoked": "VID {{vid}} has been revoked. அதைக் கொண்ட எந்த நற்சான்றிதழும் பணப்பையிலிருந்து தானாகவே அகற்றப்படும்"
- }
- },
- "MainLayout": {
- "home": "வீடு",
- "scan": "ஸ்கேன்",
- "request": "கோரிக்கை",
- "profile": "சுயவிவரம்"
- },
- "PasscodeScreen": {
- "header": "உங்கள் விண்ணப்பத்தைப் பாதுகாக்க கடவுக்குறியீட்டை அமைக்கவும்",
- "confirmPasscode": "உங்கள் கடவுக்குறியீட்டை உறுதிப்படுத்தவும்",
- "enterPasscode": "உங்கள் கடவுக்குறியீட்டை உள்ளிடவும்"
- },
- "Credits": {
- "header": "வரவுகள் மற்றும் சட்ட அறிவிப்புகள்",
- "back": "பின்"
- },
- "ProfileScreen": {
- "name": "பெயர்",
- "vcLabel": "VC லேபிள்",
- "language": "மொழி",
- "bioUnlock": "பயோமெட்ரிக் அன்லாக்",
- "authFactorUnlock": "அங்கீகார காரணியைத் திற",
- "credits": "வரவுகள் மற்றும் சட்ட அறிவிப்புகள்",
- "logout": "வெளியேறு",
- "revokeLabel": "திரும்பப் பெறு VID",
- "revokeHeader": "திரும்பப் பெறு VID",
- "revokingVids": "நீங்கள் ({{count}}) ஐ ரத்து செய்ய உள்ளீர்கள் VIDs.",
- "revokingVidsAfter": "அதாவது, அந்த VID(s) உடன் இணைக்கப்பட்ட எந்த ஐடியையும் நீங்கள் இனி பயன்படுத்தவோ பார்க்கவோ முடியாது. \nநீங்கள் நிச்சயமாக தொடர விரும்புகிறீர்களா?",
- "empty": "காலியாக",
- "revokeSuccessful": "VID வெற்றிகரமாக ரத்து செய்யப்பட்டது",
- "version": "பதிப்பு"
- },
- "QrScreen": {
- "title": "QR உள்நுழைவு",
- "alignQr": "ஸ்கேன் செய்ய ஃப்ரேமுக்குள் QR குறியீட்டை சீரமைக்கவும்",
- "confirmation": "உறுதிப்படுத்தல்",
- "checkDomain": "மேலும், முகவரிப் பட்டியில் பூட்டு ஐகான் உள்ளதா எனச் சரிபார்க்கவும்.",
- "domainHead": "https://",
- "selectId": "ஐடியைத் தேர்ந்தெடுக்கவும்",
- "noBindedVc": "சரிபார்க்க, பிணைக்கப்பட்ட {{vcLabel}} எதுவும் இல்லை",
- "back": "திரும்பி செல்",
- "confirm": "உறுதிப்படுத்தவும்",
- "verify": "சரிபார்க்கவும்",
- "faceAuth": "முக அங்கீகாரம்",
- "consent": "சம்மதம்",
- "loading": "ஏற்றுகிறது...",
- "domainWarning": "நீங்கள் QR குறியீட்டை ஸ்கேன் செய்யும் இணையதளத்தின் டொமைனை கீழே உள்ளவாறு உறுதிப்படுத்தவும்",
- "access": " அணுகலைக் கோருகிறது",
- "status": "நிலை",
- "successMessage":"நீங்கள் வெற்றிகரமாக உள்நுழைந்துள்ளீர்கள் ",
- "okay": "சரி"
- },
- "ReceiveVcScreen": {
- "header": "{{vcLabel}} விவரங்கள்",
- "acceptRequest": "கோரிக்கையை ஏற்று {{vcLabel}} ஐப் பெறவும்",
- "acceptRequestAndVerify": "கோரிக்கையை ஏற்று சரிபார்க்கவும்",
- "reject": "நிராகரிக்கவும்"
- },
- "RequestScreen": {
- "bluetoothDenied": "{{vcLabel}}ஐக் கோர புளூடூத்தை இயக்கவும்",
- "showQrCode": "{{vcLabel}}ஐக் கோர இந்த QR குறியீட்டைக் காட்டு",
- "incomingVc": "உள்வரும் {{vcLabel}}",
- "request": "கோரிக்கை",
- "status": {
- "accepted": {
- "title": "வெற்றி!",
- "message": "{{vcLabel}} ஆனது {{sender}} இடமிருந்து வெற்றிகரமாகப் பெறப்பட்டது"
- },
- "rejected": {
- "title": "அறிவிப்பு",
- "message": "நீங்கள் {{sender}} இன் {{vcLabel}} ஐ நிராகரித்தீர்கள்"
- },
- "disconnected": {
- "title": "துண்டிக்கப்பட்டது",
- "message": "இணைப்பு துண்டிக்கப்பட்டது. மீண்டும் முயற்சிக்கவும்."
- },
- "waitingConnection": "இணைப்பிற்காக காத்திருக்கிறது...",
- "exchangingDeviceInfo": {
- "message": "சாதனத் தகவலைப் பரிமாறிக் கொள்கிறது...",
- "timeoutHint": "சாதனத் தகவலைப் பரிமாறிக்கொள்ள அதிக நேரம் எடுக்கிறது..."
- },
- "connected": {
- "message": "சாதனத்துடன் இணைக்கப்பட்டது. {{vcLabel}}க்காகக் காத்திருக்கிறது...",
- "timeoutHint": "இதுவரை தரவு எதுவும் பெறப்படவில்லை. சாதனத்தை அனுப்புவது இன்னும் இணைக்கப்பட்டுள்ளதா?"
- }
- },
- "online": "நிகழ்நிலை",
- "offline": "ஆஃப்லைன்",
- "gotoSettings": "அமைப்புகளுக்குச் செல்லவும்"
- },
- "ScanScreen": {
- "header": "QR குறியீட்டை ஸ்கேன் செய்",
- "noShareableVcs": "பகிரக்கூடிய {{vcLabel}} எதுவும் இல்லை.",
- "sharingVc": "பகிர்தல் {{vcLabel}}",
- "errors": {
- "locationDisabled": {
- "message": "ஸ்கேனிங் செயல்பாட்டிற்கு இருப்பிடச் சேவைகள் இயக்கப்பட வேண்டும்",
- "button": "இருப்பிட சேவைகளை இயக்கு"
- },
- "locationDenied": {
- "message": "ஸ்கேனிங் செயல்பாட்டிற்கு இருப்பிட அனுமதி தேவை",
- "button": "இருப்பிடம் அணுகலை அனுமதி"
- }
- },
- "status": {
- "connecting": "இணைக்கிறது...",
- "connectingTimeout": "இணைப்பை ஏற்படுத்த சிறிது நேரம் ஆகும். மற்ற சாதனம் இணைப்புகளுக்குத் திறந்திருக்கிறதா?",
- "exchangingDeviceInfo": "சாதன தகவல் பரிமாற்றம்...",
- "exchangingDeviceInfoTimeout": "சாதனத் தகவலைப் பரிமாறிக்கொள்ள சிறிது நேரம் ஆகும். நீங்கள் மீண்டும் இணைக்க வேண்டியிருக்கலாம்.",
- "invalid": "தவறான QR குறியீடு"
- }
- },
- "SelectVcOverlay": {
- "header": "பகிர்வு {{vcLabel}}",
- "chooseVc": "நீங்கள் பகிர விரும்பும் {{vcLabel}} ஐத் தேர்ந்தெடுக்கவும்",
- "share": "பகிர்",
- "verifyAndShare": "அடையாளத்தைச் சரிபார்த்து பகிரவும்"
- },
- "SendVcScreen": {
- "reasonForSharing": "பகிர்வதற்கான காரணம் (விரும்பினால்)",
- "acceptRequest": "கோரிக்கையை ஏற்று {{vcLabel}}ஐத் தேர்வு செய்யவும்",
- "acceptRequestAndVerify": "கோரிக்கையை ஏற்று சரிபார்க்கவும்",
- "reject": "நிராகரிக்கவும்",
- "status": {
- "sharing": {
- "title": "பகிர்தல்...",
- "hint": "பெறும் சாதனம் பங்கை ஏற்க அல்லது நிராகரிக்க காத்திருக்கவும்.",
- "timeoutHint": "பகிர்வதற்கு எதிர்பார்த்ததை விட அதிக நேரம் எடுக்கிறது. இணைப்பில் சிக்கல் இருக்கலாம்."
- },
- "accepted": {
- "title": "வெற்றி!",
- "message": "உங்கள் {{vcLabel}} வெற்றிகரமாக {{receiver}} உடன் பகிரப்பட்டது"
- },
- "rejected": {
- "title": "கவனிக்கவும்",
- "message": "உங்கள் {{vcLabel}}, {{receiver}} ஆல் நிராகரிக்கப்பட்டது"
- }
- },
- "consentToPhotoVerification": "அங்கீகாரத்திற்காக எனது புகைப்படத்தை எடுக்க நான் ஒப்புதல் அளிக்கிறேன்"
- },
- "VerifyIdentityOverlay": {
- "status": {
- "verifyingIdentity": "அடையாளத்தை சரிபார்க்கிறது..."
- },
- "errors": {
- "invalidIdentity": {
- "title": "அடையாளத்தைச் சரிபார்க்க முடியவில்லை",
- "message": "பிழை ஏற்பட்டது, உங்கள் உருவப்படத்தை ஸ்கேன் செய்ய முடியவில்லை. மீண்டும் முயலவும், உங்களின் முகம் தெரிவதை உறுதி செய்து கொள்ளவும், துணைக்கருவிகள் எதுவும் இல்லை.",
- "messageNoRetry": "பிழை ஏற்பட்டது, உங்கள் உருவப்படத்தை ஸ்கேன் செய்ய முடியவில்லை."
- }
- }
- },
- "SendVcModal": {
- "reasonForSharing": "பகிர்வதற்கான காரணம் (விரும்பினால்)",
- "acceptRequest": "கோரிக்கையை ஏற்று {{vcLabel}} என்பதைத் தேர்ந்தெடுக்கவும்",
- "reject": "நிராகரி",
- "statusSharing": {
- "title": "பகிர்வு..."
- },
- "statusAccepted": {
- "title": "வெற்றி!",
- "message": "உங்கள் {{vcLabel}} வெற்றிகரமாக {{receiver}} உடன் பகிரப்பட்டது"
- },
- "statusRejected": {
- "title": "அறிவிப்பு",
- "message": "உங்கள் {{vcLabel}} ஆனது {{receiver}} ஆல் நிராகரிக்கப்பட்டது"
- }
- },
- "WelcomeScreen": {
- "title": "திறந்த மூல அடையாள தீர்வு",
- "getStarted": "தொடங்கு",
- "unlockApp": "பயன்பாட்டைத் திற"
- },
- "common": {
- "cancel": "ரத்துசெய்",
- "save": "சேமி",
- "dismiss": "நிராகரி",
- "editLabel": "திருத்து {{label}}",
- "tryAgain": "மீண்டும் முயற்சி செய்",
- "camera": {
- "errors": {
- "missingPermission": "இந்தப் பயன்பாடு மற்றொரு சாதனத்தின் QR குறியீட்டை ஸ்கேன் செய்ய கேமராவைப் பயன்படுத்துகிறது."
- },
- "allowAccess": "கேமராவை அணுக அனுமதிக்கவும்"
+{
+ "ActivityLogText": {
+ "VC_SHARED": "பகிர்ந்து கொண்டார்",
+ "VC_RECEIVED": "பெற்றது",
+ "VC_RECEIVED_NOT_SAVED": "பெறப்பட்டது சேமிக்கப்படவில்லை",
+ "VC_DELETED": "நீக்கப்பட்டது",
+ "VC_DOWNLOADED": "பதிவிறக்கம் செய்யப்பட்டது",
+ "VC_REVOKED": "ரத்து செய்யப்பட்டது",
+ "VC_SHARED_WITH_VERIFICATION_CONSENT": "பகிர்ந்து கொண்டார். இருப்பைச் சரிபார்ப்பதற்கு ஒப்புதல் அளிக்கப்பட்டது",
+ "VC_RECEIVED_WITH_PRESENCE_VERIFIED": "பெற்றது. இருப்பு சரிபார்க்கப்பட்டது",
+ "VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED": "பெற்றது. இருப்பைச் சரிபார்க்க முடியவில்லை",
+ "PRESENCE_VERIFIED_AND_VC_SHARED": "சரிபார்க்கப்பட்டு பகிரப்பட்டது",
+ "PRESENCE_VERIFICATION_FAILED": "சரிபார்ப்பு தோல்வியடைந்தது",
+ "QRLOGIN_SUCCESFULL": "QRஉள்நுழைவு வெற்றிகரமாக உள்ளது",
+ "WALLET_BINDING_SUCCESSFULL": "செயல்படுத்தல் வெற்றி",
+ "WALLET_BINDING_FAILURE": "செயல்படுத்துவதில் தோல்வி",
+ "VC_REMOVED": "பணப்பையிலிருந்து அகற்றப்பட்டது"
+ },
+ "DeviceInfoList": {
+ "requestedBy": "கோரியவர்",
+ "sentBy": "அனுப்பியவர்",
+ "deviceRefNumber": "சாதன குறிப்பு எண்",
+ "name": "பெயர்",
+ "Verifier": "சரிபார்ப்பவர்",
+ "Wallet": "வாலட்"
+ },
+ "PasscodeVerify": {
+ "passcodeMismatchError": "கடவுக்குறியீடு பொருந்தவில்லை."
+ },
+ "FaceScanner": {},
+ "OIDcAuth": {
+ "title": "OIDC அங்கீகாரம்",
+ "text": "OIDC வழங்குநர் UI உடன் மாற்றப்பட வேண்டும்",
+ "verify": "சரிபார்க்கவும்"
+ },
+ "QrScanner": {
+ "cameraAccessDisabled": "கேமரா அணுகல் முடக்கப்பட்டுள்ளது!",
+ "cameraPermissionGuideLabel": "அமைப்புகளுக்குச் சென்று கேமரா அணுகலை கைமுறையாக இயக்கவும்.",
+ "flipCamera": "ஃபிளிப் கேமரா"
+ },
+ "VcDetails": {
+ "generatedOn": "உருவாக்கப்பட்டது",
+ "status": "நிலை",
+ "valid": "செல்லுபடியாகும்",
+ "photo": "புகைப்படம்",
+ "fullName": "முழு பெயர்",
+ "gender": "பாலினம்",
+ "dateOfBirth": "பிறந்த தேதி",
+ "phoneNumber": "தொலைபேசி எண்",
+ "email": "மின்னஞ்சல்",
+ "address": "முகவரி",
+ "reasonForSharing": "பகிர்வதற்கான காரணம்",
+ "idType": "ஐடி வகை",
+ "id": "ஐடி",
+ "qrCodeHeader": "க்யு ஆர் குறியீடு",
+ "nationalCard": "தேசிய அட்டை್",
+ "uin": "UIN",
+ "vid": "VID",
+ "enableVerification": "செயல்படுத்த",
+ "profileAuthenticated": "ஆன்லைன் உள்நுழைவுக்காக செயல்படுத்தப்பட்டது",
+ "offlineAuthDisabledHeader": "ஆன்லைன் உள்நுழைவுக்கான செயல்படுத்தல் நிலுவையில் உள்ளது",
+ "offlineAuthDisabledMessage": "இந்த நற்சான்றிதழை ஆன்லைன் உள்நுழைவுக்குப் பயன்படுத்த, கீழே உள்ள பொத்தானைக் கிளிக் செய்யவும்.",
+ "verificationEnabledSuccess": "ஆன்லைன் உள்நுழைவுக்காக செயல்படுத்தப்பட்டது",
+ "goback": "திரும்பி செல்",
+ "BindingWarning": "இந்த நற்சான்றிதழுக்கான சரிபார்ப்பை நீங்கள் வேறொரு பணப்பையில் இயக்கியிருந்தால், அது மேலெழுதப்படும். தொடர வேண்டுமா?",
+ "yes_confirm": "ஆம், நான் உறுதி செய்கிறேன்",
+ "no": "இல்லை",
+ "Alert": "எச்சரிக்கை",
+ "ok": "சரி",
+ "credentialRegistry": "நற்சான்றிதழ்கள் பதிவு",
+ "errors": {
+ "savingFailed": {
+ "title": "அட்டைஐ சேமிப்பதில் தோல்வி",
+ "message": "கடையில் அட்டைஐ சேமிக்கும் போது ஏதோ தவறு ஏற்பட்டது."
}
}
- }
\ No newline at end of file
+ },
+ "HomeScreenKebabPopUp": {
+ "title": "மேலும் விருப்பங்கள்",
+ "unPinCard": "கார்டை அன்பின் செய்யவும்",
+ "pinCard": "பின் அட்டை",
+ "offlineAuthenticationDisabled!": "ஆன்லைன் உள்நுழைவுக்கான செயல்படுத்தல் நிலுவையில் உள்ளது",
+ "offlineAuthDisabledMessage": "இந்த நற்சான்றிதழ்களை ஆன்லைன் அங்கீகாரத்திற்காகப் பயன்படுத்த இங்கே கிளிக் செய்யவும்.",
+ "viewActivityLog": "செயல்பாட்டு பதிவைக் காண்க",
+ "removeFromWallet": "பணப்பையிலிருந்து அகற்று",
+ "revokeId": "ஐடியைத் திரும்பப் பெறு",
+ "revokeMessage": "இந்தச் சுயவிவரத்திற்கான விர்ச்சுவல் ஐடியைத் திரும்பப் பெறவும்"
+ },
+ "WalletBinding": {
+ "inProgress": "செயல்பாட்டில் உள்ளது",
+ "profileAuthenticated": "சுயவிவரம் அங்கீகரிக்கப்பட்டது!"
+ },
+ "BindingVcWarningOverlay": {
+ "alert": "தயவுசெய்து உறுதிப்படுத்தவும்",
+ "BindingWarning": "இந்த நற்சான்றிதழுக்கான சரிபார்ப்பை நீங்கள் வேறொரு பணப்பையில் இயக்கியிருந்தால், அது மேலெழுதப்படும். தொடர வேண்டுமா?",
+ "yesConfirm": "ஆம், உறுதி செய்கிறேன்",
+ "no": "இல்லை"
+ },
+ "RemoveVcWarningOverlay": {
+ "alert": "தயவுசெய்து உறுதிப்படுத்தவும்",
+ "removeWarning": "இந்த கார்டை அகற்ற விரும்புகிறீர்களா",
+ "confirm": "ஆம், உறுதி செய்கிறேன்",
+ "no": "இல்லை"
+ },
+ "AuthScreen": {
+ "header": "பயன்பாட்டைத் திறக்க பயோமெட்ரிக்ஸைப் பயன்படுத்த விரும்புகிறீர்களா?",
+ "Description": "பயன்பாட்டைத் திறக்க பயோமெட்ரிக்ஸைப் பயன்படுத்த விரும்புகிறீர்களா??",
+ "useBiometrics": "கைரேகையைப் பயன்படுத்தவும்",
+ "usePasscode": "கடவுக்குறியீட்டைப் பயன்படுத்தவும்",
+ "errors": {
+ "unavailable": "சாதனம் பயோமெட்ரிக்ஸை ஆதரிக்காது",
+ "unenrolled": "பயோமெட்ரிக்ஸைப் பயன்படுத்த, உங்கள் சாதன அமைப்புகளில் உங்கள் கைரேகையைப் பதிவு செய்யவும்",
+ "failed": "பயோமெட்ரிக்ஸ் மூலம் அங்கீகரிக்க முடியவில்லை",
+ "generic": "பயோமெட்ரிக்ஸ் அங்கீகாரத்தில் பிழை இருப்பதாகத் தெரிகிறது"
+ }
+ },
+ "BiometricScreen": {
+ "unlock": "கைரேகை மூலம் திற"
+ },
+ "HistoryScreen": {
+ "noHistory": "இதுவரை வரலாறு இல்லை",
+ "downloaded": "கிடைத்தது",
+ "shared": "பகிர்ந்து கொண்டார்",
+ "received": "பெற்றது",
+ "deleted": "அகற்றப்பட்டது"
+ },
+ "SettingScreen": {
+ "header": "அமைப்புகள்",
+ "injiAsVerifierApp": "சரிபார்ப்பு பயன்பாடாக இன்ஜி",
+ "receiveCard": "பெற்ற அட்டை",
+ "basicSettings": "அடிப்படை அமைப்புகள்",
+ "bioUnlock": "பயோமெட்ரிக்ஸ் மூலம் திறக்கவும்",
+ "language": "மொழி",
+ "aboutInji": "இன்ஜி பற்றி",
+ "credentialRegistry": "நற்சான்றிதழ் பதிவு",
+ "errorMessage": "தவறான URL உள்ளிடப்பட்டது. தொடர சரியான URL ஐ உள்ளிடவும்.",
+ "injiTourGuide": "இன்ஜி சுற்றுலா வழிகாட்டி",
+ "logout": "வெளியேறு",
+ "resetInjiProps": "இன்ஜி ப்ராப்ஸை மீட்டமைக்கிறது..."
+ },
+ "AboutInji": {
+ "aboutInji": "இன்ஜி பற்றி",
+ "header": "இன்ஜி பற்றி",
+ "appID": "பயன்பாடாகும் ID",
+ "aboutDetailes": "இன்ஜி என்பது ஒரு மொபைல் பயன்பாடாகும், இது நற்சான்றிதழ்களைச் சேமிக்க டிஜிட்டல் பணப்பையாகப் பயன்படுத்தப்படலாம். எந்த இடத்திலும் நேரத்திலும், ஆஃப்லைன் மற்றும் ஆன்லைன் முறைகள் இரண்டிலும் அடையாளச் சரிபார்ப்பை இது அனுமதிக்கிறது.",
+ "forMoreDetailes": "மேலும் விவரங்களுக்கு",
+ "clickHere": "இங்கே கிளிக் செய்யவும்",
+ "version": "பதிப்பு",
+ "tuvaliVersion": "துவாலி-பதிப்பு"
+ },
+ "HelpScreen": {
+ "header": "உதவி",
+ "whatIsDigitalCredential?": "டிஜிட்டல் நற்சான்றிதழ் என்றால் என்ன?",
+ "detail-1": "டிஜிட்டல் நற்சான்றிதழ் என்பது உங்கள் உடல் அடையாள அட்டையின் டிஜிட்டல் பதிப்பாகும்",
+ "whatCanDoWithDigitalCredential?": "டிஜிட்டல் சான்றுகளை வைத்து நாம் என்ன செய்ய முடியும்?",
+ "detail-2": "உங்கள் டிஜிட்டல் சான்றுகளைப் பயன்படுத்தி பல்வேறு அரசு மற்றும் தனியார் சேவைகளைப் பெறலாம்.",
+ "howToAddCard?": "அட்டையை எவ்வாறு சேர்ப்பது?",
+ "detail-3": "கார்டைச் சேர்க்க, முகப்புப் பக்கத்தில் உள்ள '+' பொத்தானைக் கிளிக் செய்து, பொருத்தமான விருப்பத்தைத் தேர்ந்தெடுக்கவும்.",
+ "howToRemoveCardFromWallet?": "ஒரு அட்டையை எவ்வாறு பகிர்வது?",
+ "detail-4": "கார்டில் இடதுபுறமாக ஸ்வைப் செய்யவும் > மேலும் என்பதைக் கிளிக் செய்யவும் > வாலட்டில் இருந்து அகற்று",
+ "canWeAddMultipleCards?": "பல அட்டைகளைச் சேர்க்கலாமா?",
+ "detail-5": "ஆம், முகப்புப் பக்கத்தில் உள்ள '+' பொத்தானைக் கிளிக் செய்வதன் மூலம் பல அட்டைகளை வாலட்டில் சேர்க்கலாம்.",
+ "howToShareCard?": "ஒரு அட்டையை எவ்வாறு பகிர்வது?",
+ "detail-6": "'பகிர்' பொத்தானைக் கிளிக் செய்து, கோரும் தரப்பினரிடமிருந்து QR குறியீட்டை ஸ்கேன் செய்யவும். இணைப்பு நிறுவப்பட்டதும், அட்டை பகிரப்படும்.",
+ "howToActivateCardForOnlineLogin?": "ஆன்லைன் உள்நுழைவுக்கான அட்டையை எவ்வாறு செயல்படுத்துவது?",
+ "detail-7": "வாலட்டில் கார்டை வெற்றிகரமாகச் சேர்த்த பிறகு, கார்டில் உள்ள 'ஆன்லைன் உள்நுழைவுக்கான ஆக்டிவேஷன் பெண்டிங்' என்பதைக் கிளிக் செய்யவும். 'செயல்படுத்து' என்பதைக் கிளிக் செய்தால், ஆன்லைன் உள்நுழைவுக்கு கார்டு தயாராக இருக்கும்.",
+ "howToViewActivity?": "செயல்பாட்டுப் பதிவுகளை எவ்வாறு பார்ப்பது?",
+ "detail-8": "முகப்புப் பக்கத்தில், பயனரின் செயல்பாட்டின் விவரங்களைப் பார்க்க, 'வரலாறு' என்பதைக் கிளிக் செய்யவும்.",
+ "whatCanDoBiometricsChanged?": "ஆண்ட்ராய்டு கீஸ்டோர் பயோமெட்ரிக் மாற்றப்பட்டால் என்ன நடக்கும்?",
+ "detail-9": "அடையாளச் சான்றுகளுக்கான தனிப்பட்ட விசைகள் போன்ற முக்கியமான தகவல்களை ஆண்ட்ராய்டு கீஸ்டோர் வைத்திருக்கிறது. உங்கள் பயோமெட்ரிக்ஸை மாற்றினால், பழைய விசைகள் இனி பாதுகாப்பாக இருக்காது. விஷயங்களைப் பாதுகாப்பாக வைத்திருக்க, அந்தப் பழைய சாவிகளால் கையொப்பமிடப்பட்ட அடையாளச் சான்றுகளை அகற்றுவோம். உங்கள் அடையாளச் சான்றுகளை மீண்டும் பதிவிறக்கம் செய்யலாம், மேலும் அவை சமீபத்திய, பாதுகாப்பான விசைகளுடன் கையொப்பமிடப்படும்."
+ },
+ "AddVcModal": {
+ "requestingCredential": "நற்சான்றிதழைக் கோருகிறது...",
+ "errors": {
+ "input": {
+ "empty": "உள்ளீடு காலியாக இருக்க முடியாது",
+ "invalidFormat": "உள்ளீட்டு வடிவம் தவறானது"
+ },
+ "backend": {
+ "invalidOtp": "OTP தவறானது",
+ "expiredOtp": "OTP காலாவதியானது",
+ "invalidUin": "UIN தவறானது",
+ "invalidVid": "VID தவறானது",
+ "missingUin": "உள்ளிட்ட UIN செயலிழக்கப்பட்டது/தடுக்கப்பட்டது. தொடர சரியான UIN ஐ உள்ளிடவும்",
+ "missingVid": "VID தரவுத்தளத்தில் இல்லை",
+ "noMessageAvailable": "சிறிது நேரம் கழித்து முயற்சிக்கவும்",
+ "whileGeneratingOtpErrorIsOccured": "OTP உருவாக்கும் போது பிழை ஏற்பட்டது",
+ "networkRequestFailed": "நெட்வொர்க் கோரிக்கை தோல்வியடைந்தது",
+ "deactivatedVid": "உள்ளிட்ட VID செயலிழக்கப்பட்டது/காலாவதியானது. தொடர சரியான VID ஐ உள்ளிடவும்"
+ }
+ }
+ },
+ "GetVcModal": {
+ "retrievingId": "ஐடியை மீட்டெடுக்கிறது",
+ "errors": {
+ "input": {
+ "empty": "உள்ளீடு காலியாக இருக்க முடியாது",
+ "invalidFormat": "உள்ளீட்டு வடிவம் தவறானது"
+ },
+ "backend": {
+ "invalidOtp": "OTP தவறானது",
+ "expiredOtp": "OTP காலாவதியானது",
+ "applicationProcessing": "AID தயாராக இல்லை",
+ "noMessageAvailable": "சிறிது நேரம் கழித்து முயற்சிக்கவும்",
+ "networkRequestFailed": "நெட்வொர்க் கோரிக்கை தோல்வியடைந்தது",
+ "invalidAid": "உள்ளிடப்பட்ட எய்ட் கிடைக்கவில்லை.நுழைவதற்கு முன் உங்கள் உதவியை சரிபார்க்கவும்",
+ "timeout": "நேரம் முடிந்தது"
+ }
+ }
+ },
+ "DownloadingVcModal": {
+ "header": "உங்கள் அட்டைஐப் பதிவிறக்குகிறது",
+ "bodyText": "இதற்கு சிறிது நேரம் ஆகலாம், உங்கள் அட்டை பதிவிறக்கம் செய்யப்பட்டு கிடைக்கும்போது உங்களுக்கு அறிவிப்போம்",
+ "backButton": "பேக் ஹோம்"
+ },
+ "GetIdInputModal": {
+ "header": "உங்கள் UIN/VID ஐ மீட்டெடுக்கவும்",
+ "applicationIdLabel": "உங்கள் விண்ணப்ப ஐடியை உள்ளிடவும்",
+ "enterApplicationId": "விண்ணப்ப ஐடியை உள்ளிடவும்",
+ "requestingOTP": "OTP ஐக் கோருகிறது...",
+ "qstnMarkToolTip": "விண்ணப்ப ஐடி பதிவுசெய்த பிறகு பெறப்பட்ட ஒப்புகையில் கிடைக்கும்.",
+ "getUIN": "UIN/VIDஐப் பெறுங்கள்"
+ },
+ "IdInputModal": {
+ "header": "உங்கள் ஐடியை மீட்டெடுக்கவும்",
+ "guideLabel": "ஐடி வகையைத் தேர்ந்தெடுத்து, நீங்கள் மீட்டெடுக்க விரும்பும் ஐடியின் MOSIP வழங்கப்பட்ட UIN அல்லது VID ஐ உள்ளிடவும்",
+ "generateVc": "அட்டை ஐ உருவாக்கு",
+ "downloadID": "ஐடியைப் பதிவிறக்கவும்",
+ "enterId": "{{idType}} ஐ உள்ளிடவும்",
+ "noUIN/VID": "UIN/VID இல்லையா? ",
+ "getItHere": "இப்பொழுதே பெற்றுக்கொள்ளவும்",
+ "requestingOTP": "OTP ஐக் கோருகிறது..."
+ },
+ "OtpVerificationModal": {
+ "title": "OTP சரிபார்ப்பு",
+ "otpSentMessage": "உங்கள் பதிவு செய்யப்பட்ட மொபைல் எண்ணுக்கு 6 இலக்கக் குறியீட்டை அனுப்பியுள்ளோம்!",
+ "resendTheCode": "நீங்கள் குறியீட்டை மீண்டும் அனுப்பலாம் ",
+ "resendCode": "குறியீட்டை மீண்டும் அனுப்பு"
+ },
+ "MyVcsTab": {
+ "bringYourDigitalID": "உங்கள் டிஜிட்டல் ஐடியைக் கொண்டு வாருங்கள்",
+ "generateVcDescription": "உங்கள் அட்டை ஐப் பதிவிறக்க, கீழே உள்ள பதிவிறக்கு அட்டை என்பதைத் தட்டவும்",
+ "downloadCard": "கார்டைப் பதிவிறக்கவும்",
+ "downloadingYourCard": "உங்கள் கார்டைப் பதிவிறக்க, இதற்கு 5 நிமிடங்கள் வரை ஆகலாம்",
+ "errors": {
+ "savingFailed": {
+ "title": "அட்டைஐ சேமிப்பதில் தோல்வி",
+ "message": "கடையில் அட்டைஐ சேமிக்கும் போது ஏதோ தவறு ஏற்பட்டது."
+ },
+ "storageLimitReached": {
+ "title": "போதுமான ஆப்டேட்டா இல்லை",
+ "message": "ஆப்டேட்டா நிரம்பியிருப்பதால் கார்டுகளைச் சேர்க்கவோ பெறவோ முடியாது. தொடர ஆப்டேட்டாவை அழிக்கவும்."
+ },
+ "vcIsTampered": {
+ "title": "சில அடையாளச் சான்றுகள் சிதைக்கப்பட்டுள்ளன",
+ "message": "பாதிக்கப்பட்ட கோப்புகள் அகற்றப்பட்டன, மீண்டும் பதிவிறக்கவும்."
+ },
+ "keystoreNotExists": {
+ "title": "பாதுகாப்பான விசைச் சேமிப்பகம் இல்லை",
+ "message": "உங்கள் மொபைலில் உள்ள முக்கிய சேமிப்பகம் பாதுகாப்பாக இல்லை. போன் ஹேக் செய்யப்பட்டால் உங்கள் சாவிகள் கசிந்திருக்கலாம்.",
+ "riskOkayText": "சரி, நான் ரிஸ்க் எடுக்கிறேன்"
+ }
+ }
+ },
+ "OnboardingOverlay": {
+ "stepOneTitle": "பாதுகாப்பான பகிர்வு!",
+ "stepOneText": "உங்கள் டிஜிட்டல் நற்சான்றிதழை எப்போதும் உங்களுடன் வைத்திருக்கவும். அவற்றை திறம்பட நிர்வகிக்கவும் பயன்படுத்தவும் இன்ஜி உதவுகிறது. தொடங்குவதற்கு, உங்கள் சுயவிவரத்தில் கார்டுகளைச் சேர்க்கவும்.",
+ "stepTwoTitle": "நம்பகமான டிஜிட்டல் வாலட்",
+ "stepTwoText": "உங்கள் முக்கியமான கார்டுகளை ஒரே நம்பகமான பணப்பையில் சேமித்து எடுத்துச் செல்லுங்கள்.",
+ "stepThreeTitle": "பாதுகாப்பான பகிர்வு",
+ "stepThreeText": "தொந்தரவு இல்லாத வகையில் உங்கள் கார்டுகளைப் பாதுகாப்பாகப் பகிர்ந்து, பல்வேறு சேவைகளைப் பெறுங்கள்.",
+ "stepFourTitle": "தொந்தரவு இல்லாத அங்கீகாரம்",
+ "stepFourText": "சேமிக்கப்பட்ட டிஜிட்டல் நற்சான்றிதழைப் பயன்படுத்தி உங்களை எளிதாக அங்கீகரிக்கவும்.",
+ "getStarted": "தொடங்குங்கள்",
+ "goBack": "திரும்பி போ",
+ "back": "மீண்டும்",
+ "skip": "தவிர்க்கவும்",
+ "next": "அடுத்தது"
+ },
+ "ReceivedVcsTab": {
+ "receivedCards": "பெற்ற அட்டைகள்",
+ "header": "பெற்ற அட்டைகள்",
+ "noReceivedVcsTitle": "இன்னும் அட்டை கிடைக்கவில்லை",
+ "noReceivedVcsText": "அட்டை பெறுவதற்கு கீழே உள்ள கோரிக்கையைத் தட்டவும்"
+ },
+ "ViewVcModal": {
+ "title": "அடையாள விவரங்கள்",
+ "inProgress": "செயல்பாட்டில் உள்ளது",
+ "cancel": "ரத்து செய்",
+ "lock": "பூட்டு",
+ "unlock": "திறத்தல்",
+ "rename": "மறுபெயரிடு",
+ "delete": "நீக்கு",
+ "revoke": "திரும்பப்பெறு",
+ "revoking": "உங்கள் பணப்பையில் VID {{vid}} உடன் நற்சான்றிதழ் உள்ளது. இதைத் திரும்பப் பெறுவது வாலட்டில் இருந்து தானாகவே அகற்றப்படும்.நீங்கள் நிச்சயமாக தொடர விரும்புகிறீர்களா?",
+ "requestingOtp": "ஓடிபியைக் கோருகிறது...",
+ "editTag": "திருத்து குறி",
+ "redirecting": "வழிமாற்று...",
+ "success": {
+ "unlocked": "அட்டை வெற்றிகரமாக திறக்கப்பட்டது",
+ "locked": "அட்டை வெற்றிகரமாக பூட்டப்பட்டது",
+ "revoked": "VID {{vid}} has been revoked. அதைக் கொண்ட எந்த நற்சான்றிதழும் பணப்பையிலிருந்து தானாகவே அகற்றப்படும்"
+ }
+ },
+ "MainLayout": {
+ "home": "வீடு",
+ "scan": "ஸ்கேன்",
+ "request": "கோரிக்கை",
+ "history": "வரலாறு",
+ "settings": "செட்டிங்ஸ்"
+ },
+ "PasscodeScreen": {
+ "header": "கடவுக்குறியீட்டை அமைக்கவும்",
+ "enterNewPassword": "புதிய கடவுக்குறியீட்டை உள்ளிடவும்",
+ "reEnterPassword": "புதிய கடவுக்குறியீட்டை மீண்டும் உள்ளிடவும்",
+ "confirmPasscode": "கடவுக்குறியீட்டை உறுதிப்படுத்தவும்",
+ "enterPasscode": "உங்கள் கடவுக்குறியீட்டை உள்ளிடவும்"
+ },
+ "AppMetaData": {
+ "header": "இன்ஜி பற்றி",
+ "version": "பதிப்பு",
+ "useBle": "BLE ஆல் இயக்கப்படுகிறது"
+ },
+ "QrScreen": {
+ "title": "QR உள்நுழைவு",
+ "alignQr": "ஸ்கேன் செய்ய ஃப்ரேமுக்குள் QR குறியீட்டை சீரமைக்கவும்",
+ "confirmation": "உறுதிப்படுத்தல்",
+ "checkDomain": "மேலும், முகவரிப் பட்டியில் பூட்டு ஐகான் உள்ளதா எனச் சரிபார்க்கவும்.",
+ "domainHead": "https://",
+ "selectId": "ஐடியைத் தேர்ந்தெடுக்கவும்",
+ "noBindedVc": "சரிபார்க்க, பிணைக்கப்பட்ட அட்டை எதுவும் இல்லை",
+ "back": "திரும்பி செல்",
+ "confirm": "உறுதிப்படுத்தவும்",
+ "verify": "சரிபார்க்கவும்",
+ "faceAuth": "முக அங்கீகாரம்",
+ "consent": "சம்மதம்",
+ "loading": "ஏற்றுகிறது...",
+ "domainWarning": "நீங்கள் QR குறியீட்டை ஸ்கேன் செய்யும் இணையதளத்தின் டொமைனை கீழே உள்ளவாறு உறுதிப்படுத்தவும்",
+ "access": " அணுகலைக் கோருகிறது",
+ "status": "நிலை",
+ "successMessage": "நீங்கள் வெற்றிகரமாக உள்நுழைந்துள்ளீர்கள் ",
+ "okay": "சரி",
+ "allow": "அனுமதி",
+ "cancel": "ரத்து செய்",
+ "essentialClaims": "அத்தியாவசிய உரிமைகோரல்கள்",
+ "voluntaryClaims": "தன்னார்வ உரிமைகோரல்கள்",
+ "required": "தேவை"
+ },
+ "ReceiveVcScreen": {
+ "header": "அட்டை விவரங்கள்",
+ "save": "சேமி அட்டை",
+ "verifyAndSave": "சரிபார்த்து சேமிக்கவும்",
+ "acceptRequest": "கோரிக்கையை ஏற்று அட்டை ஐப் பெறவும்",
+ "acceptRequestAndVerify": "கோரிக்கையை ஏற்று சரிபார்க்கவும்",
+ "reject": "நிராகரிக்கவும்",
+ "discard": "நிராகரிக்கவும்",
+ "goToReceivedVCTab": "பெறப்பட்ட அட்டை ஐக் காண்க",
+ "saving": "கார்டு சேமிக்கப்படுகிறது",
+ "errors": {
+ "savingFailed": {
+ "title": "அட்டைஐ சேமிப்பதில் தோல்வி",
+ "message": "கடையில் அட்டைஐ சேமிக்கும் போது ஏதோ தவறு ஏற்பட்டது."
+ }
+ }
+ },
+ "RequestScreen": {
+ "receiveCard": "பெற்ற அட்டை",
+ "bluetoothDenied": "அட்டைஐக் கோர புளூடூத்தை இயக்கவும்",
+ "bluetoothStateIos": "புளூடூத் முடக்கப்பட்டுள்ளது, கட்டுப்பாட்டு மையத்திலிருந்து அதை இயக்கவும்",
+ "bluetoothStateAndroid": "புளூடூத் முடக்கப்பட்டுள்ளது, விரைவு அமைப்புகள் மெனுவிலிருந்து அதை இயக்கவும்",
+ "showQrCode": "குடியுரிமை அட்டைஐக் கோர இந்த QR குறியீட்டைக் காட்டு",
+ "incomingVc": "உள்வரும் அட்டை",
+ "request": "கோரிக்கை",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "அட்டைகள் கோருவதற்கு அருகிலுள்ள சாதனங்களின் அனுமதி தேவை",
+ "button": "அனுமதி அனுமதி"
+ },
+ "storageLimitReached": {
+ "title": "போதுமான ஆப்டேட்டா இல்லை",
+ "message": "ஆப்டேட்டா நிரம்பியிருப்பதால் கார்டுகளைச் சேர்க்கவோ பெறவோ முடியாது. தொடர ஆப்டேட்டாவை அழிக்கவும்."
+ }
+ },
+ "status": {
+ "accepted": {
+ "title": "வெற்றி!",
+ "message": "அட்டை ஆனது பணப்பை இடமிருந்து வெற்றிகரமாகப் பெறப்பட்டது"
+ },
+ "rejected": {
+ "title": "அறிவிப்பு",
+ "message": "நீங்கள் பணப்பை இன் அட்டை ஐ நிராகரித்தீர்கள்"
+ },
+ "disconnected": {
+ "title": "துண்டிக்கப்பட்டது",
+ "message": "இணைப்பு துண்டிக்கப்பட்டது. மீண்டும் முயற்சிக்கவும்."
+ },
+ "waitingConnection": "இணைப்பிற்காக காத்திருக்கிறது...",
+ "exchangingDeviceInfo": {
+ "message": "சாதனத் தகவலைப் பரிமாறிக் கொள்கிறது...",
+ "timeoutHint": "சாதனத் தகவலைப் பரிமாறிக்கொள்ள அதிக நேரம் எடுக்கிறது..."
+ },
+ "connected": {
+ "message": "சாதனத்துடன் இணைக்கப்பட்டது. அட்டைக்காகக் காத்திருக்கிறது...",
+ "timeoutHint": "இதுவரை தரவு எதுவும் பெறப்படவில்லை. சாதனத்தை அனுப்புவது இன்னும் இணைக்கப்பட்டுள்ளதா?"
+ },
+ "offline": {
+ "message": "ஆன்லைன் பகிர்வு பயன்முறையை இயக்க இணையத்துடன் இணைக்கவும்"
+ },
+ "bleError": {
+ "title": "இடமாற்றம் செய்ய முடியவில்லை",
+ "message": "அட்டை ஐ மாற்றும்போது ஏதோ தவறு ஏற்பட்டது. தயவு செய்து மீண்டும் முயற்சிக்கவும்.",
+ "hint": "பிழை: {{code}}"
+ }
+ },
+ "online": "நிகழ்நிலை",
+ "offline": "ஆஃப்லைன்",
+ "gotoSettings": "அமைப்புகளுக்குச் செல்லவும்"
+ },
+ "ScanScreen": {
+ "header": "QR குறியீட்டை ஸ்கேன் செய்யவும்",
+ "noShareableVcs": "பகிரக்கூடிய அட்டை எதுவும் இல்லை.",
+ "sharingVc": "பகிர்கிறது அட்டை",
+ "bluetoothStateIos": "புளூடூத் முடக்கப்பட்டுள்ளது, கட்டுப்பாட்டு மையத்திலிருந்து அதை இயக்கவும்",
+ "bluetoothStateAndroid": "புளூடூத் முடக்கப்பட்டுள்ளது, விரைவு அமைப்புகள் மெனுவிலிருந்து அதை இயக்கவும்",
+ "enableBluetoothMessage": "உள்ளூர் பகிர்வை ஆதரிக்க புளூடூத் அனுமதிகளை இயக்கவும்",
+ "enableBluetoothButtonText": "புளூடூத் அனுமதிகளை அனுமதிக்கவும்",
+ "scanningGuide": "ஃபோனை நிலையாகப் பிடித்து, QR குறியீட்டை ஸ்கேன் செய்யவும்s",
+ "errors": {
+ "locationDisabled": {
+ "message": "ஸ்கேனிங் செயல்பாட்டிற்கு இருப்பிடச் சேவைகள் இயக்கப்பட வேண்டும்",
+ "button": "இருப்பிட சேவைகளை இயக்கு"
+ },
+ "locationDenied": {
+ "message": "ஸ்கேனிங் செயல்பாட்டிற்கு இருப்பிட அனுமதி தேவை",
+ "button": "இருப்பிடம் அணுகலை அனுமதி"
+ },
+ "nearbyDevicesPermissionDenied": {
+ "message": "கார்டைப் பகிர, அருகிலுள்ள சாதனங்களின் அனுமதி தேவை",
+ "button": "அனுமதி அனுமதி"
+ },
+ "storageLimitReached": {
+ "title": "போதுமான ஆப்டேட்டா இல்லை",
+ "message": "ஆப்டேட்டா நிரம்பியிருப்பதால் உங்களால் கார்டுகளைப் பகிர முடியாது. தொடர ஆப்டேட்டாவை அழிக்கவும்."
+ }
+ },
+ "status": {
+ "inProgress": "செயல்பாட்டில் உள்ளது",
+ "establishingConnection": "இணைப்பை நிறுவுதல்",
+ "sharingInProgress": "பகிர்தல் செயல்பாட்டில் உள்ளது",
+ "connectingTimeout": "இணைப்பை ஏற்படுத்த சிறிது நேரம் ஆகும். மற்ற சாதனம் இணைப்புகளுக்குத் திறந்திருக்கிறதா?",
+ "exchangingDeviceInfo": "சாதனத் தகவலைப் பரிமாறிக் கொள்கிறது...",
+ "exchangingDeviceInfoTimeout": "சாதனத் தகவலைப் பரிமாறிக்கொள்ள சிறிது நேரம் ஆகும். நீங்கள் மீண்டும் இணைக்க வேண்டியிருக்கலாம்.",
+ "invalid": "தவறான QR குறியீடு",
+ "offline": "ஆன்லைன் பகிர்வு பயன்முறையைப் பயன்படுத்தி QR குறியீடுகளை ஸ்கேன் செய்ய இணையத்துடன் இணைக்கவும்",
+ "sent": "அட்டை அனுப்பப்பட்டது...",
+ "sentHint": "ரிசீவர் உங்கள் அட்டை ஐ சேமிக்க அல்லது நிராகரிக்க காத்திருக்கிறது",
+ "sharing": {
+ "title": "பகிர்தல்...",
+ "hint": "தேர்ந்தெடுத்த கார்டைப் பகிரும் வரை காத்திருக்கவும்.",
+ "timeoutHint": "பகிர்வதற்கு எதிர்பார்த்ததை விட அதிக நேரம் எடுக்கிறது. இணைப்பில் சிக்கல் இருக்கலாம்."
+ },
+ "accepted": {
+ "title": "ஐடி வெற்றிகரமாகப் பகிரப்பட்டது",
+ "message": "உங்கள் அட்டை வெற்றிகரமாக சரிபார்ப்பவர் உடன் பகிரப்பட்டது",
+ "gotohome": "வீட்டிற்கு போ"
+ },
+ "rejected": {
+ "title": "கவனிக்கவும்",
+ "message": "உங்கள் அட்டை, சரிபார்ப்பவர் ஆல் நிராகரிக்கப்பட்டது"
+ },
+ "bleError": {
+ "title": "இடமாற்றம் செய்ய முடியவில்லை",
+ "message": "அட்டை ஐ மாற்றும்போது ஏதோ தவறு ஏற்பட்டது. தயவு செய்து மீண்டும் முயற்சிக்கவும்.",
+ "hint": "பிழை: {{code}}"
+ }
+ }
+ },
+ "SelectVcOverlay": {
+ "header": "பகிர்வு அட்டை",
+ "chooseVc": "நீங்கள் பகிர விரும்பும் அட்டை ஐத் தேர்ந்தெடுக்கவும்",
+ "share": "பகிர்",
+ "verifyAndShare": "அடையாளத்தைச் சரிபார்த்து பகிரவும்"
+ },
+ "SendVcScreen": {
+ "reasonForSharing": "பகிர்வதற்கான காரணம் (விரும்பினால்)",
+ "acceptRequest": "பகிர்",
+ "acceptRequestAndVerify": "செல்ஃபியுடன் பகிரவும்",
+ "reject": "நிராகரிக்கவும்",
+ "consentToPhotoVerification": "அங்கீகாரத்திற்காக எனது புகைப்படத்தை எடுக்க நான் ஒப்புதல் அளிக்கிறேன்",
+ "pleaseSelectAnId": "ஐடியைத் தேர்ந்தெடுக்கவும்",
+ "status": {
+ "sharing": {
+ "title": "பகிர்தல்...",
+ "hint": "பெறும் சாதனம் பங்கை ஏற்க அல்லது நிராகரிக்க காத்திருக்கவும்.",
+ "timeoutHint": "பகிர்வதற்கு எதிர்பார்த்ததை விட அதிக நேரம் எடுக்கிறது. இணைப்பில் சிக்கல் இருக்கலாம்."
+ },
+ "accepted": {
+ "title": "வெற்றி!",
+ "message": "உங்கள் அட்டை வெற்றிகரமாக சரிபார்ப்பவர் உடன் பகிரப்பட்டது"
+ },
+ "rejected": {
+ "title": "கவனிக்கவும்",
+ "message": "உங்கள் அட்டை, சரிபார்ப்பவர் ஆல் நிராகரிக்கப்பட்டது"
+ }
+ }
+ },
+ "VerifyIdentityOverlay": {
+ "faceAuth": "முக அங்கீகாரம்",
+ "status": {
+ "verifyingIdentity": "அடையாளத்தை சரிபார்க்கிறது..."
+ },
+ "errors": {
+ "invalidIdentity": {
+ "title": "அடையாளத்தைச் சரிபார்க்க முடியவில்லை",
+ "message": "முகம் அடையாளம் தெரியவில்லை. தயவு செய்து மீண்டும் முயற்சிக்கவும்.",
+ "messageNoRetry": "முகம் அடையாளம் தெரியவில்லை."
+ }
+ }
+ },
+ "WelcomeScreen": {
+ "title": "திறந்த மூல அடையாள தீர்வு",
+ "getStarted": "தொடங்கு",
+ "unlockApp": "பயன்பாட்டைத் திற",
+ "failedToReadKeys": "விசைகளைப் படிக்க முடியவில்லை",
+ "retryRead": "மீண்டும் முயற்சிக்க வேண்டுமா?",
+ "errors": {
+ "decryptionFailed": "தரவை மறைகுறியாக்க முடியவில்லை",
+ "invalidateKeyError": {
+ "title": "பாதுகாப்புக் காரணங்களால் சில அடையாளச் சான்றுகள் நீக்கப்பட்டன.",
+ "message": "மீண்டும் பதிவிறக்கவும்."
+ }
+ },
+ "ignore": "புறக்கணிக்க"
+ },
+ "SetupLanguage": {
+ "header": "மொழியைத் தேர்ந்தெடுக்கவும்",
+ "description": "உங்களுக்கு விருப்பமான மொழியைத் தேர்ந்தெடுக்கவும்",
+ "save": "விருப்பத்தை சேமிக்கவும்"
+ },
+ "common": {
+ "cancel": "ரத்துசெய்",
+ "accept": "ஏற்றுக்கொள்",
+ "save": "சேமி",
+ "dismiss": "நிராகரி",
+ "editLabel": "திருத்து {{label}}",
+ "tryAgain": "மீண்டும் முயற்சி செய்",
+ "ignore": "புறக்கணிக்க",
+ "camera": {
+ "errors": {
+ "missingPermission": "இந்தப் பயன்பாடு மற்றொரு சாதனத்தின் QR குறியீட்டை ஸ்கேன் செய்ய கேமராவைப் பயன்படுத்துகிறது."
+ },
+ "allowAccess": "கேமராவை அணுக அனுமதிக்கவும்"
+ },
+ "errors": {
+ "genericError": "ஏதோ தவறு நடந்துவிட்டது. சிறிது நேரம் கழித்து மீண்டும் முயற்சிக்கவும்!"
+ },
+ "clipboard": {
+ "copy": "நகலெடுக்கவும்",
+ "copied": "நகலெடுக்கப்பட்டது"
+ },
+ "biometricPopup": {
+ "title": "பயன்பாட்டைத் திறக்கவும்",
+ "description": "பயன்பாட்டைத் திறக்க கைரேகையைப் பயன்படுத்தவும்"
+ }
+ }
+}
diff --git a/machines/QrLoginMachine.ts b/machines/QrLoginMachine.ts
index 501e347d..42dd9a8e 100644
--- a/machines/QrLoginMachine.ts
+++ b/machines/QrLoginMachine.ts
@@ -1,11 +1,10 @@
import {
ActorRefFrom,
assign,
- ErrorPlatformEvent,
EventFrom,
send,
- StateFrom,
sendParent,
+ StateFrom,
} from 'xstate';
import { createModel } from 'xstate/lib/model';
import { AppServices } from '../shared/GlobalContext';
@@ -13,8 +12,15 @@ import { MY_VCS_STORE_KEY } from '../shared/constants';
import { StoreEvents } from './store';
import { linkTransactionResponse, VC } from '../types/vc';
import { request } from '../shared/request';
-import { getJwt } from '../shared/cryptoutil/cryptoUtil';
-import { getPrivateKey } from '../shared/keystore/SecureKeystore';
+import {
+ getJwt,
+ isCustomSecureKeystore,
+} from '../shared/cryptoutil/cryptoUtil';
+import {
+ getBindingCertificateConstant,
+ getPrivateKey,
+} from '../shared/keystore/SecureKeystore';
+import i18n from '../i18n';
const model = createModel(
{
@@ -22,6 +28,7 @@ const model = createModel(
selectedVc: {} as VC,
linkCode: '',
myVcs: [] as string[],
+ thumbprint: '',
linkTransactionResponse: {} as linkTransactionResponse,
authFactors: [],
authorizeScopes: null,
@@ -144,7 +151,7 @@ export const qrLoginMachine =
faceAuth: {
on: {
FACE_VALID: {
- target: 'sendingAuthenticate',
+ target: 'requestConsent',
},
FACE_INVALID: {
target: 'invalidIdentity',
@@ -182,7 +189,7 @@ export const qrLoginMachine =
requestConsent: {
on: {
CONFIRM: {
- target: 'sendingConsent',
+ target: 'loadingThumbprint',
},
TOGGLE_CONSENT_CLAIM: {
actions: 'setConsentClaims',
@@ -194,6 +201,15 @@ export const qrLoginMachine =
},
},
},
+ loadingThumbprint: {
+ entry: 'loadThumbprint',
+ on: {
+ STORE_RESPONSE: {
+ actions: 'setThumbprint',
+ target: 'sendingConsent',
+ },
+ },
+ },
sendingConsent: {
invoke: {
src: 'sendConsent',
@@ -237,6 +253,20 @@ export const qrLoginMachine =
myVcs: (_context, event) => (event.response || []) as string[],
}),
+ loadThumbprint: send(
+ (context) =>
+ StoreEvents.GET(
+ getBindingCertificateConstant(
+ context.selectedVc.walletBindingResponse?.walletBindingId
+ )
+ ),
+ { to: (context) => context.serviceRefs.store }
+ ),
+ setThumbprint: assign({
+ thumbprint: (_context, event) => {
+ return (event.response || '') as string;
+ },
+ }),
resetLinkTransactionId: model.assign({
linkTransactionId: () => '',
}),
@@ -286,7 +316,9 @@ export const qrLoginMachine =
SetErrorMessage: assign({
errorMessage: (context, event) =>
- (event as ErrorPlatformEvent).data.message,
+ i18n.t(`errors.genericError`, {
+ ns: 'common',
+ }),
}),
setConsentClaims: assign({
@@ -311,7 +343,7 @@ export const qrLoginMachine =
linkTransaction: async (context) => {
const response = await request(
'POST',
- '/v1/idp/linked-authorization/link-transaction',
+ '/v1/esignet/linked-authorization/link-transaction',
{
requestTime: String(new Date().toISOString()),
request: {
@@ -323,20 +355,24 @@ export const qrLoginMachine =
},
sendAuthenticate: async (context) => {
- var privateKey = await getPrivateKey(
- context.selectedVc.walletBindingResponse?.walletBindingId
- );
+ let privateKey;
+
+ if (!isCustomSecureKeystore()) {
+ privateKey = await getPrivateKey(
+ context.selectedVc.walletBindingResponse?.walletBindingId
+ );
+ }
+
var walletBindingResponse = context.selectedVc.walletBindingResponse;
var jwt = await getJwt(
privateKey,
context.selectedVc.id,
- walletBindingResponse?.keyId,
- walletBindingResponse?.thumbprint
+ context.thumbprint
);
const response = await request(
'POST',
- '/v1/idp/linked-authorization/authenticate',
+ '/v1/esignet/linked-authorization/authenticate',
{
requestTime: String(new Date().toISOString()),
request: {
@@ -356,13 +392,46 @@ export const qrLoginMachine =
},
sendConsent: async (context) => {
+ let privateKey;
+ if (!isCustomSecureKeystore()) {
+ privateKey = await getPrivateKey(
+ context.selectedVc.walletBindingResponse?.walletBindingId
+ );
+ }
+
+ const jwt = await getJwt(
+ privateKey,
+ context.selectedVc.id,
+ context.thumbprint
+ );
+
const response = await request(
'POST',
- '/v1/idp/linked-authorization/consent',
+ '/v1/esignet/linked-authorization/authenticate',
{
requestTime: String(new Date().toISOString()),
request: {
- linkedTransactionId: context.linkedTransactionId,
+ linkedTransactionId: context.linkTransactionId,
+ individualId: context.selectedVc.id,
+ challengeList: [
+ {
+ authFactorType: 'WLA',
+ challenge: jwt,
+ format: 'jwt',
+ },
+ ],
+ },
+ }
+ );
+ var linkedTrnId = response.response.linkedTransactionId;
+
+ const resp = await request(
+ 'POST',
+ '/v1/esignet/linked-authorization/consent',
+ {
+ requestTime: String(new Date().toISOString()),
+ request: {
+ linkedTransactionId: linkedTrnId,
acceptedClaims: context.essentialClaims.concat(
context.selectedVoluntaryClaims
),
@@ -370,7 +439,7 @@ export const qrLoginMachine =
},
}
);
- console.log(response.response.linkedTransactionId);
+ console.log(resp.response.linkedTransactionId);
},
},
}
diff --git a/machines/QrLoginMachine.typegen.ts b/machines/QrLoginMachine.typegen.ts
index 7b0bf787..6bb013c7 100644
--- a/machines/QrLoginMachine.typegen.ts
+++ b/machines/QrLoginMachine.typegen.ts
@@ -46,6 +46,7 @@ export interface Typegen0 {
expandLinkTransResp: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
forwardToParent: 'DISMISS';
loadMyVcs: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
+ loadThumbprint: 'CONFIRM';
resetLinkTransactionId: 'GET';
resetSelectedVoluntaryClaims: 'GET';
setClaims: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
@@ -54,14 +55,15 @@ export interface Typegen0 {
setMyVcs: 'STORE_RESPONSE';
setScanData: 'GET';
setSelectedVc: 'SELECT_VC';
+ setThumbprint: 'STORE_RESPONSE';
setlinkTransactionResponse: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
};
'eventsCausingDelays': {};
'eventsCausingGuards': {};
'eventsCausingServices': {
linkTransaction: 'GET';
- sendAuthenticate: 'FACE_VALID';
- sendConsent: 'CONFIRM';
+ sendAuthenticate: never;
+ sendConsent: 'STORE_RESPONSE';
};
'matchesStates':
| 'ShowError'
@@ -70,6 +72,7 @@ export interface Typegen0 {
| 'invalidIdentity'
| 'linkTransaction'
| 'loadMyVcs'
+ | 'loadingThumbprint'
| 'requestConsent'
| 'sendingAuthenticate'
| 'sendingConsent'
diff --git a/machines/activityLog.ts b/machines/activityLog.ts
index 534fd702..ba0cedb2 100644
--- a/machines/activityLog.ts
+++ b/machines/activityLog.ts
@@ -124,13 +124,17 @@ export type ActivityLogType =
| 'VC_RECEIVED_NOT_SAVED'
| 'VC_DELETED'
| 'VC_DOWNLOADED'
+ | 'VC_UPDATED'
| 'VC_REVOKED'
| 'VC_SHARED_WITH_VERIFICATION_CONSENT'
| 'VC_RECEIVED_WITH_PRESENCE_VERIFIED'
| 'VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED'
| 'PRESENCE_VERIFIED_AND_VC_SHARED'
| 'PRESENCE_VERIFICATION_FAILED'
- | 'QRLOGIN_SUCCESFULL';
+ | 'QRLOGIN_SUCCESFULL'
+ | 'WALLET_BINDING_SUCCESSFULL'
+ | 'WALLET_BINDING_FAILURE'
+ | 'VC_REMOVED';
type State = StateFrom;
diff --git a/machines/app.ts b/machines/app.ts
index 8d19a291..cd35a0e3 100644
--- a/machines/app.ts
+++ b/machines/app.ts
@@ -9,39 +9,58 @@ import { EventFrom, spawn, StateFrom, send, assign, AnyState } from 'xstate';
import { createModel } from 'xstate/lib/model';
import { authMachine, createAuthMachine } from './auth';
import { createSettingsMachine, settingsMachine } from './settings';
-import { storeMachine } from './store';
+import { StoreEvents, storeMachine } from './store';
import { createVcMachine, vcMachine } from './vc';
import { createActivityLogMachine, activityLogMachine } from './activityLog';
-import { createRequestMachine, requestMachine } from './request';
-import { createScanMachine, scanMachine } from './scan';
+import {
+ createRequestMachine,
+ requestMachine,
+} from './bleShare/request/requestMachine';
+import { createScanMachine, scanMachine } from './bleShare/scan/scanMachine';
import { createRevokeMachine, revokeVidsMachine } from './revoke';
-
import { pure, respond } from 'xstate/lib/actions';
import { AppServices } from '../shared/GlobalContext';
import { request } from '../shared/request';
+import {
+ changeCrendetialRegistry,
+ SETTINGS_STORE_KEY,
+} from '../shared/constants';
+import { MIMOTO_HOST } from 'react-native-dotenv';
const model = createModel(
{
info: {} as AppInfo,
backendInfo: {} as BackendInfo,
serviceRefs: {} as AppServices,
+ isReadError: false,
+ isDecryptError: false,
+ isKeyInvalidateError: false,
},
{
events: {
ACTIVE: () => ({}),
INACTIVE: () => ({}),
+ ERROR: () => ({}),
+ DECRYPT_ERROR: () => ({}),
+ DECRYPT_ERROR_DISMISS: () => ({}),
+ KEY_INVALIDATE_ERROR: () => ({}),
OFFLINE: () => ({}),
ONLINE: (networkType: NetInfoStateType) => ({ networkType }),
REQUEST_DEVICE_INFO: () => ({}),
READY: (data?: unknown) => ({ data }),
APP_INFO_RECEIVED: (info: AppInfo) => ({ info }),
BACKEND_INFO_RECEIVED: (info: BackendInfo) => ({ info }),
+ STORE_RESPONSE: (response: unknown) => ({ response }),
+ RESET_KEY_INVALIDATE_ERROR_DISMISS: () => ({}),
},
}
);
+export const APP_EVENTS = model.events;
+
export const appMachine = model.createMachine(
{
+ /** @xstate-layout N4IgpgJg5mDOIC5QEMAOqB0BLAdlgLhrPgPYBOYAxAEoCiAggCICaA2gAwC6ioqJsBLCRw8QAD0QBmdgE4MMgIwAmSaoDsADmkb2agDQgAnoiUAWJRnNqZayVvYKArDdMBfVwbSZcBIqQqUtNTUAPLUHNxIIHwC+EIiURIICpJypgBsaqaOSjmOqfmmBsbJjuzyaimaMpJq7BqOOe6e6Nh4hLBgZABuWADGcDQMLBGiMYLCokmZ6RiSSro5NQrsjcUm5pZK1rb2Ti7NIF5tvn0UEGA4ccgANtRgUFjEZIaUAMoAKmG0APp0bwAFEIAOTetFGUXGcUmiUQCgU6VMFW0tVkOXY6XWCCUCjkakqBNMMl0ZjcHiOrR8hFwADMSJR6ACAT8AJLAgBiIT+tAAwrQWQA1WiMCG8fgTBKgJIIjJzdRqRGmDQEjRYnF4gkKLLEtSkw7HKkYC69HB0ygAIXoPIA0rRgYxWRyuXQ+YLhaLouLoZLxCZlI55DjTJJ0jV0vlJGrcRh8VqtUSSaYyS1MBRkBBXnQAIoAVVonx+jFoApZfMdnI9UPiUxM9Rj6URGmJMh0Zg0mKMiEc6Q0GA0GmyPd180kyYpqbA6cMGDpfQArrAGTyPm7K17q7Dkroscre+l2KknAoB8qbPrWmmMzOSPPF2yrSuhWvYhupXDt52EDIbBhGnVJN27CyA2SjnhOU4YDgYD4AA7uQADWlAggAMmy4JcGM64wm+W76J+yhEpYaiOKYGL4jI+4hmBGCXtOUGwQhSHsuyqHAuhkRii+2G+rhWIpD2WwNNsuLdjI7jkjgJAXPAUReJhXE+kkAC0tRYkpZgYEBWnaTpajUVS8kSjW2IyFi6SSJYDS2FqjgaPCMi2fp7R+OQYCGd6xn4mqGKWKimimMoTaOLqTm+J0PT9HA7mvjx5gWeYChJmYEbth2JQLLMwZ1P5gUOSF5IGs5ZyQJc1x3A8Tz4C80XcUk1R9koLbpAiDghgoUZpNImgkSsGhmLUoXUqaJA1YpcJJrM4aVCkShaDI5hFJ+6q+bouz4tIqgaINRpgCadKjcZx7pBYDakZoo6OCkjgdSt1ihkmF1UQVF6ThmB2bvCZmqBgIGaPU5FONRtHXre704c4WK6goGCJQOs2rD2Ohic94FXrOC4YH0AAWYB9PBuBQGDPHwtDWoLDUtn1LN35YjUcgYhRiUNhiTbIymNGvdO6OwBgyB9HE3RuZCWFjdipE-YopE1O2f12DujQ-WR0jNUBl2OEDnMgxjuB8wLQucUZm5mOUoaJbIdiZDocufi4v7OA0KxKM1tRbSjHMQfRcFkPBRNJBD+GyBYDjfri4YtRkGse9BXvwZjON4wTvvvnhJQpLI8gBSsx2NAFdiR1ensIRgwg3Lg+uegpxkqBYo66ko9e5MoZh8fXmWaA3CymPiTRu8Dhfe8XNI0qXUFJ9i8xzF3HeN-Xi2pxdvkpOYx31M16Tia4QA */
predictableActionArguments: true,
preserveActionOrder: true,
tsTypes: {} as import('./app.typegen').Typegen0,
@@ -51,6 +70,22 @@ export const appMachine = model.createMachine(
},
id: 'app',
initial: 'init',
+ on: {
+ DECRYPT_ERROR: {
+ actions: ['setIsDecryptError'],
+ },
+ DECRYPT_ERROR_DISMISS: {
+ actions: ['unsetIsDecryptError'],
+ },
+ KEY_INVALIDATE_ERROR: {
+ actions: ['updateKeyInvalidateError'],
+ target: 'waiting',
+ },
+ RESET_KEY_INVALIDATE_ERROR_DISMISS: {
+ actions: ['resetKeyInvalidateError'],
+ target: 'init',
+ },
+ },
states: {
init: {
initial: 'store',
@@ -58,13 +93,32 @@ export const appMachine = model.createMachine(
store: {
entry: ['spawnStoreActor', 'logStoreEvents'],
on: {
- READY: 'services',
+ READY: {
+ actions: [
+ 'unsetIsReadError',
+ 'unsetIsDecryptError',
+ 'resetKeyInvalidateError',
+ ],
+ target: 'services',
+ },
+ ERROR: {
+ actions: ['setIsReadError', 'updateKeyInvalidateError'],
+ },
},
},
services: {
entry: ['spawnServiceActors', 'logServiceEvents'],
on: {
- READY: 'info',
+ READY: 'credentialRegistry',
+ },
+ },
+ credentialRegistry: {
+ entry: ['loadCredentialRegistryHostFromStorage'],
+ on: {
+ STORE_RESPONSE: {
+ actions: ['loadCredentialRegistryInConstants'],
+ target: 'info',
+ },
},
},
info: {
@@ -140,6 +194,7 @@ export const appMachine = model.createMachine(
},
},
},
+ waiting: {},
},
},
{
@@ -149,6 +204,30 @@ export const appMachine = model.createMachine(
send({ ...event, type: `APP_${event.type}` }, { to: serviceRef })
)
),
+ setIsReadError: assign({
+ isReadError: true,
+ }),
+ setIsDecryptError: assign({
+ isDecryptError: true,
+ }),
+ unsetIsDecryptError: assign({
+ isDecryptError: false,
+ }),
+ unsetIsReadError: assign({
+ isReadError: false,
+ }),
+
+ updateKeyInvalidateError: model.assign({
+ isKeyInvalidateError: (_, event) => {
+ if (event.type === 'KEY_INVALIDATE_ERROR') {
+ return true;
+ }
+ },
+ }),
+
+ resetKeyInvalidateError: model.assign({
+ isKeyInvalidateError: false,
+ }),
requestDeviceInfo: respond((context) => ({
type: 'RECEIVE_DEVICE_INFO',
@@ -199,10 +278,12 @@ export const appMachine = model.createMachine(
scanMachine.id
);
- serviceRefs.request = spawn(
- createRequestMachine(serviceRefs),
- requestMachine.id
- );
+ if (Platform.OS === 'android') {
+ serviceRefs.request = spawn(
+ createRequestMachine(serviceRefs),
+ requestMachine.id
+ );
+ }
serviceRefs.revoke = spawn(
createRevokeMachine(serviceRefs),
@@ -220,7 +301,11 @@ export const appMachine = model.createMachine(
context.serviceRefs.settings.subscribe(logState);
context.serviceRefs.activityLog.subscribe(logState);
context.serviceRefs.scan.subscribe(logState);
- context.serviceRefs.request.subscribe(logState);
+
+ if (Platform.OS === 'android') {
+ context.serviceRefs.request.subscribe(logState);
+ }
+
context.serviceRefs.revoke.subscribe(logState);
}
},
@@ -232,6 +317,21 @@ export const appMachine = model.createMachine(
setBackendInfo: model.assign({
backendInfo: (_, event) => event.info,
}),
+
+ loadCredentialRegistryHostFromStorage: send(
+ StoreEvents.GET(SETTINGS_STORE_KEY),
+ {
+ to: (context) => context.serviceRefs.store,
+ }
+ ),
+
+ loadCredentialRegistryInConstants: (_context, event) => {
+ changeCrendetialRegistry(
+ !event.response?.credentialRegistry
+ ? MIMOTO_HOST
+ : event.response?.credentialRegistry
+ );
+ },
},
services: {
@@ -311,6 +411,7 @@ interface AppInfo {
deviceId: string;
deviceName: string;
}
+
interface BackendInfo {
application: {
name: string;
@@ -367,3 +468,15 @@ export function logState(state: AnyState) {
`
);
}
+
+export function selectIsReadError(state: State) {
+ return state.context.isReadError;
+}
+
+export function selectIsDecryptError(state: State) {
+ return state.context.isDecryptError;
+}
+
+export function selectIsKeyInvalidateError(state: State) {
+ return state.context.isKeyInvalidateError;
+}
diff --git a/machines/app.typegen.ts b/machines/app.typegen.ts
index 35298387..a65a1c20 100644
--- a/machines/app.typegen.ts
+++ b/machines/app.typegen.ts
@@ -19,24 +19,33 @@ export interface Typegen0 {
};
'eventsCausingActions': {
forwardToServices: 'ACTIVE' | 'INACTIVE' | 'OFFLINE' | 'ONLINE';
+ loadCredentialRegistryHostFromStorage: 'READY';
+ loadCredentialRegistryInConstants: 'STORE_RESPONSE';
logServiceEvents: 'READY';
logStoreEvents: 'xstate.init';
requestDeviceInfo: 'REQUEST_DEVICE_INFO';
+ resetKeyInvalidateError: 'READY' | 'RESET_KEY_INVALIDATE_ERROR_DISMISS';
setAppInfo: 'APP_INFO_RECEIVED';
setBackendInfo: 'BACKEND_INFO_RECEIVED';
+ setIsDecryptError: 'DECRYPT_ERROR';
+ setIsReadError: 'ERROR';
spawnServiceActors: 'READY';
spawnStoreActor: 'xstate.init';
+ unsetIsDecryptError: 'DECRYPT_ERROR_DISMISS' | 'READY';
+ unsetIsReadError: 'READY';
+ updateKeyInvalidateError: 'ERROR' | 'KEY_INVALIDATE_ERROR';
};
'eventsCausingDelays': {};
'eventsCausingGuards': {};
'eventsCausingServices': {
checkFocusState: 'BACKEND_INFO_RECEIVED';
checkNetworkState: 'BACKEND_INFO_RECEIVED';
- getAppInfo: 'READY';
+ getAppInfo: 'STORE_RESPONSE';
getBackendInfo: 'APP_INFO_RECEIVED';
};
'matchesStates':
| 'init'
+ | 'init.credentialRegistry'
| 'init.devinfo'
| 'init.info'
| 'init.services'
@@ -51,7 +60,7 @@ export interface Typegen0 {
| 'ready.network.offline'
| 'ready.network.online'
| {
- init?: 'devinfo' | 'info' | 'services' | 'store';
+ init?: 'credentialRegistry' | 'devinfo' | 'info' | 'services' | 'store';
ready?:
| 'focus'
| 'network'
diff --git a/machines/auth.ts b/machines/auth.ts
index 98447c06..3ed6db77 100644
--- a/machines/auth.ts
+++ b/machines/auth.ts
@@ -1,16 +1,22 @@
import { init } from 'mosip-inji-face-sdk';
-import { ContextFrom, EventFrom, send, StateFrom } from 'xstate';
+import { assign, ContextFrom, EventFrom, send, StateFrom } from 'xstate';
import { createModel } from 'xstate/lib/model';
-import getAllConfigurations from '../shared/commonprops/commonProps';
+import getAllConfigurations, {
+ downloadModel,
+} from '../shared/commonprops/commonProps';
import { AppServices } from '../shared/GlobalContext';
import { StoreEvents, StoreResponseEvent } from './store';
+import { generateSecureRandom } from 'react-native-securerandom';
+import binaryToBase64 from 'react-native/Libraries/Utilities/binaryToBase64';
const model = createModel(
{
serviceRefs: {} as AppServices,
passcode: '',
+ passcodeSalt: '',
biometrics: '',
canUseBiometrics: false,
+ selectLanguage: false,
},
{
events: {
@@ -19,6 +25,8 @@ const model = createModel(
LOGOUT: () => ({}),
LOGIN: () => ({}),
STORE_RESPONSE: (response?: unknown) => ({ response }),
+ SELECT: () => ({}),
+ NEXT: () => ({}),
},
}
);
@@ -60,21 +68,42 @@ export const authMachine = model.createMachine(
},
checkingAuth: {
always: [
+ { cond: 'hasLanguageset', target: 'languagesetup' },
{ cond: 'hasPasscodeSet', target: 'unauthorized' },
{ cond: 'hasBiometricSet', target: 'unauthorized' },
{ target: 'settingUp' },
],
},
+ languagesetup: {
+ on: {
+ SELECT: {
+ target: 'introSlider',
+ },
+ },
+ },
+ introSlider: {
+ invoke: {
+ src: 'generatePasscodeSalt',
+ onDone: {
+ actions: ['setPasscodeSalt', 'storeContext'],
+ },
+ },
+ on: {
+ NEXT: {
+ target: 'settingUp',
+ },
+ },
+ },
settingUp: {
on: {
SETUP_PASSCODE: {
target: 'authorized',
- actions: ['setPasscode', 'storeContext'],
+ actions: ['setPasscode', 'setLanguage', 'storeContext'],
},
SETUP_BIOMETRICS: {
// Note! dont authorized yet we need to setup passcode too as discuss
// target: 'authorized',
- actions: ['setBiometrics', 'storeContext'],
+ actions: ['setBiometrics', 'setLanguage', 'storeContext'],
},
},
},
@@ -127,21 +156,25 @@ export const authMachine = model.createMachine(
setBiometrics: model.assign({
biometrics: (_, event: SetupBiometricsEvent) => event.biometrics,
}),
+
+ setLanguage: assign({
+ selectLanguage: (context) => true,
+ }),
+
+ setPasscodeSalt: assign({
+ passcodeSalt: (context, event) => {
+ return event.data as string;
+ },
+ }),
},
services: {
- downloadFaceSdkModel: () => async () => {
- var injiProp = null;
- try {
- var injiProp = await getAllConfigurations();
- const resp: string =
- injiProp != null ? injiProp.faceSdkModelUrl : null;
- if (resp != null) {
- init(resp, false);
- }
- } catch (error) {
- console.log(error);
- }
+ downloadFaceSdkModel: () => () => {
+ downloadModel();
+ },
+ generatePasscodeSalt: () => async (context) => {
+ const randomBytes = await generateSecureRandom(16);
+ return binaryToBase64(randomBytes) as string;
},
},
@@ -154,6 +187,9 @@ export const authMachine = model.createMachine(
hasBiometricSet: (context) => {
return context.biometrics !== '' && context.passcode !== '';
},
+ hasLanguageset: (context) => {
+ return !context.selectLanguage;
+ },
},
}
);
@@ -171,6 +207,10 @@ export function selectPasscode(state: State) {
return state.context.passcode;
}
+export function selectPasscodeSalt(state: State) {
+ return state.context.passcodeSalt;
+}
+
export function selectBiometrics(state: State) {
return state.context.biometrics;
}
@@ -190,3 +230,10 @@ export function selectUnauthorized(state: State) {
export function selectSettingUp(state: State) {
return state.matches('settingUp');
}
+
+export function selectLanguagesetup(state: State) {
+ return state.matches('languagesetup');
+}
+export function selectIntroSlider(state: State) {
+ return state.matches('introSlider');
+}
diff --git a/machines/auth.typegen.ts b/machines/auth.typegen.ts
index 33448776..3843a6d7 100644
--- a/machines/auth.typegen.ts
+++ b/machines/auth.typegen.ts
@@ -9,10 +9,16 @@ export interface Typegen0 {
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
+ 'done.invoke.auth.introSlider:invocation[0]': {
+ type: 'done.invoke.auth.introSlider:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
'xstate.init': { type: 'xstate.init' };
};
'invokeSrcNameMap': {
downloadFaceSdkModel: 'done.invoke.auth.authorized:invocation[0]';
+ generatePasscodeSalt: 'done.invoke.auth.introSlider:invocation[0]';
};
'missingImplementations': {
actions: never;
@@ -24,26 +30,33 @@ export interface Typegen0 {
requestStoredContext: 'xstate.init';
setBiometrics: 'SETUP_BIOMETRICS';
setContext: 'STORE_RESPONSE';
+ setLanguage: 'SETUP_BIOMETRICS' | 'SETUP_PASSCODE';
setPasscode: 'SETUP_PASSCODE';
+ setPasscodeSalt: 'done.invoke.auth.introSlider:invocation[0]';
storeContext:
| 'SETUP_BIOMETRICS'
| 'SETUP_PASSCODE'
| 'STORE_RESPONSE'
- | 'done.invoke.auth.authorized:invocation[0]';
+ | 'done.invoke.auth.authorized:invocation[0]'
+ | 'done.invoke.auth.introSlider:invocation[0]';
};
'eventsCausingDelays': {};
'eventsCausingGuards': {
hasBiometricSet: '';
hasData: 'STORE_RESPONSE';
+ hasLanguageset: '';
hasPasscodeSet: '';
};
'eventsCausingServices': {
downloadFaceSdkModel: 'LOGIN' | 'SETUP_PASSCODE';
+ generatePasscodeSalt: 'SELECT';
};
'matchesStates':
| 'authorized'
| 'checkingAuth'
| 'init'
+ | 'introSlider'
+ | 'languagesetup'
| 'savingDefaults'
| 'settingUp'
| 'unauthorized';
diff --git a/machines/bleShare/commonSelectors.ts b/machines/bleShare/commonSelectors.ts
new file mode 100644
index 00000000..3ad78764
--- /dev/null
+++ b/machines/bleShare/commonSelectors.ts
@@ -0,0 +1,74 @@
+import { StateFrom } from 'xstate';
+import { scanMachine } from './scan/scanMachine';
+import { requestMachine } from './request/requestMachine';
+
+type State = StateFrom;
+
+export function selectIsCancelling(state: State) {
+ return state.matches('cancelling');
+}
+
+export function selectIsReviewing(state: State) {
+ return state.matches('reviewing');
+}
+
+export function selectIsAccepted(state: State) {
+ return state.matches('reviewing.accepted');
+}
+
+export function selectIsRejected(state: State) {
+ return state.matches('reviewing.rejected');
+}
+
+export function selectIsVerifyingIdentity(state: State) {
+ return state.matches('reviewing.verifyingIdentity');
+}
+
+export function selectIsInvalidIdentity(state: State) {
+ return state.matches('reviewing.invalidIdentity');
+}
+
+export function selectIsDisconnected(state: State) {
+ return state.matches('disconnected');
+}
+
+export function selectIsBluetoothDenied(state: State) {
+ return state.matches('bluetoothDenied');
+}
+
+export function selectBleError(state: State) {
+ return state.context.bleError;
+}
+
+// TODO: Remove these selectors and respective UI code once discussed with team
+export function selectIsExchangingDeviceInfo() {
+ return false;
+}
+
+export function selectIsExchangingDeviceInfoTimeout() {
+ return false;
+}
+
+export function selectIsOffline() {
+ return false;
+}
+
+export function selectIsHandlingBleError(state: State) {
+ return state.matches('handlingBleError');
+}
+
+export function selectReadyForBluetoothStateCheck(state: State) {
+ return state.context.readyForBluetoothStateCheck;
+}
+
+export function selectIsNearByDevicesPermissionDenied(state: State) {
+ return state.matches('nearByDevicesPermissionDenied');
+}
+
+export function selectIsBluetoothPermissionDenied(state: State) {
+ return state.matches('bluetoothPermissionDenied');
+}
+
+export function selectIsStartPermissionCheck(state: State) {
+ return state.matches('startPermissionCheck');
+}
diff --git a/machines/bleShare/request/requestMachine.ts b/machines/bleShare/request/requestMachine.ts
new file mode 100644
index 00000000..ee66e005
--- /dev/null
+++ b/machines/bleShare/request/requestMachine.ts
@@ -0,0 +1,818 @@
+import tuvali from 'react-native-tuvali';
+import BluetoothStateManager from 'react-native-bluetooth-state-manager';
+import { EmitterSubscription, Linking, Platform } from 'react-native';
+import {
+ checkMultiple,
+ PERMISSIONS,
+ requestMultiple,
+ RESULTS,
+} from 'react-native-permissions';
+import { assign, EventFrom, send, StateFrom } from 'xstate';
+import { createModel } from 'xstate/lib/model';
+import { DeviceInfo } from '../../../components/DeviceInfoList';
+import { getDeviceNameSync } from 'react-native-device-info';
+import { StoreEvents } from '../../store';
+import { VC } from '../../../types/vc';
+import { AppServices } from '../../../shared/GlobalContext';
+import {
+ RECEIVED_VCS_STORE_KEY,
+ VC_ITEM_STORE_KEY,
+} from '../../../shared/constants';
+import { ActivityLogEvents, ActivityLogType } from '../../activityLog';
+import { VcEvents } from '../../vc';
+import { subscribe } from '../../../shared/openIdBLE/verifierEventHandler';
+import { log } from 'xstate/lib/actions';
+import { VerifierDataEvent } from 'react-native-tuvali/src/types/events';
+import { BLEError } from '../types';
+import Storage from '../../../shared/storage';
+// import { verifyPresentation } from '../shared/vcjs/verifyPresentation';
+
+const { verifier, EventTypes, VerificationStatus } = tuvali;
+
+const model = createModel(
+ {
+ serviceRefs: {} as AppServices,
+ senderInfo: {} as DeviceInfo,
+ receiverInfo: {} as DeviceInfo,
+ incomingVc: {} as VC,
+ openId4VpUri: '',
+ bleError: {} as BLEError,
+ loggers: [] as EmitterSubscription[],
+ receiveLogType: '' as ActivityLogType,
+ readyForBluetoothStateCheck: false,
+ },
+ {
+ events: {
+ ACCEPT: () => ({}),
+ ACCEPT_AND_VERIFY: () => ({}),
+ GO_TO_RECEIVED_VC_TAB: () => ({}),
+ REJECT: () => ({}),
+ CANCEL: () => ({}),
+ RESET: () => ({}),
+ DISMISS: () => ({}),
+ VC_RECEIVED: (vc: VC) => ({ vc }),
+ ADV_STARTED: (openId4VpUri: string) => ({ openId4VpUri }),
+ CONNECTED: () => ({}),
+ DISCONNECT: () => ({}),
+ BLE_ERROR: (bleError: BLEError) => ({ bleError }),
+ EXCHANGE_DONE: (senderInfo: DeviceInfo) => ({ senderInfo }),
+ SCREEN_FOCUS: () => ({}),
+ SCREEN_BLUR: () => ({}),
+ BLUETOOTH_STATE_ENABLED: () => ({}),
+ BLUETOOTH_STATE_DISABLED: () => ({}),
+ NEARBY_ENABLED: () => ({}),
+ NEARBY_DISABLED: () => ({}),
+ STORE_READY: () => ({}),
+ STORE_RESPONSE: (response: unknown) => ({ response }),
+ STORE_ERROR: (error: Error) => ({ error }),
+ RECEIVE_DEVICE_INFO: (info: DeviceInfo) => ({ info }),
+ RECEIVED_VCS_UPDATED: () => ({}),
+ VC_RESPONSE: (response: unknown) => ({ response }),
+ GOTO_SETTINGS: () => ({}),
+ APP_ACTIVE: () => ({}),
+ FACE_VALID: () => ({}),
+ FACE_INVALID: () => ({}),
+ RETRY_VERIFICATION: () => ({}),
+ },
+ }
+);
+export const RequestEvents = model.events;
+
+export const requestMachine =
+ /** @xstate-layout N4IgpgJg5mDOIC5QCcwEcCucAuBiAygMIBKAoqQHID6AQgDICqxA2gAwC6ioADgPawBLbAN4A7LiAAeiACwAmADQgAnogCMADlYyAdBrms5MgGynjAZlYbzAXxtLUmHARLlqAMQDyhBvjackED5BYTEJaQR5JVUEOQBWIx04gE41OVTrAHZtYzsHdCxYPHwAdQBJABVCAAkqAAViTwrvTzp-CWChEXFAiKiVRHjMuJ1WOJkNTONkzMzklLyQR0K8elIqUmJGlg4O-i6w3tlFAdiNGV1MmWG1C9Y1NXN9ReXnMnxSCvbAztCe0D6JxiRiuOjSs1YpmSxketnsSwKOB0AGMABZgZEAawoYAAhsgAEbKOpgZAAWwEsEEYhR6KxAlEUFwFFIAEFiDQAJobCistYAEW+PH2f3C6lYMySJnOGmsyXMCWig2mcil2WsKTkjzGL0RRVpGOxeMJxNJFKp3QN9MZzLZHO5-LK+D5dFIgt2PxF3TFCDiph0sw0xjimi1cmMMmSSti42SejUyTk6TUKWShjiuqc+rRhpx+KJJPJlOpoh0ryKDKZLPZXJ5LrdQqCXsOAPFkvGxhlcoVQMGft0kM010s5hmU0zKytRvzpqLFpp5eENur9qojudAsbv29RwQaglmSlnYm3cVpzkTzUOnMcnOD3lCSsMgnSJz1qgNAANlhsLxeNhUXwUkADcBGRMAp0rXB6AYT5PCaWpKHrd0AmFEId1bPdjEMME-TkWYLFSC5MmjfDrlGNQrkyG9A0hZ94UXSDGS-H8-wAoDkFA8CmKZGC4IQtcnWQrdm3+KR1Gw1UU2MfCplHW5rlI7DdFvaFNHOOI4kyc4X2zOlMUrFiwF-f9AJAsCIMXKC+OaASkM3D00IOMSIgMKZRkjOJzFuVgrhkJTNCSG9vOSWVDGsXTsB4oyTPY8zuKsm0bPgipanXYTHKbdCW3E2IZE00ZzCecMNDwhVSMjQ8tDGfDLFC-DIui79jLYszOIsnQwFEXECU-SBcBE7KXMGfKRlYIr9E7Mq4lIq4r1qtJzAuOJzkhRretY0z+S6gR+oAcSaTwqA+CoKjKCg9r8TLtxyvoivMHRw1vJbzEyRbzAq7QdGHLVZU0YN5ka0RjRoWdzRLbbRF2iBcAO5pjs+M6Lqu1Csucn1KNHa8Hk0YZZjDKNz1vDRRnufCLy8owNEa5E+vxStCDEYHkT+XBCE8CgWUIM6ObXUh8AqRpOQba7RJ9Jb8p0Y9xj9YxsgmWbHm+i8THyh8g0yGm6eQBmmYxVnJCKXFsAg3EADMTeQAAKfl+cFzxuTOgBZUhPAYCoAEpcEY2njV10Rmb+Qb0d3CWRml-LTHljRZosPRJm0GYJeSGZGoAd1xLpGXcXhkEZgP9e6NmOa5ioRdRm7hoQcxpj0AjHn0a5MnDGbTle7zrwjZv7gTDQ1HTzOlygHO871lmi-XdnOdIbng9FUPa8mKYG5BZvg2jGRWAla8ZAeEM-M0ZJGu4VBuHpxkKl4UhJDRXFGTAMpRDN3hcDIQhSDKAA1dZbc-sp36oOdLwc8MK5VmIeZuqQtK7yejID6bd1RJGDBebQr0ZSNTADfVEd8oCVm2lxB+T8X6kAABo1FZBdH+HNSAgNuuoXse45AYKwTgvBYACGP2frgSeJcZ5fFFkNDGmkIHJHkH6NMag5YkQQZGPQXcDD3j7sw2+jI2EcKIToBkdRkC8CgKgKkuBDbYGNqbC2pIrZT1LmUXmztXbuy9oxTBKjcGMnwRZThvBNGiG0bo-RsBaFVweNkKWCZZgjniE8aMr1N5yLCktAw41AYMT1FFJx2DVGuPYe4jRwgyRgF4BgPAhAKHvzaAIkOmEUxaQDKI+I0x7hSKidMOMm8HhLRmLKUKA8s7D1zp-ZE3CnSWL4QEn0+gom3ivLUmYcQt7eRrnCfIWYooZx6SPfpuBP6ECoG-D+38UJ7EEbuFaIw5L3EMJIvu8pSJ+h0PKYKMJxgoNuN0oe6zkReJ8XouAsBDFGxNjoc2lsrb4GqOyc6e0qC2Ldp7b2KSdCrLeX0j5WidHfKpKM3cv0AxaT7kYJ4cst4MISZceQjxpgXFCoshEyyEWD0rO8nQuT8mFLZiU0gZSK5i13ImKJkj5oPAlPMeQYxKI0zvuBT8n4oKYsws3KJszdCUSDONNI8pJjUsYqgUCYA05QVZIQd+dR+FcqOXKvudygwzH3ONZMDDN6sG+hGJuVwipanoksyc2rdp6ptAao1FQqAUP5FQb+xAyjuE5LKsBFrQrTDenMu10Z9COq3o8Ne2kprU2SbS71uqoJkAAFIjPKfPc1UyrUJttakBh+5JHfTgUmBMMJ1WNTzb6pkxSKClOjREbSFb402pvDW6M0IRgzGhLMCYcCEgeppV6rJ+bGQ6GAqSAQZtlCVjKBALqwhsDKFwO4A16xP6sjoGUA5nozW5VuOcb6Vqx3pHSHLaMphLj4VmRKTSYx7htsXR2lda6N1bp3aIPdB6j0APOqe89l6nJltyvMB6K1SrRJ+uNaMKRdBqwWuquBf6dUAdXTrYDjJt27qEAertPbS2gIiLe7DD7kGJkndGKYjq5hb0MGmCUSYmE5oXYRysXjgK4mlRAcjYHKODPwE7J0KNDkVMQ15JIsovJ+WogYeBMRxgPRTlpW8b0ZLQIIz64TDJRPick+B1+nxiDcjDRG-+rIeYUF7YgURyG1Noc0xh04zTHrTGwgqOWd5+OeqRO24TxH12bsZJ-bguAIBiAghZ3gmJLLwqi8umLpGoAJYQGl5Extuj+Hc3ueJ8dxhwP3MvbyyaHiPS8uMai2lZnaVM0uqAgGSNxfy4l0kOjkA6G4J+Y2z9yRliy-+6LQG+sFaKyVsQZXaN0Iq-IKrFxvK+RhPV04pUSbZETNpN6aDNYCcizN5duJkTgW4EPAgzQyAbC2J4HYpqlMRH0AO61iaR2nBTBeAM+gEiiJORKTrAGbt3aHlN5ZlZiAYjAAIVdEB+m-K2Ts-mdQOYfHKwo5D+5vJ70uaVV9+FvohhMPuTeN5NKQ+E9DsA93hOJSgIj8CKPIDo82ds94OOKB47UB9hDrl7iE9VSTzsZPTgJCmfMZukxJFDDnVqq73Wmcs+XWz6+lIh4bIFm99Y-Pcc0NW1XIYqaDtNojPobTiAZKHnyrcGE2hbX04u-qbLGvbvM9h3k5ALioCP2RLwCk8WBmG+eybwXZuRd0cQFoH7Vbh1pGjJjOMKQ5Y1wsDeXyGZPdRW94C33Wvusn2Z11CACOkdc7R5Hp7xvsem-x1pK3K0bcTAvJhrUdyFeGeVyZwvU2hPXdL7DooudKwG8b1j-AAu8fm7GY1uNv3q1p4B52B6o0ImrVp+diLXv1cl5h-1dccn8AKavZ99QlhdARm8jKIcUx0-UUOxYLb0I8+PAZ2P0-MMDooUjpdkv43RQ1tkKg+RyttR78asn9zgX9N871iZHcsg6IC9D8i9j9UAAArfWM-J0C-K-eDBPaufcYwb6UcUqFacaNBdPDQeUR6YqBMeQbCfcbNTAkfMzZdWAXEUCbOTOPqGGc-eTaAi5KWadLUOYTzSJAHTSOMKwAwFILQV6UKDA+dS7UfbrXg-g4eQQ-aI6eGEA-ZcAqFKApfXcbUEYcYSRe4AibCYwdParUYFNZQ8aOYUqRqavWAUPAuFmAg2TUQiwzCVQuuOrRufGdeNuWUEmbCB8VIVrG8RqdJCAaVZiPqUgZAIbGTIg8rGuXQFIB4OBPFTGYYUic4UlG4O4NpZ4RYUQXgHdeAQIRcRTUXRAAAWhrmjHaLSFVGWmJlemDCDAsEagZBu2EFXVaNIK1CvCzwVATFeluGolbhiGVSvEbiHUjHuQ4I0L0lzGNALDNGLFAUrh9AvBJnzwSA70gTgWkWBDgTjAlm0GUPiDHRpn0jzBNELHBktDfAMkZCmLW1vAoMuPiH0BuNehuV3lGGDGyHiBDFxVV3hT+M+MOLnBLDhxWErEBKrlmCvEDAsGUKmHDEcPPASAoLtyfE3mGEMHeMNEMmalijagIRxIxlvEdSTFHCKnynOL9AqkYL7md2oIYK3nUJ9n0gZM2jinam4j+OxOvzaIq1vEegvHuR5KeD5PPCOwDBO3lHwgTAWGHzlPSKlOZI6jZ1ZMsOsBJkUTehWiOzGBuQtXSAVHEWtLojpPfBilag4gIU6m6l6kgEtMwhQUPHqTSDbzxLgVmhiTqQTFqhMCPmHw2hai2h2iDIVNIO8nckonVQIhqzUBuTGCClxTdXaVMCBhBjBmOLEEhmhmDJvUsFVA7GsEsDGFO1JOBCeAUIsCjlEVlDmCRNpV9nPigHzkDhOO5RCIvCvBvBJPSGKOWkVgoLCVuHmSmF3jFPhURQZVznHMLhylON3BfTbjTBGHiBMFa0ohuGPlPlHMvmvmcUIWfgbIiASEPFCnmFSBTEsFMCiUQRrlKjf3GhnS3NpTSVYUyXURfMzLWxTkdSDF7j9EonylHCaWLM3gjBmFCzp2UXSSDzcXAg8U+TRT8VfPFCeDkSQphCuHGH-KxlKlxgWQ-yHMnAgoySgEIufM8WZQKWwHIr3BgTuSKL9HfIBhjgQQYpDA1V7IlleV3OQH6QErQoBytUemkNxgQN-WHx3OzmRRIt8R+QEsmFIjmQDHiDcn5UMwP12JWXpT0sUo+V4sKQErgQQqTyTm2wlELPPDMubkfCMzSCXnFVEElTSKgAEpQsdSGKDGKlxXDCiWuDjFCy8hTksH7F-witgtxKKktUHT+w3xiG8lVDUO8hFQMFWlyGH2LwEFSLAEirmiSAMw1FSHmHiDY07CSAssjC3lqQamquP1yz62s0o0iqUPjkMHdVB1EUJhiFCx1IVF8nSFitlEypEzE1qpGv3QEv7TyrX1TwYU0hGFdPIIVGom8jWqGun24EitsLBCeGeKeFHDmGTS3j7xorBOomwrWs1yHgaqVmEWekKLapWNkEa0fGuByAnU0B+vH1ZxSRr051R3RwaphCasVwVFaquMwyViMCTGUi-y3lYs0O4J9xh3hvh0ZF1wrAjwEovESE3jiVEUB00lfS+lGhrm0ngrenC1sq4K6xPz92EwDyDxDzD2n2RDpqmEz1mDaueprTuId3Zs0k5oYLTB5thvJuXQr24Cr0RuR2RsluyrOLzyapMASGHVnXt0iFCj7y-1aX3GTE1qFp4N-B1lpuNqxWkLBA1RyDTWmA3ltpTntp7m437gGq0MFvuwzJILWzrSvCSobjxOGBmHTywqlE0l7M0DGE7DWtwPwIgAErTBXNFP+isB7kVoQFEQ4yKgUgSOuE8IjtJp0G6lAigBKwvl4GqDD3qs9sqT9EdXTTTGqlQIktWNMHmkTAmEB0hCTM4OLx0IZX0MLr7sQ2ogkPOCkJTjgVkNWLKrBE7Hz0TDfWDDWsXoEIECEM0TqsisSQDChBTHCmuBMCcLes1C8hd16qeDPr4KXsvsgBXVJqUtXvoxdyCl6IYKoJTjHvUHkKQTTGuFSvz15sYm8N8MDhjrRkVMxmipQwsBB20gSuiOQOHFKmZs8uSLvlSIZLAEyKG0ioYKdV41lllCMAjHKMlhVlmS1HyJTHojsCAA */
+ model.createMachine(
+ {
+ predictableActionArguments: true,
+ preserveActionOrder: true,
+ tsTypes: {} as import('./requestMachine.typegen').Typegen0,
+ schema: {
+ context: model.initialContext,
+ events: {} as EventFrom,
+ services: {} as {
+ verifyVp: {
+ data: VC;
+ };
+ },
+ },
+ invoke: {
+ src: 'monitorConnection',
+ },
+ id: 'request',
+ initial: 'inactive',
+ on: {
+ SCREEN_BLUR: {
+ target: '.inactive',
+ },
+ SCREEN_FOCUS: {
+ // eslint-disable-next-line sonarjs/no-duplicate-string
+ target: '.checkStorage',
+ },
+ BLE_ERROR: {
+ target: '.handlingBleError',
+ actions: 'setBleError',
+ },
+ RESET: {
+ target: '.checkNearbyDevicesPermission',
+ },
+ },
+ states: {
+ inactive: {
+ entry: 'removeLoggers',
+ },
+ checkStorage: {
+ invoke: {
+ src: 'checkStorageAvailability',
+ onDone: [
+ {
+ cond: 'isMinimumStorageLimitReached',
+ target: 'storageLimitReached',
+ },
+ {
+ target: 'checkNearbyDevicesPermission',
+ },
+ ],
+ },
+ },
+ storageLimitReached: {},
+ checkNearbyDevicesPermission: {
+ initial: 'checking',
+ states: {
+ checking: {
+ invoke: {
+ src: 'checkNearByDevicesPermission',
+ },
+ on: {
+ NEARBY_ENABLED: {
+ actions: 'setReadyForBluetoothStateCheck',
+ target: '#request.checkingBluetoothService',
+ },
+ NEARBY_DISABLED: {
+ target: 'requesting',
+ },
+ },
+ },
+ requesting: {
+ invoke: {
+ src: 'requestNearByDevicesPermission',
+ },
+ on: {
+ NEARBY_ENABLED: {
+ target: '#request.checkingBluetoothService',
+ },
+ NEARBY_DISABLED: {
+ target: '#request.nearByDevicesPermissionDenied',
+ },
+ },
+ },
+ },
+ },
+
+ checkingBluetoothService: {
+ initial: 'checking',
+ states: {
+ checking: {
+ invoke: {
+ src: 'checkBluetoothService',
+ },
+ on: {
+ BLUETOOTH_STATE_ENABLED: {
+ target: 'enabled',
+ },
+ BLUETOOTH_STATE_DISABLED: {
+ target: 'requesting',
+ },
+ },
+ },
+ requesting: {
+ invoke: {
+ src: 'requestBluetooth',
+ },
+ on: {
+ BLUETOOTH_STATE_ENABLED: {
+ target: 'enabled',
+ },
+ BLUETOOTH_STATE_DISABLED: {
+ target: '#request.bluetoothDenied',
+ },
+ },
+ },
+ enabled: {
+ always: {
+ // eslint-disable-next-line sonarjs/no-duplicate-string
+ target: '#request.clearingConnection',
+ },
+ },
+ },
+ },
+ bluetoothDenied: {},
+ nearByDevicesPermissionDenied: {
+ on: {
+ APP_ACTIVE: '#request.checkNearbyDevicesPermission',
+ GOTO_SETTINGS: {
+ actions: 'openAppPermission',
+ },
+ },
+ },
+ clearingConnection: {
+ invoke: {
+ src: 'disconnect',
+ },
+ on: {
+ DISCONNECT: {
+ target: '#request.waitingForConnection',
+ actions: [],
+ internal: false,
+ },
+ },
+ after: {
+ DESTROY_TIMEOUT: {
+ target: '#request.waitingForConnection',
+ actions: [],
+ internal: false,
+ },
+ },
+ },
+ waitingForConnection: {
+ entry: ['removeLoggers', 'registerLoggers'],
+ invoke: {
+ src: 'advertiseDevice',
+ },
+ on: {
+ ADV_STARTED: {
+ actions: 'setOpenID4VpUri',
+ },
+ CONNECTED: {
+ target: 'waitingForVc',
+ actions: ['setSenderInfo', 'setReceiverInfo'],
+ },
+
+ DISCONNECT: {
+ target: 'disconnected',
+ },
+ },
+ },
+ waitingForVc: {
+ invoke: {
+ src: 'receiveVc',
+ },
+ initial: 'inProgress',
+ states: {
+ inProgress: {
+ after: {
+ SHARING_TIMEOUT: {
+ target: '#request.waitingForVc.timeout',
+ actions: [],
+ internal: false,
+ },
+ },
+ },
+ timeout: {
+ on: {
+ CANCEL: {
+ target: '#request.cancelling',
+ },
+ },
+ },
+ },
+ on: {
+ DISCONNECT: {
+ target: 'disconnected',
+ },
+ VC_RECEIVED: {
+ target: 'reviewing.accepting',
+ actions: 'setIncomingVc',
+ },
+ },
+ },
+ cancelling: {
+ always: {
+ target: '#request.clearingConnection',
+ },
+ },
+ reviewing: {
+ initial: 'idle',
+ states: {
+ idle: {},
+ verifyingIdentity: {
+ exit: 'clearShouldVerifyPresence',
+ on: {
+ FACE_VALID: {
+ target: 'accepting',
+ actions: 'setReceiveLogTypeVerified',
+ },
+ FACE_INVALID: {
+ target: 'invalidIdentity',
+ actions: 'setReceiveLogTypeUnverified',
+ },
+ CANCEL: {
+ target: 'idle',
+ },
+ },
+ },
+ invalidIdentity: {
+ on: {
+ DISMISS: {
+ target: 'accepting',
+ },
+ RETRY_VERIFICATION: {
+ target: 'verifyingIdentity',
+ },
+ },
+ },
+ verifyingVp: {
+ invoke: {
+ src: 'verifyVp',
+ onDone: [
+ {
+ target: 'accepting',
+ },
+ ],
+ onError: [
+ {
+ target: 'idle',
+ actions: log('Failed to verify Verifiable Presentation'),
+ },
+ ],
+ },
+ },
+ accepting: {
+ initial: 'requestingReceivedVcs',
+ states: {
+ requestingReceivedVcs: {
+ entry: 'requestReceivedVcs',
+ on: {
+ VC_RESPONSE: [
+ {
+ target: 'requestingExistingVc',
+ cond: 'hasExistingVc',
+ },
+ {
+ target: 'prependingReceivedVc',
+ },
+ ],
+ },
+ },
+ requestingExistingVc: {
+ entry: 'requestExistingVc',
+ on: {
+ STORE_RESPONSE: {
+ target: 'mergingIncomingVc',
+ },
+ },
+ },
+ mergingIncomingVc: {
+ entry: 'mergeIncomingVc',
+ on: {
+ STORE_RESPONSE: {
+ target: '#request.reviewing.accepted',
+ },
+ },
+ },
+ prependingReceivedVc: {
+ entry: 'prependReceivedVc',
+ on: {
+ STORE_RESPONSE: {
+ target: 'storingVc',
+ },
+ },
+ },
+ storingVc: {
+ entry: 'storeVc',
+ on: {
+ STORE_RESPONSE: {
+ target: '#request.reviewing.accepted',
+ },
+ },
+ },
+ },
+ on: {
+ STORE_ERROR: {
+ target: '#request.reviewing.savingFailed',
+ },
+ },
+ },
+ accepted: {
+ entry: [
+ 'sendVcReceived',
+ 'setReceiveLogTypeRegular',
+ 'logReceived',
+ ],
+ invoke: {
+ src: 'sendVcResponse',
+ data: {
+ status: VerificationStatus.ACCEPTED,
+ },
+ },
+ on: {
+ DISMISS: {
+ target: 'navigatingToHistory',
+ },
+ },
+ },
+ rejected: {
+ entry: ['setReceiveLogTypeDiscarded', 'logReceived'],
+ invoke: {
+ src: 'sendVcResponse',
+ data: {
+ status: VerificationStatus.REJECTED,
+ },
+ },
+ on: {
+ DISMISS: {
+ target: '#request.clearingConnection',
+ },
+ },
+ },
+ navigatingToHistory: {
+ invoke: {
+ src: 'disconnect',
+ },
+ },
+ displayingIncomingVC: {
+ on: {
+ GO_TO_RECEIVED_VC_TAB: {
+ target: 'navigatingToHistory',
+ },
+ },
+ },
+
+ savingFailed: {
+ initial: 'idle',
+ entry: ['setReceiveLogTypeDiscarded', 'logReceived'],
+ invoke: {
+ src: 'sendVcResponse',
+ data: {
+ status: VerificationStatus.REJECTED,
+ },
+ },
+ states: {
+ idle: {},
+ viewingVc: {},
+ },
+ on: {
+ DISMISS: {
+ target: '.viewingVc',
+ },
+ GO_TO_RECEIVED_VC_TAB: {
+ target: 'navigatingToHistory',
+ },
+ },
+ },
+ },
+ on: {
+ ACCEPT: {
+ target: '.accepting',
+ actions: 'setReceiveLogTypeRegular',
+ },
+ ACCEPT_AND_VERIFY: {
+ target: '.verifyingIdentity',
+ },
+ REJECT: {
+ target: '.rejected',
+ },
+ CANCEL: {
+ target: '.rejected',
+ },
+ },
+ },
+ disconnected: {
+ on: {
+ DISMISS: {
+ target: 'waitingForConnection',
+ },
+ },
+ },
+ handlingBleError: {
+ on: {
+ DISMISS: {
+ target: '#request.clearingConnection',
+ },
+ },
+ },
+ },
+ },
+ {
+ actions: {
+ openAppPermission: () => {
+ Linking.openSettings();
+ },
+
+ requestReceivedVcs: send(VcEvents.GET_RECEIVED_VCS(), {
+ to: (context) => context.serviceRefs.vc,
+ }),
+
+ setReadyForBluetoothStateCheck: model.assign({
+ readyForBluetoothStateCheck: () => true,
+ }),
+
+ setIncomingVc: assign({
+ incomingVc: (_context, event) => {
+ const vp = event.vc.verifiablePresentation;
+ return vp != null
+ ? {
+ ...event.vc,
+ verifiableCredential: vp.verifiableCredential[0],
+ }
+ : event.vc;
+ },
+ }),
+
+ setOpenID4VpUri: assign({
+ openId4VpUri: (_context, event) => {
+ return event.openId4VpUri;
+ },
+ }),
+
+ setSenderInfo: assign({
+ senderInfo: () => {
+ return { name: 'Wallet', deviceName: 'Wallet', deviceId: '' };
+ },
+ }),
+
+ setReceiverInfo: assign({
+ receiverInfo: () => {
+ return { name: 'Verifier', deviceName: 'Verifier', deviceId: '' };
+ },
+ }),
+
+ setBleError: assign({
+ bleError: (_context, event) => event.bleError,
+ }),
+
+ registerLoggers: assign({
+ loggers: () => {
+ if (__DEV__) {
+ return [
+ verifier.handleDataEvents((event) => {
+ console.log(
+ getDeviceNameSync(),
+ '',
+ JSON.stringify(event).slice(0, 100)
+ );
+ }),
+ ];
+ } else {
+ return [];
+ }
+ },
+ }),
+
+ removeLoggers: assign({
+ loggers: ({ loggers }) => {
+ loggers?.forEach((logger) => logger.remove());
+ return null;
+ },
+ }),
+
+ prependReceivedVc: send(
+ (context) =>
+ StoreEvents.PREPEND(
+ RECEIVED_VCS_STORE_KEY,
+ VC_ITEM_STORE_KEY(context.incomingVc)
+ ),
+ { to: (context) => context.serviceRefs.store }
+ ),
+
+ requestExistingVc: send(
+ (context) => StoreEvents.GET(VC_ITEM_STORE_KEY(context.incomingVc)),
+ { to: (context) => context.serviceRefs.store }
+ ),
+
+ mergeIncomingVc: send(
+ (context, event) => {
+ const existing = event.response as VC;
+ const updated: VC = {
+ ...existing,
+ reason: existing.reason.concat(context.incomingVc.reason),
+ };
+ return StoreEvents.SET(VC_ITEM_STORE_KEY(updated), updated);
+ },
+ { to: (context) => context.serviceRefs.store }
+ ),
+
+ storeVc: send(
+ (context) =>
+ StoreEvents.SET(
+ VC_ITEM_STORE_KEY(context.incomingVc),
+ context.incomingVc
+ ),
+ { to: (context) => context.serviceRefs.store }
+ ),
+
+ setReceiveLogTypeRegular: model.assign({
+ receiveLogType: 'VC_RECEIVED',
+ }),
+
+ setReceiveLogTypeVerified: model.assign({
+ receiveLogType: 'VC_RECEIVED_WITH_PRESENCE_VERIFIED',
+ }),
+
+ setReceiveLogTypeUnverified: model.assign({
+ receiveLogType: 'VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED',
+ }),
+
+ setReceiveLogTypeDiscarded: model.assign({
+ receiveLogType: 'VC_RECEIVED_NOT_SAVED',
+ }),
+
+ logReceived: send(
+ (context) =>
+ ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: VC_ITEM_STORE_KEY(context.incomingVc),
+ type: context.receiveLogType,
+ timestamp: Date.now(),
+ deviceName:
+ context.senderInfo.name || context.senderInfo.deviceName,
+ vcLabel: context.incomingVc.tag || context.incomingVc.id,
+ }),
+ { to: (context) => context.serviceRefs.activityLog }
+ ),
+
+ sendVcReceived: send(
+ (context) => {
+ return VcEvents.VC_RECEIVED(VC_ITEM_STORE_KEY(context.incomingVc));
+ },
+ { to: (context) => context.serviceRefs.vc }
+ ),
+
+ clearShouldVerifyPresence: assign({
+ incomingVc: (context) => ({
+ ...context.incomingVc,
+ shouldVerifyPresence: false,
+ }),
+ }),
+ },
+
+ services: {
+ disconnect: () => () => {
+ try {
+ verifier.disconnect();
+ } catch (e) {
+ // pass
+ }
+ },
+
+ checkBluetoothService: () => (callback) => {
+ const subscription = BluetoothStateManager.onStateChange((state) => {
+ if (state === 'PoweredOn') {
+ callback(model.events.BLUETOOTH_STATE_ENABLED());
+ } else {
+ callback(model.events.BLUETOOTH_STATE_DISABLED());
+ }
+ }, true);
+ return () => subscription.remove();
+ },
+
+ requestBluetooth: () => (callback) => {
+ BluetoothStateManager.requestToEnable()
+ .then(() => callback(model.events.BLUETOOTH_STATE_ENABLED()))
+ .catch(() => callback(model.events.BLUETOOTH_STATE_DISABLED()));
+ },
+
+ advertiseDevice: () => (callback) => {
+ const openId4VpUri = verifier.startAdvertisement('OVPMOSIP');
+ callback({ type: 'ADV_STARTED', openId4VpUri });
+
+ const statusCallback = (event: VerifierDataEvent) => {
+ if (event.type === EventTypes.onSecureChannelEstablished) {
+ callback({ type: 'CONNECTED' });
+ }
+ };
+ const subscription = subscribe(statusCallback);
+ return () => subscription?.remove();
+ },
+
+ requestNearByDevicesPermission: () => (callback) => {
+ requestMultiple([
+ PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE,
+ PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
+ ])
+ .then((response) => {
+ if (
+ response[PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE] ===
+ RESULTS.GRANTED &&
+ response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
+ RESULTS.GRANTED
+ ) {
+ callback(model.events.NEARBY_ENABLED());
+ } else {
+ callback(model.events.NEARBY_DISABLED());
+ }
+ })
+ .catch((err) => {
+ callback(model.events.NEARBY_DISABLED());
+ });
+ },
+
+ checkNearByDevicesPermission: () => (callback) => {
+ if (Platform.OS === 'android' && Platform.Version >= 31) {
+ const result = checkMultiple([
+ PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE,
+ PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
+ PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
+ ])
+ .then((response) => {
+ if (
+ response[PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE] ===
+ RESULTS.GRANTED &&
+ response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
+ RESULTS.GRANTED
+ ) {
+ callback(model.events.NEARBY_ENABLED());
+ } else {
+ callback(model.events.NEARBY_DISABLED());
+ }
+ })
+ .catch((err) => {
+ callback(model.events.NEARBY_DISABLED());
+ });
+ } else {
+ callback(model.events.NEARBY_ENABLED());
+ }
+ },
+
+ monitorConnection: () => (callback) => {
+ const subscription = verifier.handleDataEvents((event) => {
+ if (event.type === EventTypes.onDisconnected) {
+ callback({ type: 'DISCONNECT' });
+ }
+
+ if (event.type === EventTypes.onError) {
+ callback({
+ type: 'BLE_ERROR',
+ bleError: { message: event.message, code: event.code },
+ });
+ console.log('BLE Exception: ' + event.message);
+ }
+ });
+
+ return () => subscription.remove();
+ },
+
+ receiveVc: () => (callback) => {
+ const statusCallback = (event: VerifierDataEvent) => {
+ if (event.type === EventTypes.onDataReceived) {
+ callback({ type: 'VC_RECEIVED', vc: JSON.parse(event.data) });
+ }
+ };
+ const subscription = subscribe(statusCallback);
+
+ return () => subscription.remove();
+ },
+
+ sendVcResponse: (context, _event, meta) => async () => {
+ verifier.sendVerificationStatus(meta.data.status);
+ },
+
+ verifyVp: (context) => async () => {
+ const vp = context.incomingVc.verifiablePresentation;
+
+ // TODO
+ // const challenge = ?
+ // await verifyPresentation(vp, challenge);
+
+ const vc: VC = {
+ ...context.incomingVc,
+ verifiablePresentation: null,
+ verifiableCredential: vp.verifiableCredential[0],
+ };
+
+ return Promise.resolve(vc);
+ },
+
+ checkStorageAvailability: () => async () => {
+ return Promise.resolve(
+ Storage.isMinimumLimitReached('minStorageRequired')
+ );
+ },
+ },
+
+ guards: {
+ hasExistingVc: (context, event) => {
+ const receivedVcs = event.response as string[];
+ const vcKey = VC_ITEM_STORE_KEY(context.incomingVc);
+ return receivedVcs.includes(vcKey);
+ },
+
+ isMinimumStorageLimitReached: (_context, event) => Boolean(event.data),
+ },
+
+ delays: {
+ DESTROY_TIMEOUT: 500,
+ SHARING_TIMEOUT: 15 * 1000,
+ },
+ }
+ );
+
+type State = StateFrom;
+
+export function createRequestMachine(serviceRefs: AppServices) {
+ return requestMachine.withContext({
+ ...requestMachine.context,
+ serviceRefs,
+ });
+}
+
+export function selectIsMinimumStorageLimitReached(state: State) {
+ return state.matches('storageLimitReached');
+}
diff --git a/machines/request.typegen.ts b/machines/bleShare/request/requestMachine.typegen.ts
similarity index 56%
rename from machines/request.typegen.ts
rename to machines/bleShare/request/requestMachine.typegen.ts
index 431d0e1e..79fcc938 100644
--- a/machines/request.typegen.ts
+++ b/machines/bleShare/request/requestMachine.typegen.ts
@@ -4,19 +4,18 @@ export interface Typegen0 {
'@@xstate/typegen': true;
'internalEvents': {
'': { type: '' };
+ 'done.invoke.request.checkStorage:invocation[0]': {
+ type: 'done.invoke.request.checkStorage:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
'done.invoke.request.reviewing.verifyingVp:invocation[0]': {
type: 'done.invoke.request.reviewing.verifyingVp:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
- 'xstate.after(CANCEL_TIMEOUT)#request.cancelling': {
- type: 'xstate.after(CANCEL_TIMEOUT)#request.cancelling';
- };
- 'xstate.after(CLEAR_DELAY)#request.clearingConnection': {
- type: 'xstate.after(CLEAR_DELAY)#request.clearingConnection';
- };
- 'xstate.after(CONNECTION_TIMEOUT)#request.exchangingDeviceInfo.inProgress': {
- type: 'xstate.after(CONNECTION_TIMEOUT)#request.exchangingDeviceInfo.inProgress';
+ 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection': {
+ type: 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection';
};
'xstate.after(SHARING_TIMEOUT)#request.waitingForVc.inProgress': {
type: 'xstate.after(SHARING_TIMEOUT)#request.waitingForVc.inProgress';
@@ -27,15 +26,19 @@ export interface Typegen0 {
'invokeSrcNameMap': {
advertiseDevice: 'done.invoke.request.waitingForConnection:invocation[0]';
checkBluetoothService: 'done.invoke.request.checkingBluetoothService.checking:invocation[0]';
- checkNetwork: 'done.invoke.request.checkingNetwork:invocation[0]';
- exchangeDeviceInfo: 'done.invoke.request.exchangingDeviceInfo:invocation[0]';
+ checkNearByDevicesPermission: 'done.invoke.request.checkNearbyDevicesPermission.checking:invocation[0]';
+ checkStorageAvailability: 'done.invoke.request.checkStorage:invocation[0]';
+ disconnect:
+ | 'done.invoke.request.clearingConnection:invocation[0]'
+ | 'done.invoke.request.reviewing.navigatingToHistory:invocation[0]';
monitorConnection: 'done.invoke.request:invocation[0]';
receiveVc: 'done.invoke.request.waitingForVc:invocation[0]';
requestBluetooth: 'done.invoke.request.checkingBluetoothService.requesting:invocation[0]';
- sendDisconnect: 'done.invoke.request.cancelling:invocation[0]';
+ requestNearByDevicesPermission: 'done.invoke.request.checkNearbyDevicesPermission.requesting:invocation[0]';
sendVcResponse:
| 'done.invoke.request.reviewing.accepted:invocation[0]'
- | 'done.invoke.request.reviewing.rejected:invocation[0]';
+ | 'done.invoke.request.reviewing.rejected:invocation[0]'
+ | 'done.invoke.request.reviewing.savingFailed:invocation[0]';
verifyVp: 'done.invoke.request.reviewing.verifyingVp:invocation[0]';
};
'missingImplementations': {
@@ -47,101 +50,92 @@ export interface Typegen0 {
'eventsCausingActions': {
clearShouldVerifyPresence:
| 'ACCEPT'
+ | 'BLE_ERROR'
| 'CANCEL'
| 'FACE_INVALID'
| 'FACE_VALID'
| 'REJECT'
+ | 'RESET'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
- | 'SWITCH_PROTOCOL'
| 'xstate.stop';
- disconnect:
- | ''
+ logReceived: 'CANCEL' | 'REJECT' | 'STORE_ERROR' | 'STORE_RESPONSE';
+ mergeIncomingVc: 'STORE_RESPONSE';
+ openAppPermission: 'GOTO_SETTINGS';
+ prependReceivedVc: 'VC_RESPONSE';
+ registerLoggers:
+ | 'DISCONNECT'
+ | 'DISMISS'
+ | 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection';
+ removeLoggers:
| 'DISCONNECT'
| 'DISMISS'
| 'SCREEN_BLUR'
- | 'SCREEN_FOCUS'
- | 'SWITCH_PROTOCOL'
- | 'xstate.after(CANCEL_TIMEOUT)#request.cancelling'
- | 'xstate.stop';
- generateConnectionParams:
- | 'DISMISS'
- | 'xstate.after(CLEAR_DELAY)#request.clearingConnection';
- logReceived: 'CANCEL' | 'REJECT' | 'STORE_RESPONSE';
- mergeIncomingVc: 'STORE_RESPONSE';
- openSettings: 'GOTO_SETTINGS';
- prependReceivedVc: 'VC_RESPONSE';
- registerLoggers:
- | 'DISMISS'
- | 'xstate.after(CLEAR_DELAY)#request.clearingConnection';
- removeLoggers:
- | 'DISMISS'
- | 'SCREEN_BLUR'
- | 'xstate.after(CLEAR_DELAY)#request.clearingConnection'
+ | 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection'
| 'xstate.init';
requestExistingVc: 'VC_RESPONSE';
requestReceivedVcs:
| 'ACCEPT'
| 'DISMISS'
| 'FACE_VALID'
+ | 'VC_RECEIVED'
| 'done.invoke.request.reviewing.verifyingVp:invocation[0]';
- requestReceiverInfo: 'CONNECTED';
+ sendVcReceived: 'STORE_RESPONSE';
+ setBleError: 'BLE_ERROR';
setIncomingVc: 'VC_RECEIVED';
- setPairId: 'CONNECTED';
- setReceiveLogTypeDiscarded: 'CANCEL' | 'REJECT';
- setReceiveLogTypeRegular: 'ACCEPT';
+ setOpenID4VpUri: 'ADV_STARTED';
+ setReadyForBluetoothStateCheck: 'NEARBY_ENABLED';
+ setReceiveLogTypeDiscarded: 'CANCEL' | 'REJECT' | 'STORE_ERROR';
+ setReceiveLogTypeRegular: 'ACCEPT' | 'STORE_RESPONSE';
setReceiveLogTypeUnverified: 'FACE_INVALID';
setReceiveLogTypeVerified: 'FACE_VALID';
- setReceiverInfo: 'RECEIVE_DEVICE_INFO';
- setSenderInfo: 'EXCHANGE_DONE';
+ setReceiverInfo: 'CONNECTED';
+ setSenderInfo: 'CONNECTED';
storeVc: 'STORE_RESPONSE';
- switchProtocol: 'SWITCH_PROTOCOL';
- updateReceivedVcs: 'STORE_RESPONSE';
};
'eventsCausingDelays': {
- CANCEL_TIMEOUT: 'CANCEL';
- CLEAR_DELAY: '';
- CONNECTION_TIMEOUT: 'RECEIVE_DEVICE_INFO';
- SHARING_TIMEOUT: 'EXCHANGE_DONE';
+ DESTROY_TIMEOUT: '' | 'DISMISS';
+ SHARING_TIMEOUT: 'CONNECTED';
};
'eventsCausingGuards': {
hasExistingVc: 'VC_RESPONSE';
- isModeOnline: 'SCREEN_FOCUS' | 'SWITCH_PROTOCOL';
+ isMinimumStorageLimitReached: 'done.invoke.request.checkStorage:invocation[0]';
};
'eventsCausingServices': {
advertiseDevice:
+ | 'DISCONNECT'
| 'DISMISS'
- | 'xstate.after(CLEAR_DELAY)#request.clearingConnection';
- checkBluetoothService:
- | 'ONLINE'
- | 'SCREEN_FOCUS'
- | 'SWITCH_PROTOCOL'
- | 'xstate.after(CANCEL_TIMEOUT)#request.cancelling';
- checkNetwork: 'APP_ACTIVE' | 'SCREEN_FOCUS' | 'SWITCH_PROTOCOL';
- exchangeDeviceInfo: 'RECEIVE_DEVICE_INFO';
+ | 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection';
+ checkBluetoothService: 'NEARBY_ENABLED';
+ checkNearByDevicesPermission:
+ | 'APP_ACTIVE'
+ | 'RESET'
+ | 'done.invoke.request.checkStorage:invocation[0]';
+ checkStorageAvailability: 'SCREEN_FOCUS';
+ disconnect: '' | 'DISMISS' | 'GO_TO_RECEIVED_VC_TAB';
monitorConnection: 'xstate.init';
- receiveVc: 'EXCHANGE_DONE';
- requestBluetooth: 'BLUETOOTH_DISABLED';
- sendDisconnect: 'CANCEL';
- sendVcResponse: 'CANCEL' | 'REJECT' | 'STORE_RESPONSE';
+ receiveVc: 'CONNECTED';
+ requestBluetooth: 'BLUETOOTH_STATE_DISABLED';
+ requestNearByDevicesPermission: 'NEARBY_DISABLED';
+ sendVcResponse: 'CANCEL' | 'REJECT' | 'STORE_ERROR' | 'STORE_RESPONSE';
verifyVp: never;
};
'matchesStates':
| 'bluetoothDenied'
| 'cancelling'
+ | 'checkNearbyDevicesPermission'
+ | 'checkNearbyDevicesPermission.checking'
+ | 'checkNearbyDevicesPermission.requesting'
+ | 'checkStorage'
| 'checkingBluetoothService'
| 'checkingBluetoothService.checking'
| 'checkingBluetoothService.enabled'
| 'checkingBluetoothService.requesting'
- | 'checkingNetwork'
| 'clearingConnection'
| 'disconnected'
- | 'exchangingDeviceInfo'
- | 'exchangingDeviceInfo.inProgress'
- | 'exchangingDeviceInfo.timeout'
+ | 'handlingBleError'
| 'inactive'
- | 'offline'
- | 'preparingToExchangeInfo'
+ | 'nearByDevicesPermissionDenied'
| 'reviewing'
| 'reviewing.accepted'
| 'reviewing.accepting'
@@ -150,26 +144,33 @@ export interface Typegen0 {
| 'reviewing.accepting.requestingExistingVc'
| 'reviewing.accepting.requestingReceivedVcs'
| 'reviewing.accepting.storingVc'
+ | 'reviewing.displayingIncomingVC'
| 'reviewing.idle'
| 'reviewing.invalidIdentity'
- | 'reviewing.navigatingToHome'
+ | 'reviewing.navigatingToHistory'
| 'reviewing.rejected'
+ | 'reviewing.savingFailed'
+ | 'reviewing.savingFailed.idle'
+ | 'reviewing.savingFailed.viewingVc'
| 'reviewing.verifyingIdentity'
| 'reviewing.verifyingVp'
+ | 'storageLimitReached'
| 'waitingForConnection'
| 'waitingForVc'
| 'waitingForVc.inProgress'
| 'waitingForVc.timeout'
| {
+ checkNearbyDevicesPermission?: 'checking' | 'requesting';
checkingBluetoothService?: 'checking' | 'enabled' | 'requesting';
- exchangingDeviceInfo?: 'inProgress' | 'timeout';
reviewing?:
| 'accepted'
| 'accepting'
+ | 'displayingIncomingVC'
| 'idle'
| 'invalidIdentity'
- | 'navigatingToHome'
+ | 'navigatingToHistory'
| 'rejected'
+ | 'savingFailed'
| 'verifyingIdentity'
| 'verifyingVp'
| {
@@ -179,6 +180,7 @@ export interface Typegen0 {
| 'requestingExistingVc'
| 'requestingReceivedVcs'
| 'storingVc';
+ savingFailed?: 'idle' | 'viewingVc';
};
waitingForVc?: 'inProgress' | 'timeout';
};
diff --git a/machines/bleShare/request/selectors.ts b/machines/bleShare/request/selectors.ts
new file mode 100644
index 00000000..44fef7c1
--- /dev/null
+++ b/machines/bleShare/request/selectors.ts
@@ -0,0 +1,60 @@
+import { StateFrom } from 'xstate';
+import { requestMachine } from './requestMachine';
+
+type State = StateFrom;
+
+export function selectSenderInfo(state: State) {
+ return state.context.senderInfo;
+}
+
+export function selectIncomingVc(state: State) {
+ return state.context.incomingVc;
+}
+
+export function selectSharingProtocol(state: State) {
+ return state.context.sharingProtocol;
+}
+
+export function selectIsIncomingVp(state: State) {
+ return state.context.incomingVc?.verifiablePresentation != null;
+}
+
+export function selectIsReviewingInIdle(state: State) {
+ return state.matches('reviewing.idle');
+}
+
+export function selectIsWaitingForConnection(state: State) {
+ return state.matches('waitingForConnection');
+}
+
+export function selectIsCheckingBluetoothService(state: State) {
+ return state.matches('checkingBluetoothService');
+}
+
+export function selectIsWaitingForVc(state: State) {
+ return state.matches('waitingForVc.inProgress');
+}
+
+export function selectIsWaitingForVcTimeout(state: State) {
+ return state.matches('waitingForVc.timeout');
+}
+
+export function selectOpenId4VpUri(state: State) {
+ return state.context.openId4VpUri;
+}
+
+export function selectIsAccepting(state: State) {
+ return state.matches('reviewing.accepting');
+}
+
+export function selectIsSavingFailedInIdle(state: State) {
+ return state.matches('reviewing.savingFailed.idle');
+}
+
+export function selectIsSavingFailedInViewingVc(state: State) {
+ return state.matches('reviewing.savingFailed.viewingVc');
+}
+
+export function selectIsDone(state: State) {
+ return state.matches('reviewing.navigatingToHistory');
+}
diff --git a/machines/bleShare/scan/scanMachine.ts b/machines/bleShare/scan/scanMachine.ts
new file mode 100644
index 00000000..9d736eb8
--- /dev/null
+++ b/machines/bleShare/scan/scanMachine.ts
@@ -0,0 +1,1094 @@
+/* eslint-disable sonarjs/no-duplicate-string */
+import tuvali from 'react-native-tuvali';
+import BluetoothStateManager from 'react-native-bluetooth-state-manager';
+import {
+ ActorRefFrom,
+ assign,
+ DoneInvokeEvent,
+ EventFrom,
+ send,
+ spawn,
+ StateFrom,
+} from 'xstate';
+import { createModel } from 'xstate/lib/model';
+import { EmitterSubscription, Linking, Platform } from 'react-native';
+import { DeviceInfo } from '../../../components/DeviceInfoList';
+import { getDeviceNameSync } from 'react-native-device-info';
+import { VC, VerifiablePresentation } from '../../../types/vc';
+import { AppServices } from '../../../shared/GlobalContext';
+import { ActivityLogEvents, ActivityLogType } from '../../activityLog';
+import {
+ MY_LOGIN_STORE_KEY,
+ VC_ITEM_STORE_KEY,
+} from '../../../shared/constants';
+import { subscribe } from '../../../shared/openIdBLE/walletEventHandler';
+import {
+ check,
+ checkMultiple,
+ PermissionStatus,
+ PERMISSIONS,
+ requestMultiple,
+ RESULTS,
+} from 'react-native-permissions';
+import {
+ checkLocationPermissionStatus,
+ requestLocationPermission,
+} from '../../../shared/location';
+import { CameraCapturedPicture } from 'expo-camera';
+import { log } from 'xstate/lib/actions';
+import { createQrLoginMachine, qrLoginMachine } from '../../QrLoginMachine';
+import { StoreEvents } from '../../store';
+import { WalletDataEvent } from 'react-native-tuvali/lib/typescript/types/events';
+import { BLEError } from '../types';
+import Storage from '../../../shared/storage';
+import { logState } from '../../app';
+
+const { wallet, EventTypes, VerificationStatus } = tuvali;
+
+const model = createModel(
+ {
+ serviceRefs: {} as AppServices,
+ senderInfo: {} as DeviceInfo,
+ receiverInfo: {} as DeviceInfo,
+ selectedVc: {} as VC,
+ bleError: {} as BLEError,
+ createdVp: null as VC,
+ reason: '',
+ loggers: [] as EmitterSubscription[],
+ vcName: '',
+ verificationImage: {} as CameraCapturedPicture,
+ openId4VpUri: '',
+ shareLogType: '' as ActivityLogType,
+ QrLoginRef: {} as ActorRefFrom,
+ linkCode: '',
+ readyForBluetoothStateCheck: false,
+ },
+ {
+ events: {
+ SELECT_VC: (vc: VC) => ({ vc }),
+ SCAN: (params: string) => ({ params }),
+ ACCEPT_REQUEST: () => ({}),
+ VERIFY_AND_ACCEPT_REQUEST: () => ({}),
+ VC_ACCEPTED: () => ({}),
+ VC_REJECTED: () => ({}),
+ VC_SENT: () => ({}),
+ CANCEL: () => ({}),
+ DISMISS: () => ({}),
+ CONNECTED: () => ({}),
+ DISCONNECT: () => ({}),
+ BLE_ERROR: (bleError: BLEError) => ({ bleError }),
+ CONNECTION_DESTROYED: () => ({}),
+ SCREEN_BLUR: () => ({}),
+ SCREEN_FOCUS: () => ({}),
+ BLUETOOTH_PERMISSION_ENABLED: () => ({}),
+ BLUETOOTH_PERMISSION_DENIED: () => ({}),
+ BLUETOOTH_STATE_ENABLED: () => ({}),
+ BLUETOOTH_STATE_DISABLED: () => ({}),
+ NEARBY_ENABLED: () => ({}),
+ NEARBY_DISABLED: () => ({}),
+ GOTO_SETTINGS: () => ({}),
+ START_PERMISSION_CHECK: () => ({}),
+ UPDATE_REASON: (reason: string) => ({ reason }),
+ LOCATION_ENABLED: () => ({}),
+ LOCATION_DISABLED: () => ({}),
+ LOCATION_REQUEST: () => ({}),
+ UPDATE_VC_NAME: (vcName: string) => ({ vcName }),
+ STORE_RESPONSE: (response: any) => ({ response }),
+ APP_ACTIVE: () => ({}),
+ FACE_VALID: () => ({}),
+ FACE_INVALID: () => ({}),
+ RETRY_VERIFICATION: () => ({}),
+ VP_CREATED: (vp: VerifiablePresentation) => ({ vp }),
+ TOGGLE_USER_CONSENT: () => ({}),
+ RESET: () => ({}),
+ },
+ }
+);
+const QR_LOGIN_REF_ID = 'QrLogin';
+export const ScanEvents = model.events;
+
+export const scanMachine =
+ /** @xstate-layout N4IgpgJg5mDOIC5SwMYEMB2BiAygYQCUBRIgOQH0AhAGQFUCBtABgF1FQAHAe1gEsAXXlwzsQAD0QAWAEwAaEAE9EARgCsygHSSAnLu1N1ypkwBs06QF8L81JlyESFAGIB5PLRzM2SENz6DhUQkEGXklBFVVJg0zQ20TJn0AdmlVKxt0bBoiciICAhdGVlE-ASERH2CADjlFRCqTJI1lVJbzYyYUqvSQWwwNFAALMBQAaxx+LgAnNBgsCGEwDV4MADcuUaW+geGxienZsAQV9fQAjC8vEp4ywMrEKJMNJKYqgGYTN+k3qKrtWvCqhMTzeSSiYMkb0kyn+SR62yGI3GkxmcwWGCWJw2W0yOyR+1RRyxZ3Kl2U3k4N3OQQepmerw+Xx+r3+YVpTSqSR0qiSMOUkhMaWsvVxsH4aCm-AACmApgBbXiwPjCPC7Ua4AAqAEECBryFK8gBZACSOBwxpcFDwAAkiHgANJXHylan3BBGeIaJjQpJgzoyVImNkhfkaPS6N5GaTGQUmeGi8WSmXyxXKjCqpGanV6g0EE1mi1W20Ohjk67+co091GJ7e5S+8EBoHBgWqLR6Ixg741OHC7ZiiXS2UKpXlDNjLO6-VG03my3kG12x3SCm+KmVt0tbSSL1mBJffTaA-B9RtvQ1KqSJjSMFVbp93GIsakMASgBGCgAImBVrwUHBkxHNM8TGFYoCwUgiB1SgAE1clILVsk-J1KQrO5QGCaEQVUaFtBaNRpB0RoT0kGpmkkHkrxaAxtHjTAQNGF93y-H8-wA4dU3KBiwIgqCCFg8hP1NRDqCIZDimddd0PEKRlGw3D8NUQj4iSEjjHI1R3m0TTVChe8Mnop9GNfKYP2-X9-1gQDOOEDQpjAABHABXOBBAwcDIOguCyBEsSULXNCKgwxBdDbKprzUMFlDeH5BRPRkND+HkkjMUwjGUOj+iMpjTJYiz2JTUdbPs5zXJ4zz+LgoScF88TVxdDdgoQULEoinl1BioFVBI0M3m0pJtySPrlH0kVDLVHKzNYyzrKK-owAwNA3wAG0gLB-Ia6Tgha8LpEijrYu6uoIlIt4Ygogb9F01R-kyhjKGWlzJi4fhBlm4CjJ4mhaCIDUXBcDVrWnPNZ0LeDao2qSgpkhA9qSKoND2u9fW0O8mDUE96x3fkdJR5GhQMrK1Qep6uBet6OLm7j3Kwb7fv+wHgfzOcKE-MhjT8iTUNuaHgmkYEdxiqFLtx7R4qvDQfhkN53iqetUjuoySbAZ7XveriFqW1aIHWrmAp5qsRtIyXIQaRIr15TST29JocaPQjzF0SRFeJx6VbJ16JjQfglk+mm6b+gGgZwbUNRyHykMhwKqz6ppIS7KpIk6Ex+pbJPJf6nDJBSUFnYfcakWV1XBi9n3qfAgOGeD0OcmqiG9c23mVGzhH4k5bQor+OSW0aTQcZS0EZbwvPCfut3i9L321S+uh6aD8gQ61MPBOEyOy0k6O3VjrRQSUxPwRTnkWwt86eRMZR+QG-kXcL8ePZL8Uy5KlyxRnn7A8Zxfl4j0S6vLA3NxMD6l6d4fUGjxFIuoY+e1EqZz+OYIaI8xpE1vqTcmk87KORfm5Cus8P7VyXrXVev8o4AKapfVuJh26dzwkGY6kJ0YaS5PEIEMIkEIldmgz2j8liaxWmtUhrpyEtzDFQgaNDu70KiGFNoNQBQmAFJYfOKCxhF3vhgvh2t1rr25kImGPx9AZx5NRSMl5j4pUlnvSEHcL5AjuvZJWd90E8PLrTPBVcF413BpHBuUMY4dx3gnJOKVU7HV3gjBROlYy6X9PYkYnD3bOO9lPJEb856fy8XXHx9U-FuneE0L40hUYfAGjUSIwYZYDSMQ0F43p9DX2UZgxxXCH7JI0JogRvjN5NXyZLR27xGio1SEdcIoJGiSxaKRDufw9C9lHg4hJE8XEdJ1qWHJ3SYYjU9OoUwCigH8lRqpMJe0zwDU6B8I8A87orRaerYQ34MC8DWlqKUUpyBajwBqY0AA1IggjGqbMvAjKEMsEjbk6GoKoLZ-ggn6kNYwOFrrXKcWrSmaYHlPJ1gAcQBi4Bev0vmkCxZ4LpZCYYyB0M0X0Q8bxyQ+CeB21SDBbkjG8ZFLSMXPNee8z5Py-mkr0cEKMLZ0bRD6ppOSQIfhRHYbiDEEpKB5TYlZNF5ROU6xeW8j5Xzfn-K2g8AEDxPjSFgTdYwvIL7vAJsgjQ8qpiKvMsqu5GB1VYBxX9fFGpCXEr1U3WGoITVAnCuKnQR5JAnl0ia+OAouSaV9Eo0eKBVoSjAngYQGIUDnCwNVPAlpIKfN9THHQCMcIjV9EAvCe1gxFJuhpINW4CKK2TVMVN6aRhZrEAOMuaAABmPspgAAo2YhwKHBL5hoiAuFoBqAAlFgBEzbW0YAzecQtW9i0aFLZyF4w0q3HSKRfU+QJBQDVznGRpPaVgQCXSu8o9gtSkDXU1Pq58Yhoxui0N4iQxb7u0sC94QDOg3mFrK+il6MDXvcmm5d7a734AfWs-+grEDis0FQ8KH7vjfurQop4V4+oxhOaNbY4HINQGg7e4Q97H0riQwC4IfVoRvow5Wr9uhq0yARryBRii7yo2tf2QYXAADuABFKY1AuBQBWPMRYyw1jYg0OJyT0mLgCvo1IR2zw5ZyworhnCOH3jNBiokL9lqgFssabAITYmJNSZk9VZmT79HxDQ++1j2H91yxNefBBKVE780kKB-o1mRPKfsyFlEPEQ6FByMQHAUpLQ4H5esslmEEh4dMCkC+2kD0jMQPzTSYYK2EVePzIacybUoDbZmniubSD5rDn-DeaWVBApNqC82EKrb0JCW+2NLI94ZUadVmDtX3LyalFMKT9klRYE7S43t-aB31ca2Dcdk7p1zoRDVnBk3ptQFm7AZzmEoTaC0CnK8lzLkGGrboaIvmikvGjOjT4itdtgQ0IIOUYAuBOX4FgPAD68BEGoCdlDAbN1yzAeYH4AyWxG0RmCXSF9IwKMs-M1iYBhOfdgGAVa42oDfJQFgWgUpPyEPIMQLUOBLTg-dDoTQ8NorSEvN6BopFgxqFeJu6Mh5vimxTnE382Pcf49g+5Yn2bTSrbtBqenWyng7IFvs4tRzRmSq0PDbSMg8bDcxyLnHE28cE5wVL5LolPnkG+XgBX0jN1qBTi902ULjr8haJuvc8LIh0oxza+yhuxem7AlL35BBjRODgg+z8PKQdSj1MQUTP0Q7095E0UtjQFHhT+DLLn58mimEDPhZS+v-dY6N1ADQJuJdE5Jx8uPCeiBJ6ICn9T+qEBp83VhFKpEWS57d9nB73o9qAY7kA4juIA9PIr1X8XhOpdA9ICDsHbe-VyXVwVq80Ry3gt9J8Awwvp9B5r1Lv6WKsWiXIB4PIC4ktkHl6vw2ijEZ4S5C8bO+g6HhGinJGIw+wHXhRS0SNJT6i4TaZD-jLTLQ8QK5-BK41h7KRhq7VpKRnTXivBRCw5Z5+7bCgEz544QYh4k45p5py6wHbIIH4YHKcjVrZ684GCpCnQqQCaT7l5i6EGS4k4274qkAP6pbIYhCMKozxD8wzLMLhq-p0joFmAwhlaIKH5gGV4EFkah54Cx5EDx6cz8EabViJzPBlrFqYH-CGqwyNBoHRjAgdyaSxAKH4ELQqFcFqHEAABScuWhdG7eOWbYvInIhh14xhd2Hw9BMh+gPYUIth7BDhgOwOoOCumuPhzCic-h5gKBKQXo0Y7wQWPInIrOERxu9hRB+2M2cAsA82XaSwS2soA6OA1oOoxoRK5AG2U6s686rBge+RHBteRRh2JR9OukXG3m4I4IrmtB-MzwLwOEHwZh14OBbRR+HRDhX2vAP2f2AOi+y+cRkQ+hvh-GyRJhqQMCSkiQck4UzCYIeRShBRnBs+GAaxMRK+2hnh9Y3hBhuxRSKR+6Zgga0YXYRgciwBBu8xleaAKA-4HAPsOsjms4duAozwscmkrw58bwOGQ06RuyVhDQCsIBbBE29kAAVu2mtFCWaOQfAbslQcgb+kEUcSEXIbMfRHgZ9qsLKLwD2goGBMaBAAtIIPwAoFgE4B8jkN8lqNQMaM1rojoZfHdroEjgYKcTFAKA0oCYoRoMyS2myRyVybcQIHyQKSDuQPUcKaKeKfrAIZ3hnj3tnkeK7t-onCWnuOFGYD2MFpgu0ZXmqayeye5JydyTqdEUvrEY-m6Oad3lnn3jaSoMep7oFrFHtPyBPgyTiZXigPZN7CHhwLJhiPJusJsFXnMSqSma+GbhwMcApiSMIJcEGeQkfPupbBMjCAiVljeBcQMKmcWVgLKNNlMBoBwMtN7D2tMHKHmYmW6a2UWemaWacGmRWawPTqyv1tIrIfENuMiW7uoLWHzvzHDOhgmf0IyRNicGgNARAD6dqbydLjgE5lWTDKzhEqkMYH1KVgYKud-gkK3KehSjUoci2YeceaeTyXycQBqAQHBGHhHsaEDl8nTteXzKjDEPeSVlvrpFzhVolC0KlP8OPkUndNeqgLtkSaaFeY8X6uYB7jdFeF+QcvELQWoOMQYF8Q+TUPSf0IMJgBANAe5A9GAEQFMF2ReURR4X6leDuMCDxkiSxvzMGHxolDhLeZgXIueqPL+bwJCYRdCTBShqRCWtCNuhWvhNWqCAjHtAojeMjp-jfKBO5JJuWRgDgLKPlOXM6qXE5KUdQG4EvGDD-O4S1gIVCBRLzv1OfNIflggIZW2DWq0JUpEAmlVtPFZVwDZXZVMA5X7FAE5Y-C5VgG5ZBWDFkiQhpf6ryIlEFmWgYFyLEBUhKs8I0HGSNKzl8C6aldZdObZfZWxJgqVK-O5BqFwEQItPwlle5VBRQF5SaY3FWN2OdkYEgTFOfJiRvqFbpGdNLPWHspeN8BZaMGBM1ecElQ5c-GVN1b1f1atINTlfOHld5RKe3redEFeFQvUq2LyJVVQpYgYDGtCFCHYiNnFVADteUHte1VqZilgJqjyjqiloJRNduLWDGDhJyMnD+qMtCNEOoCkK8OjENDYT9akvFYlW1f+BoMDWtNlR5fOInsnnwVDVvN8G2Map0IXk6QtVCEAojFECzdItruesKBgFwFyfAD4H0NTU1AALRI2IAi1njhjS26CRJ3QrAgmCDMnC03mHqfA4SJCfB1Vwxc6s6bodCmAURfqJy3Q417AoiHAq18yESJRCypCXI5zvAMpNCxDRSRCGBKQxW4GuQtqZo4CsUtqcFW0qAXwmo1BFI57ox87i0RCCiSzMI1VfA56l79iJhDiFRpjjijDB0IBoxGLGGWlyLWxPCcgyp-qtCVYcJIiTRKozSqrSTjVbwx17znaRKJx4yciKWxXV0mRTT5QqoZ1cSpU500HHS6R4RMqs5vnaSbU12Op12D3FRYKHVQA50yGSyJxBZiLTXRTxS+hMJyxmDFop2PgTS9210FRAQawnWQA51dBhi0pXiaSs4vBf4PCkQ+YURyzqDxCJCbVqLkzOo50jQ-AdZmy76QrWwNCnxHixymX-0ooUyL0qJbXuTAN3hnQgrgMWyQNj0jQIwtDs0NlfC6QIO3L13zQ30QA52tDRAdCO5DQRg3iYwBK7zoxMXq2NWLLqI8Ij0x0yABI4yJxfCfB8ZkOJLcJtLD0+WSmghpw3hGLlrQhZHMVjwtIYIHVdWr0yPt7hR9xSqvZJ1mEtgywiUXTlozJHjiNLJtIrLAMNUxBSxchfrXiXZpyQinz+aaSgJxLNISOtI+x8MVLAgmrir-B1UNmQi+PcNJJlzSPXVr5yNhLMKmqXhAi97WHROoL+MaJUNr1kTCHAjejnz1h3gVJghTVf2RhHi2IAk2o3L+POrqo0OoyaBwE0Q3R3itjiyYOyUywyzywukNPFzNM6Nr7+YyXSyJC+HM0Kla76AM0Mh1PbB2oOrTSX02QuoLSYrAP4QxBY3RXfATELVSqYPaQLMWogMsGGSLpQYfYN25LPqfW87GLvH8Y1mjLoyaAdy8gLMZGvAumkY3qwYPMbIMa8gmrLn4PRTIy0Epy7jmA3gZamNd2CZhZ2aqY506VM46Y4z6YSHhCEQKLGaRj1W6BdOqOha2YqYrDLDsVgBYtEuOPWEY3fBHg4Y22fBfpcgtyO13RUvhaqZV5RZoNjNVimwcgC4YH74x2FYRImblpfMyz8s2aCu0uLS-hQBplHXWiKgojhAJPisYZhgywVqRBHjbiGYmrRTG0UTRiNojYfaiuGtuhYSt2+jwzRXvC020FbGh1FIyGZGNVOuV4rBTbFFKiMv1j7O+j7z1U+u-p-AxCyIBYDKkOOtjZ7bfa-b-ZYsfrPD-CDw55MV3ZJuPZ3h7wfDpvKkV530x2o7RBGACOyFXYn0jlAmz7B5B1ituhKRtjTNHhAJggevKB56JDzNQiERfnvAtkQH44cXaMuvkIuMXZ3h7KYWJwoHmBom0KnE6CV35l2GdHE450-BnSFOiG6DiE4YT03hDsvYnGXgtnKGFFhsHZHZYtCFwGXsdw6AEsFZlJ0WQg4RFOAHPtXFdHZurHAPGCaAyyIotzcgDSjHeHv5SygeqP7mXHHsoA3H8A539HaaEOdDDHny0GXiym4bfrwwxQtkglgkQn2M8iJRRQos1AKKjufFRBonq320-DNnYmjn4mEnUM9vLvEuipf0jR0rNhUkF4WF7ShHAYulYe2poCavatQA9XWhcA-bAO9wxDAjCOQg6AvkFZmHBEpy3ixAqdJmqkskanelakAUwcKMWMhHFLMNu5DSQt7gsjwzhQyCzttnpnANeff5RB0OweQgHHxB9Q-lrBHkqX-k6lhcLVlrLXr7HFAh1Jtv9C4WjYrq31ic3k0RaCmAgfoH6BmewyH2UfoU+jhGNKsUQYLtcU8Vdk0NFLtjhhAJt0jRSWGJSxyXXgKXy2JfHlYtySaD3kpBxkpBQL7rSyOORjTNGcH5m2oN-UJUtWA3-g0Ps7NDFNPYpxmz-uhWRjeHs3DSNCMOoun243bf43JXtWpXpXewuUHeehNtmAdyncJDnfoeIzywPlZadCbXbU7e7UE1LCaM4I9V9VawMsld8w3RnS2IY1BY3hBaVX+XMhAiiGTvXMoOQ-PcOXE2idLv6L8jLW7JBWHOA-GJvUgdcjRQChWBWBAA */
+ model.createMachine(
+ {
+ predictableActionArguments: true,
+ preserveActionOrder: true,
+ tsTypes: {} as import('./scanMachine.typegen').Typegen0,
+ schema: {
+ context: model.initialContext,
+ events: {} as EventFrom,
+ services: {} as {
+ createVp: {
+ data: VC;
+ };
+ },
+ },
+ invoke: {
+ src: 'monitorConnection',
+ },
+ id: 'scan',
+ initial: 'inactive',
+ on: {
+ SCREEN_BLUR: {
+ target: '#scan.disconnectDevice',
+ },
+ SCREEN_FOCUS: {
+ target: '.checkStorage',
+ },
+ BLE_ERROR: {
+ target: '.handlingBleError',
+ actions: 'setBleError',
+ },
+ RESET: {
+ target: '.checkStorage',
+ },
+ DISMISS: {
+ target: '#scan.reviewing.navigatingToHome',
+ },
+ },
+ states: {
+ inactive: {
+ entry: 'removeLoggers',
+ },
+ disconnectDevice: {
+ invoke: {
+ src: 'disconnect',
+ },
+ on: {
+ DISCONNECT: {
+ target: '#scan.inactive',
+ },
+ },
+ },
+ checkStorage: {
+ invoke: {
+ src: 'checkStorageAvailability',
+ onDone: [
+ {
+ cond: 'isMinimumStorageRequiredForAuditEntryReached',
+ target: 'restrictSharingVc',
+ },
+ {
+ target: 'startPermissionCheck',
+ },
+ ],
+ },
+ },
+ restrictSharingVc: {},
+ startPermissionCheck: {
+ on: {
+ START_PERMISSION_CHECK: [
+ {
+ cond: 'uptoAndroid11',
+ target: '#scan.checkBluetoothPermission',
+ },
+ {
+ cond: 'isIOS',
+ target: '#scan.checkBluetoothPermission',
+ },
+ {
+ target: '#scan.checkNearbyDevicesPermission',
+ },
+ ],
+ },
+ },
+
+ checkNearbyDevicesPermission: {
+ initial: 'checking',
+ states: {
+ checking: {
+ invoke: {
+ src: 'checkNearByDevicesPermission',
+ },
+ on: {
+ NEARBY_ENABLED: {
+ target: 'enabled',
+ },
+ NEARBY_DISABLED: {
+ target: 'requesting',
+ },
+ },
+ },
+ requesting: {
+ invoke: {
+ src: 'requestNearByDevicesPermission',
+ },
+ on: {
+ NEARBY_ENABLED: {
+ target: '#scan.checkBluetoothPermission',
+ },
+ NEARBY_DISABLED: {
+ target: '#scan.nearByDevicesPermissionDenied',
+ },
+ },
+ },
+ enabled: {
+ always: {
+ target: '#scan.checkBluetoothPermission',
+ },
+ },
+ },
+ },
+
+ checkBluetoothPermission: {
+ initial: 'checking',
+ states: {
+ checking: {
+ invoke: {
+ src: 'checkBluetoothPermission',
+ },
+ on: {
+ BLUETOOTH_PERMISSION_ENABLED: {
+ actions: 'setReadyForBluetoothStateCheck',
+ target: 'enabled',
+ },
+ BLUETOOTH_PERMISSION_DENIED: {
+ target: '#scan.bluetoothPermissionDenied',
+ },
+ },
+ },
+ enabled: {
+ always: {
+ target: '#scan.checkBluetoothState',
+ },
+ },
+ },
+ },
+
+ checkBluetoothState: {
+ initial: 'checking',
+ states: {
+ checking: {
+ invoke: {
+ src: 'checkBluetoothState',
+ },
+ on: {
+ BLUETOOTH_STATE_ENABLED: {
+ target: 'enabled',
+ },
+ BLUETOOTH_STATE_DISABLED: [
+ {
+ cond: 'isIOS',
+ target: '#scan.checkBluetoothPermission',
+ },
+ {
+ target: 'requesting',
+ },
+ ],
+ },
+ },
+ requesting: {
+ invoke: {
+ src: 'requestBluetooth',
+ },
+ on: {
+ BLUETOOTH_STATE_ENABLED: {
+ target: 'enabled',
+ },
+ BLUETOOTH_STATE_DISABLED: {
+ target: '#scan.bluetoothDenied',
+ },
+ },
+ },
+ enabled: {
+ always: [
+ {
+ cond: 'uptoAndroid11',
+ target: '#scan.checkingLocationService',
+ },
+ {
+ target: '#scan.clearingConnection',
+ },
+ ],
+ },
+ },
+ },
+
+ recheckBluetoothState: {
+ initial: 'checking',
+ states: {
+ checking: {
+ invoke: {
+ src: 'checkBluetoothState',
+ },
+ on: {
+ BLUETOOTH_STATE_ENABLED: {
+ target: 'enabled',
+ },
+ BLUETOOTH_STATE_DISABLED: {
+ target: '#scan.bluetoothDenied',
+ },
+ },
+ },
+ enabled: {
+ always: [
+ {
+ cond: 'uptoAndroid11',
+ target: '#scan.checkingLocationService',
+ },
+ {
+ target: '#scan.clearingConnection',
+ },
+ ],
+ },
+ },
+ },
+
+ bluetoothPermissionDenied: {
+ on: {
+ APP_ACTIVE: '#scan.checkBluetoothState',
+ GOTO_SETTINGS: {
+ actions: 'openBluetoothSettings',
+ },
+ },
+ },
+
+ bluetoothDenied: {
+ on: {
+ APP_ACTIVE: '#scan.recheckBluetoothState',
+ },
+ },
+
+ nearByDevicesPermissionDenied: {
+ on: {
+ APP_ACTIVE: '#scan.checkNearbyDevicesPermission',
+ GOTO_SETTINGS: {
+ actions: 'openAppPermission',
+ },
+ },
+ },
+
+ clearingConnection: {
+ invoke: {
+ src: 'disconnect',
+ },
+ on: {
+ DISCONNECT: {
+ target: '#scan.findingConnection',
+ actions: [],
+ internal: false,
+ },
+ },
+ after: {
+ DESTROY_TIMEOUT: {
+ target: '#scan.findingConnection',
+ actions: [],
+ internal: false,
+ },
+ },
+ },
+ findingConnection: {
+ entry: [
+ 'removeLoggers',
+ 'registerLoggers',
+ 'clearUri',
+ 'setChildRef',
+ ],
+ on: {
+ SCAN: [
+ {
+ target: 'connecting',
+ cond: 'isOpenIdQr',
+ actions: 'setUri',
+ },
+ {
+ target: 'showQrLogin',
+ cond: 'isQrLogin',
+ actions: 'setLinkCode',
+ },
+ {
+ target: 'invalid',
+ },
+ ],
+ },
+ },
+ showQrLogin: {
+ invoke: {
+ id: 'QrLogin',
+ src: qrLoginMachine,
+ onDone: '.storing',
+ },
+ on: {
+ DISMISS: 'findingConnection',
+ },
+ initial: 'idle',
+ states: {
+ idle: {},
+ storing: {
+ entry: ['storeLoginItem'],
+ on: {
+ STORE_RESPONSE: {
+ target: 'navigatingToHistory',
+ actions: ['storingActivityLog'],
+ },
+ },
+ },
+ navigatingToHistory: {},
+ },
+ entry: 'sendScanData',
+ },
+ connecting: {
+ invoke: {
+ src: 'startConnection',
+ },
+ initial: 'inProgress',
+ states: {
+ inProgress: {
+ after: {
+ CONNECTION_TIMEOUT: {
+ target: '#scan.connecting.timeout',
+ actions: [],
+ internal: false,
+ },
+ },
+ },
+ timeout: {
+ on: {
+ CANCEL: {
+ target: '#scan.reviewing.cancelling',
+ },
+ },
+ },
+ },
+ on: {
+ CONNECTED: {
+ target: 'reviewing',
+ actions: ['setSenderInfo', 'setReceiverInfo'],
+ },
+ },
+ },
+ reviewing: {
+ entry: ['resetShouldVerifyPresence'],
+ exit: ['clearReason', 'clearCreatedVp'],
+ initial: 'selectingVc',
+ states: {
+ selectingVc: {
+ on: {
+ UPDATE_REASON: {
+ actions: 'setReason',
+ },
+ DISCONNECT: {
+ target: '#scan.disconnected',
+ },
+ SELECT_VC: {
+ actions: 'setSelectedVc',
+ },
+ VERIFY_AND_ACCEPT_REQUEST: {
+ target: 'verifyingIdentity',
+ },
+ ACCEPT_REQUEST: {
+ target: 'sendingVc',
+ actions: 'setShareLogTypeUnverified',
+ },
+ CANCEL: {
+ target: 'cancelling',
+ },
+ TOGGLE_USER_CONSENT: {
+ actions: 'toggleShouldVerifyPresence',
+ },
+ },
+ },
+ cancelling: {
+ always: {
+ target: '#scan.clearingConnection',
+ },
+ },
+ sendingVc: {
+ invoke: {
+ src: 'sendVc',
+ },
+ initial: 'inProgress',
+ states: {
+ inProgress: {
+ after: {
+ SHARING_TIMEOUT: {
+ target: '#scan.reviewing.sendingVc.timeout',
+ actions: [],
+ internal: false,
+ },
+ },
+ },
+ timeout: {
+ on: {
+ CANCEL: {
+ target: '#scan.reviewing.cancelling',
+ },
+ },
+ },
+ sent: {
+ description:
+ 'VC data has been shared and the receiver should now be viewing it',
+ on: {
+ CANCEL: {
+ target: '#scan.reviewing.cancelling',
+ },
+ },
+ },
+ },
+ on: {
+ DISCONNECT: {
+ target: '#scan.disconnected',
+ },
+ VC_SENT: {
+ target: '.sent',
+ },
+ VC_ACCEPTED: {
+ target: '#scan.reviewing.accepted',
+ },
+ VC_REJECTED: {
+ target: '#scan.reviewing.rejected',
+ },
+ CANCEL: {
+ target: '#scan.reviewing.cancelling',
+ },
+ },
+ },
+ accepted: {
+ entry: 'logShared',
+ on: {
+ DISMISS: {
+ target: 'navigatingToHome',
+ },
+ },
+ },
+ rejected: {
+ on: {
+ DISMISS: {
+ target: '#scan.clearingConnection',
+ },
+ },
+ },
+ navigatingToHome: {},
+ verifyingIdentity: {
+ on: {
+ FACE_VALID: {
+ target: 'sendingVc',
+ actions: 'setShareLogTypeVerified',
+ },
+ FACE_INVALID: {
+ target: 'invalidIdentity',
+ actions: 'logFailedVerification',
+ },
+ CANCEL: {
+ target: 'selectingVc',
+ },
+ },
+ },
+ creatingVp: {
+ invoke: {
+ src: 'createVp',
+ onDone: [
+ {
+ target: 'sendingVc',
+ actions: 'setCreatedVp',
+ },
+ ],
+ onError: [
+ {
+ target: 'selectingVc',
+ actions: log('Could not create Verifiable Presentation'),
+ },
+ ],
+ },
+ },
+ invalidIdentity: {
+ on: {
+ DISMISS: {
+ target: 'selectingVc',
+ },
+ RETRY_VERIFICATION: {
+ target: 'verifyingIdentity',
+ },
+ },
+ },
+ },
+ },
+ disconnected: {
+ on: {
+ DISMISS: {
+ target: '#scan.clearingConnection',
+ },
+ },
+ },
+ handlingBleError: {
+ on: {
+ DISMISS: {
+ target: '#scan.clearingConnection',
+ },
+ },
+ },
+ invalid: {
+ on: {
+ DISMISS: {
+ target: '#scan.clearingConnection',
+ },
+ },
+ },
+ checkingLocationService: {
+ initial: 'checkingPermissionStatus',
+ states: {
+ checkingPermissionStatus: {
+ invoke: {
+ src: 'checkLocationPermission',
+ },
+ on: {
+ LOCATION_ENABLED: {
+ target: '#scan.clearingConnection',
+ },
+ LOCATION_DISABLED: {
+ target: 'requestToEnableLocation',
+ },
+ },
+ },
+ requestToEnableLocation: {
+ invoke: {
+ src: 'requestToEnableLocationPermission',
+ },
+ on: {
+ LOCATION_ENABLED: {
+ target: '#scan.clearingConnection',
+ },
+ LOCATION_DISABLED: {
+ target: 'denied',
+ },
+ },
+ },
+ denied: {
+ on: {
+ APP_ACTIVE: {
+ target: 'checkingPermissionStatus',
+ },
+ LOCATION_REQUEST: {
+ actions: 'openAppPermission',
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ actions: {
+ setChildRef: assign({
+ QrLoginRef: (context) => {
+ const service = spawn(
+ createQrLoginMachine(context.serviceRefs),
+ QR_LOGIN_REF_ID
+ );
+ service.subscribe(logState);
+ return service;
+ },
+ }),
+
+ sendScanData: (context) =>
+ context.QrLoginRef.send({
+ type: 'GET',
+ value: context.linkCode,
+ }),
+ openBluetoothSettings: () => {
+ Platform.OS === 'android'
+ ? BluetoothStateManager.openSettings().catch()
+ : Linking.openURL('App-Prefs:Bluetooth');
+ },
+
+ openAppPermission: () => Linking.openSettings(),
+
+ setUri: model.assign({
+ openId4VpUri: (_context, event) => event.params,
+ }),
+
+ clearUri: assign({
+ openId4VpUri: '',
+ }),
+
+ setSenderInfo: assign({
+ senderInfo: () => {
+ return { name: 'Wallet', deviceName: 'Wallet', deviceId: '' };
+ },
+ }),
+
+ setReceiverInfo: assign({
+ receiverInfo: () => {
+ return { name: 'Verifier', deviceName: 'Verifier', deviceId: '' };
+ },
+ }),
+
+ setReadyForBluetoothStateCheck: model.assign({
+ readyForBluetoothStateCheck: () => true,
+ }),
+
+ setBleError: assign({
+ bleError: (_context, event) => event.bleError,
+ }),
+
+ setReason: model.assign({
+ reason: (_context, event) => event.reason,
+ }),
+
+ clearReason: assign({ reason: '' }),
+
+ setSelectedVc: assign({
+ selectedVc: (context, event) => {
+ return {
+ ...event.vc,
+ shouldVerifyPresence: context.selectedVc.shouldVerifyPresence,
+ };
+ },
+ }),
+
+ setCreatedVp: assign({
+ createdVp: (_context, event) => event.data,
+ }),
+
+ clearCreatedVp: assign({
+ createdVp: () => null,
+ }),
+
+ registerLoggers: assign({
+ loggers: () => {
+ if (__DEV__) {
+ return [
+ wallet.handleDataEvents((event) => {
+ console.log(
+ getDeviceNameSync(),
+ '',
+ JSON.stringify(event).slice(0, 100)
+ );
+ }),
+ ];
+ } else {
+ return [];
+ }
+ },
+ }),
+
+ removeLoggers: assign({
+ loggers: ({ loggers }) => {
+ loggers?.forEach((logger) => logger.remove());
+ return [];
+ },
+ }),
+
+ setShareLogTypeUnverified: model.assign({
+ shareLogType: 'VC_SHARED',
+ }),
+
+ setShareLogTypeVerified: model.assign({
+ shareLogType: 'PRESENCE_VERIFIED_AND_VC_SHARED',
+ }),
+
+ logShared: send(
+ (context) =>
+ ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: VC_ITEM_STORE_KEY(context.selectedVc),
+ type: context.selectedVc.shouldVerifyPresence
+ ? 'VC_SHARED_WITH_VERIFICATION_CONSENT'
+ : context.shareLogType,
+ timestamp: Date.now(),
+ deviceName:
+ context.receiverInfo.name || context.receiverInfo.deviceName,
+ vcLabel: context.selectedVc.tag || context.selectedVc.id,
+ }),
+ { to: (context) => context.serviceRefs.activityLog }
+ ),
+
+ logFailedVerification: send(
+ (context) =>
+ ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: VC_ITEM_STORE_KEY(context.selectedVc),
+ type: 'PRESENCE_VERIFICATION_FAILED',
+ timestamp: Date.now(),
+ deviceName:
+ context.receiverInfo.name || context.receiverInfo.deviceName,
+ vcLabel: context.selectedVc.tag || context.selectedVc.id,
+ }),
+ { to: (context) => context.serviceRefs.activityLog }
+ ),
+
+ toggleShouldVerifyPresence: assign({
+ selectedVc: (context) => ({
+ ...context.selectedVc,
+ shouldVerifyPresence: !context.selectedVc.shouldVerifyPresence,
+ }),
+ }),
+
+ setLinkCode: assign({
+ linkCode: (_context, event) =>
+ event.params.substring(
+ event.params.indexOf('linkCode=') + 9,
+ event.params.indexOf('&')
+ ),
+ }),
+
+ resetShouldVerifyPresence: assign({
+ selectedVc: (context) => ({
+ ...context.selectedVc,
+ shouldVerifyPresence: false,
+ }),
+ }),
+
+ storeLoginItem: send(
+ (_context, event) => {
+ return StoreEvents.PREPEND(
+ MY_LOGIN_STORE_KEY,
+ (event as DoneInvokeEvent).data
+ );
+ },
+ { to: (context) => context.serviceRefs.store }
+ ),
+
+ storingActivityLog: send(
+ (_, event) =>
+ ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: '',
+ type: 'QRLOGIN_SUCCESFULL',
+ timestamp: Date.now(),
+ deviceName: '',
+ vcLabel: String(event.response.selectedVc.id),
+ }),
+ {
+ to: (context) => context.serviceRefs.activityLog,
+ }
+ ),
+ },
+
+ services: {
+ checkBluetoothPermission: () => async (callback) => {
+ // wait a bit for animation to finish when app becomes active
+ await new Promise((resolve) => setTimeout(resolve, 250));
+ try {
+ // Passing Granted for android since permission status is always granted even if its denied.
+ let response: PermissionStatus = RESULTS.GRANTED;
+
+ if (Platform.OS === 'ios') {
+ response = await check(PERMISSIONS.IOS.BLUETOOTH_PERIPHERAL);
+ }
+
+ if (response === RESULTS.GRANTED) {
+ callback(model.events.BLUETOOTH_PERMISSION_ENABLED());
+ } else {
+ callback(model.events.BLUETOOTH_PERMISSION_DENIED());
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ checkBluetoothState: () => (callback) => {
+ const subscription = BluetoothStateManager.onStateChange((state) => {
+ if (state === 'PoweredOn') {
+ callback(model.events.BLUETOOTH_STATE_ENABLED());
+ } else {
+ callback(model.events.BLUETOOTH_STATE_DISABLED());
+ }
+ }, true);
+ return () => subscription.remove();
+ },
+
+ requestBluetooth: () => (callback) => {
+ BluetoothStateManager.requestToEnable()
+ .then(() => callback(model.events.BLUETOOTH_STATE_ENABLED()))
+ .catch(() => callback(model.events.BLUETOOTH_STATE_DISABLED()));
+ },
+
+ requestToEnableLocationPermission: () => (callback) => {
+ requestLocationPermission(
+ () => callback(model.events.LOCATION_ENABLED()),
+ () => callback(model.events.LOCATION_DISABLED())
+ );
+ },
+
+ monitorConnection: () => (callback) => {
+ const subscription = wallet.handleDataEvents((event) => {
+ if (event.type === EventTypes.onDisconnected) {
+ callback({ type: 'DISCONNECT' });
+ }
+ if (event.type === EventTypes.onError) {
+ callback({
+ type: 'BLE_ERROR',
+ bleError: { message: event.message, code: event.code },
+ });
+ console.log('BLE Exception: ' + event.message);
+ }
+ });
+
+ return () => subscription.remove();
+ },
+
+ checkNearByDevicesPermission: () => (callback) => {
+ checkMultiple([
+ PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
+ PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
+ ])
+ .then((response) => {
+ if (
+ response[PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE] ===
+ RESULTS.GRANTED &&
+ response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
+ RESULTS.GRANTED
+ ) {
+ callback(model.events.NEARBY_ENABLED());
+ } else {
+ callback(model.events.NEARBY_DISABLED());
+ }
+ })
+ .catch((err) => {
+ callback(model.events.NEARBY_DISABLED());
+ });
+ },
+
+ requestNearByDevicesPermission: () => (callback) => {
+ requestMultiple([
+ PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
+ PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
+ ])
+ .then((response) => {
+ if (
+ response[PERMISSIONS.ANDROID.BLUETOOTH_SCAN] ===
+ RESULTS.GRANTED &&
+ response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
+ RESULTS.GRANTED
+ ) {
+ callback(model.events.NEARBY_ENABLED());
+ } else {
+ callback(model.events.NEARBY_DISABLED());
+ }
+ })
+ .catch((err) => {
+ callback(model.events.NEARBY_DISABLED());
+ });
+ },
+
+ checkLocationPermission: () => (callback) => {
+ checkLocationPermissionStatus(
+ () => callback(model.events.LOCATION_ENABLED()),
+ () => callback(model.events.LOCATION_DISABLED())
+ );
+ },
+
+ startConnection: (context) => (callback) => {
+ wallet.startConnection(context.openId4VpUri);
+ const statusCallback = (event: WalletDataEvent) => {
+ if (event.type === EventTypes.onSecureChannelEstablished) {
+ callback({ type: 'CONNECTED' });
+ }
+ };
+
+ const subscription = subscribe(statusCallback);
+ return () => subscription?.remove();
+ },
+
+ sendVc: (context) => (callback) => {
+ const vp = context.createdVp;
+ const vc = {
+ ...(vp != null ? vp : context.selectedVc),
+ tag: '',
+ };
+
+ const reason = [];
+ if (context.reason.trim() !== '') {
+ reason.push({ message: context.reason, timestamp: Date.now() });
+ }
+
+ const statusCallback = (event: WalletDataEvent) => {
+ if (event.type === EventTypes.onDataSent) {
+ callback({ type: 'VC_SENT' });
+ } else if (event.type === EventTypes.onVerificationStatusReceived) {
+ callback({
+ type:
+ event.status === VerificationStatus.ACCEPTED
+ ? 'VC_ACCEPTED'
+ : 'VC_REJECTED',
+ });
+ }
+ };
+ wallet.sendData(
+ JSON.stringify({
+ ...vc,
+ reason,
+ })
+ );
+ const subscription = subscribe(statusCallback);
+ return () => subscription?.remove();
+ },
+
+ disconnect: () => () => {
+ try {
+ wallet.disconnect();
+ } catch (e) {
+ // pass
+ }
+ },
+
+ createVp: (context) => async () => {
+ // const verifiablePresentation = await createVerifiablePresentation(...);
+
+ const verifiablePresentation: VerifiablePresentation = {
+ '@context': [''],
+ 'proof': null,
+ 'type': 'VerifiablePresentation',
+ 'verifiableCredential': [context.selectedVc.verifiableCredential],
+ };
+
+ const vc: VC = {
+ ...context.selectedVc,
+ verifiableCredential: null,
+ verifiablePresentation,
+ };
+
+ return Promise.resolve(vc);
+ },
+
+ checkStorageAvailability: () => async () => {
+ return Promise.resolve(
+ Storage.isMinimumLimitReached('minStorageRequiredForAuditEntry')
+ );
+ },
+ },
+
+ guards: {
+ isOpenIdQr: (_context, event) => event.params.includes('OPENID4VP://'),
+
+ isQrLogin: (_context, event) => {
+ let linkCode = '';
+ try {
+ linkCode = event.params.substring(
+ event.params.indexOf('linkCode=') + 9,
+ event.params.indexOf('&')
+ );
+ return linkCode !== null;
+ } catch (e) {
+ return false;
+ }
+ },
+
+ uptoAndroid11: () => Platform.OS === 'android' && Platform.Version < 31,
+
+ isIOS: () => Platform.OS === 'ios',
+
+ isMinimumStorageRequiredForAuditEntryReached: (_context, event) =>
+ Boolean(event.data),
+ },
+
+ delays: {
+ DESTROY_TIMEOUT: 500,
+ CONNECTION_TIMEOUT: 5 * 1000,
+ SHARING_TIMEOUT: 15 * 1000,
+ },
+ }
+ );
+
+type State = StateFrom;
+
+export function createScanMachine(serviceRefs: AppServices) {
+ return scanMachine.withContext({
+ ...scanMachine.context,
+ serviceRefs,
+ });
+}
+
+export function selectIsMinimumStorageRequiredForAuditEntryLimitReached(
+ state: State
+) {
+ return state.matches('restrictSharingVc');
+}
diff --git a/machines/bleShare/scan/scanMachine.typegen.ts b/machines/bleShare/scan/scanMachine.typegen.ts
new file mode 100644
index 00000000..e7c323e7
--- /dev/null
+++ b/machines/bleShare/scan/scanMachine.typegen.ts
@@ -0,0 +1,231 @@
+// This file was automatically generated. Edits will be overwritten
+
+export interface Typegen0 {
+ '@@xstate/typegen': true;
+ 'internalEvents': {
+ '': { type: '' };
+ 'done.invoke.QrLogin': {
+ type: 'done.invoke.QrLogin';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
+ 'done.invoke.scan.checkStorage:invocation[0]': {
+ type: 'done.invoke.scan.checkStorage:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
+ 'done.invoke.scan.reviewing.creatingVp:invocation[0]': {
+ type: 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
+ 'xstate.after(CONNECTION_TIMEOUT)#scan.connecting.inProgress': {
+ type: 'xstate.after(CONNECTION_TIMEOUT)#scan.connecting.inProgress';
+ };
+ 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection': {
+ type: 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
+ };
+ 'xstate.after(SHARING_TIMEOUT)#scan.reviewing.sendingVc.inProgress': {
+ type: 'xstate.after(SHARING_TIMEOUT)#scan.reviewing.sendingVc.inProgress';
+ };
+ 'xstate.init': { type: 'xstate.init' };
+ 'xstate.stop': { type: 'xstate.stop' };
+ };
+ 'invokeSrcNameMap': {
+ checkBluetoothPermission: 'done.invoke.scan.checkBluetoothPermission.checking:invocation[0]';
+ checkBluetoothState:
+ | 'done.invoke.scan.checkBluetoothState.checking:invocation[0]'
+ | 'done.invoke.scan.recheckBluetoothState.checking:invocation[0]';
+ checkLocationPermission: 'done.invoke.scan.checkingLocationService.checkingPermissionStatus:invocation[0]';
+ checkNearByDevicesPermission: 'done.invoke.scan.checkNearbyDevicesPermission.checking:invocation[0]';
+ checkStorageAvailability: 'done.invoke.scan.checkStorage:invocation[0]';
+ createVp: 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
+ disconnect:
+ | 'done.invoke.scan.clearingConnection:invocation[0]'
+ | 'done.invoke.scan.disconnectDevice:invocation[0]';
+ monitorConnection: 'done.invoke.scan:invocation[0]';
+ requestBluetooth: 'done.invoke.scan.checkBluetoothState.requesting:invocation[0]';
+ requestNearByDevicesPermission: 'done.invoke.scan.checkNearbyDevicesPermission.requesting:invocation[0]';
+ requestToEnableLocationPermission: 'done.invoke.scan.checkingLocationService.requestToEnableLocation:invocation[0]';
+ sendVc: 'done.invoke.scan.reviewing.sendingVc:invocation[0]';
+ startConnection: 'done.invoke.scan.connecting:invocation[0]';
+ };
+ 'missingImplementations': {
+ actions: never;
+ delays: never;
+ guards: never;
+ services: never;
+ };
+ 'eventsCausingActions': {
+ clearCreatedVp:
+ | ''
+ | 'BLE_ERROR'
+ | 'DISCONNECT'
+ | 'DISMISS'
+ | 'RESET'
+ | 'SCREEN_BLUR'
+ | 'SCREEN_FOCUS'
+ | 'xstate.stop';
+ clearReason:
+ | ''
+ | 'BLE_ERROR'
+ | 'DISCONNECT'
+ | 'DISMISS'
+ | 'RESET'
+ | 'SCREEN_BLUR'
+ | 'SCREEN_FOCUS'
+ | 'xstate.stop';
+ clearUri:
+ | 'DISCONNECT'
+ | 'DISMISS'
+ | 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
+ logFailedVerification: 'FACE_INVALID';
+ logShared: 'VC_ACCEPTED';
+ openAppPermission: 'GOTO_SETTINGS' | 'LOCATION_REQUEST';
+ openBluetoothSettings: 'GOTO_SETTINGS';
+ registerLoggers:
+ | 'DISCONNECT'
+ | 'DISMISS'
+ | 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
+ removeLoggers:
+ | 'DISCONNECT'
+ | 'DISMISS'
+ | 'SCREEN_BLUR'
+ | 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection'
+ | 'xstate.init';
+ resetShouldVerifyPresence: 'CANCEL' | 'CONNECTED' | 'DISMISS';
+ sendScanData: 'SCAN';
+ setBleError: 'BLE_ERROR';
+ setChildRef:
+ | 'DISCONNECT'
+ | 'DISMISS'
+ | 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
+ setCreatedVp: 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
+ setLinkCode: 'SCAN';
+ setReadyForBluetoothStateCheck: 'BLUETOOTH_PERMISSION_ENABLED';
+ setReason: 'UPDATE_REASON';
+ setReceiverInfo: 'CONNECTED';
+ setSelectedVc: 'SELECT_VC';
+ setSenderInfo: 'CONNECTED';
+ setShareLogTypeUnverified: 'ACCEPT_REQUEST';
+ setShareLogTypeVerified: 'FACE_VALID';
+ setUri: 'SCAN';
+ storeLoginItem: 'done.invoke.QrLogin';
+ storingActivityLog: 'STORE_RESPONSE';
+ toggleShouldVerifyPresence: 'TOGGLE_USER_CONSENT';
+ };
+ 'eventsCausingDelays': {
+ CONNECTION_TIMEOUT: 'SCAN';
+ DESTROY_TIMEOUT: '' | 'DISMISS' | 'LOCATION_ENABLED';
+ SHARING_TIMEOUT:
+ | 'ACCEPT_REQUEST'
+ | 'FACE_VALID'
+ | 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
+ };
+ 'eventsCausingGuards': {
+ isIOS: 'BLUETOOTH_STATE_DISABLED' | 'START_PERMISSION_CHECK';
+ isMinimumStorageRequiredForAuditEntryReached: 'done.invoke.scan.checkStorage:invocation[0]';
+ isOpenIdQr: 'SCAN';
+ isQrLogin: 'SCAN';
+ uptoAndroid11: '' | 'START_PERMISSION_CHECK';
+ };
+ 'eventsCausingServices': {
+ QrLogin: 'SCAN';
+ checkBluetoothPermission:
+ | ''
+ | 'BLUETOOTH_STATE_DISABLED'
+ | 'NEARBY_ENABLED'
+ | 'START_PERMISSION_CHECK';
+ checkBluetoothState: '' | 'APP_ACTIVE';
+ checkLocationPermission: '' | 'APP_ACTIVE';
+ checkNearByDevicesPermission: 'APP_ACTIVE' | 'START_PERMISSION_CHECK';
+ checkStorageAvailability: 'RESET' | 'SCREEN_FOCUS';
+ createVp: never;
+ disconnect: '' | 'DISMISS' | 'LOCATION_ENABLED' | 'SCREEN_BLUR';
+ monitorConnection: 'DISMISS' | 'SCREEN_BLUR' | 'xstate.init';
+ requestBluetooth: 'BLUETOOTH_STATE_DISABLED';
+ requestNearByDevicesPermission: 'NEARBY_DISABLED';
+ requestToEnableLocationPermission: 'LOCATION_DISABLED';
+ sendVc:
+ | 'ACCEPT_REQUEST'
+ | 'FACE_VALID'
+ | 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
+ startConnection: 'SCAN';
+ };
+ 'matchesStates':
+ | 'bluetoothDenied'
+ | 'bluetoothPermissionDenied'
+ | 'checkBluetoothPermission'
+ | 'checkBluetoothPermission.checking'
+ | 'checkBluetoothPermission.enabled'
+ | 'checkBluetoothState'
+ | 'checkBluetoothState.checking'
+ | 'checkBluetoothState.enabled'
+ | 'checkBluetoothState.requesting'
+ | 'checkNearbyDevicesPermission'
+ | 'checkNearbyDevicesPermission.checking'
+ | 'checkNearbyDevicesPermission.enabled'
+ | 'checkNearbyDevicesPermission.requesting'
+ | 'checkStorage'
+ | 'checkingLocationService'
+ | 'checkingLocationService.checkingPermissionStatus'
+ | 'checkingLocationService.denied'
+ | 'checkingLocationService.requestToEnableLocation'
+ | 'clearingConnection'
+ | 'connecting'
+ | 'connecting.inProgress'
+ | 'connecting.timeout'
+ | 'disconnectDevice'
+ | 'disconnected'
+ | 'findingConnection'
+ | 'handlingBleError'
+ | 'inactive'
+ | 'invalid'
+ | 'nearByDevicesPermissionDenied'
+ | 'recheckBluetoothState'
+ | 'recheckBluetoothState.checking'
+ | 'recheckBluetoothState.enabled'
+ | 'restrictSharingVc'
+ | 'reviewing'
+ | 'reviewing.accepted'
+ | 'reviewing.cancelling'
+ | 'reviewing.creatingVp'
+ | 'reviewing.invalidIdentity'
+ | 'reviewing.navigatingToHome'
+ | 'reviewing.rejected'
+ | 'reviewing.selectingVc'
+ | 'reviewing.sendingVc'
+ | 'reviewing.sendingVc.inProgress'
+ | 'reviewing.sendingVc.sent'
+ | 'reviewing.sendingVc.timeout'
+ | 'reviewing.verifyingIdentity'
+ | 'showQrLogin'
+ | 'showQrLogin.idle'
+ | 'showQrLogin.navigatingToHistory'
+ | 'showQrLogin.storing'
+ | 'startPermissionCheck'
+ | {
+ checkBluetoothPermission?: 'checking' | 'enabled';
+ checkBluetoothState?: 'checking' | 'enabled' | 'requesting';
+ checkNearbyDevicesPermission?: 'checking' | 'enabled' | 'requesting';
+ checkingLocationService?:
+ | 'checkingPermissionStatus'
+ | 'denied'
+ | 'requestToEnableLocation';
+ connecting?: 'inProgress' | 'timeout';
+ recheckBluetoothState?: 'checking' | 'enabled';
+ reviewing?:
+ | 'accepted'
+ | 'cancelling'
+ | 'creatingVp'
+ | 'invalidIdentity'
+ | 'navigatingToHome'
+ | 'rejected'
+ | 'selectingVc'
+ | 'sendingVc'
+ | 'verifyingIdentity'
+ | { sendingVc?: 'inProgress' | 'sent' | 'timeout' };
+ showQrLogin?: 'idle' | 'navigatingToHistory' | 'storing';
+ };
+ 'tags': never;
+}
diff --git a/machines/bleShare/scan/selectors.ts b/machines/bleShare/scan/selectors.ts
new file mode 100644
index 00000000..7174b939
--- /dev/null
+++ b/machines/bleShare/scan/selectors.ts
@@ -0,0 +1,80 @@
+import { StateFrom } from 'xstate';
+import { scanMachine } from './scanMachine';
+
+type State = StateFrom;
+
+export function selectReceiverInfo(state: State) {
+ return state.context.receiverInfo;
+}
+
+export function selectReason(state: State) {
+ return state.context.reason;
+}
+
+export function selectVcName(state: State) {
+ return state.context.vcName;
+}
+
+export function selectSelectedVc(state: State) {
+ return state.context.selectedVc;
+}
+
+export function selectQrLoginRef(state: State) {
+ return state.context.QrLoginRef;
+}
+
+export function selectIsScanning(state: State) {
+ return state.matches('findingConnection');
+}
+
+export function selectIsConnecting(state: State) {
+ return state.matches('connecting.inProgress');
+}
+
+export function selectIsConnectingTimeout(state: State) {
+ return state.matches('connecting.timeout');
+}
+
+export function selectIsSelectingVc(state: State) {
+ return state.matches('reviewing.selectingVc');
+}
+
+export function selectIsSendingVc(state: State) {
+ return state.matches('reviewing.sendingVc.inProgress');
+}
+
+export function selectIsSendingVcTimeout(state: State) {
+ return state.matches('reviewing.sendingVc.timeout');
+}
+
+export function selectIsSent(state: State) {
+ return state.matches('reviewing.sendingVc.sent');
+}
+
+export function selectIsInvalid(state: State) {
+ return state.matches('invalid');
+}
+
+export function selectIsLocationDenied(state: State) {
+ return state.matches('checkingLocationService.denied');
+}
+
+export function selectIsLocationDisabled(state: State) {
+ return state.matches('checkingLocationService.disabled');
+}
+
+export function selectIsShowQrLogin(state: State) {
+ return state.matches('showQrLogin');
+}
+
+export function selectIsQrLoginDone(state: State) {
+ return state.matches('showQrLogin.navigatingToHistory');
+}
+
+export function selectIsQrLoginStoring(state: State) {
+ return state.matches('showQrLogin.storing');
+}
+
+export function selectIsDone(state: State) {
+ return state.matches('reviewing.navigatingToHome');
+}
diff --git a/machines/bleShare/types.ts b/machines/bleShare/types.ts
new file mode 100644
index 00000000..c1672d8f
--- /dev/null
+++ b/machines/bleShare/types.ts
@@ -0,0 +1,4 @@
+export interface BLEError {
+ message?: string;
+ code?: string;
+}
diff --git a/machines/request.ts b/machines/request.ts
deleted file mode 100644
index 0fef357c..00000000
--- a/machines/request.ts
+++ /dev/null
@@ -1,999 +0,0 @@
-/* eslint-disable sonarjs/no-duplicate-string */
-import SmartshareReactNative from '@idpass/smartshare-react-native';
-const { IdpassSmartshare, GoogleNearbyMessages } = SmartshareReactNative;
-
-import uuid from 'react-native-uuid';
-import BluetoothStateManager from 'react-native-bluetooth-state-manager';
-import { EmitterSubscription, Linking, Platform } from 'react-native';
-import { assign, EventFrom, send, sendParent, StateFrom } from 'xstate';
-import { createModel } from 'xstate/lib/model';
-import { DeviceInfo } from '../components/DeviceInfoList';
-import { getDeviceNameSync } from 'react-native-device-info';
-import { StoreEvents } from './store';
-import { VC } from '../types/vc';
-import { AppServices } from '../shared/GlobalContext';
-import {
- GNM_API_KEY,
- RECEIVED_VCS_STORE_KEY,
- VC_ITEM_STORE_KEY,
-} from '../shared/constants';
-import { ActivityLogEvents, ActivityLogType } from './activityLog';
-import { VcEvents } from './vc';
-import { ConnectionParams } from '@idpass/smartshare-react-native/lib/typescript/IdpassSmartshare';
-import {
- ExchangeReceiverInfoEvent,
- onlineSubscribe,
- offlineSubscribe,
- PairingResponseEvent,
- onlineSend,
- offlineSend,
- SendVcResponseEvent,
-} from '../shared/smartshare';
-import { log } from 'xstate/lib/actions';
-import NetInfo from '@react-native-community/netinfo';
-// import { verifyPresentation } from '../shared/vcjs/verifyPresentation';
-
-type SharingProtocol = 'OFFLINE' | 'ONLINE';
-
-const model = createModel(
- {
- serviceRefs: {} as AppServices,
- senderInfo: {} as DeviceInfo,
- receiverInfo: {} as DeviceInfo,
- incomingVc: {} as VC,
- connectionParams: '',
- loggers: [] as EmitterSubscription[],
- sharingProtocol: (Platform.OS === 'ios'
- ? 'ONLINE'
- : 'OFFLINE') as SharingProtocol,
- receiveLogType: '' as ActivityLogType,
- pairId: '',
- },
- {
- events: {
- ACCEPT: () => ({}),
- ACCEPT_AND_VERIFY: () => ({}),
- REJECT: () => ({}),
- CANCEL: () => ({}),
- DISMISS: () => ({}),
- VC_RECEIVED: (vc: VC) => ({ vc }),
- CONNECTED: (pairId?: string) => ({ pairId: pairId || '' }),
- DISCONNECT: () => ({}),
- EXCHANGE_DONE: (senderInfo: DeviceInfo) => ({ senderInfo }),
- SCREEN_FOCUS: () => ({}),
- SCREEN_BLUR: () => ({}),
- BLUETOOTH_ENABLED: () => ({}),
- BLUETOOTH_DISABLED: () => ({}),
- STORE_READY: () => ({}),
- STORE_RESPONSE: (response: unknown) => ({ response }),
- RECEIVE_DEVICE_INFO: (info: DeviceInfo) => ({ info }),
- RECEIVED_VCS_UPDATED: () => ({}),
- VC_RESPONSE: (response: unknown) => ({ response }),
- SWITCH_PROTOCOL: (value: boolean) => ({ value }),
- GOTO_SETTINGS: () => ({}),
- FACE_VALID: () => ({}),
- FACE_INVALID: () => ({}),
- RETRY_VERIFICATION: () => ({}),
- ONLINE: () => ({}),
- OFFLINE: () => ({}),
- APP_ACTIVE: () => ({}),
- },
- }
-);
-
-export const RequestEvents = model.events;
-
-export const requestMachine =
- /** @xstate-layout N4IgpgJg5mDOIC5QCcwEcCucAuBiAygMIBKAoqQHID6AQgDICqxA2gAwC6ioADgPawBLbAN4A7LiAAeiAIwAmAMysAdKxkKA7AFY1ADgAsurQDYNAGhABPRAFoAnBrnK7RuVpm6NuuQY0BfPwtUTBwCEnJqADEAeUIGfDZOJBA+QWExCWkELS19ZW9jOTlC1mNjGTsZC2sEeztjZw19OXrvVl1jBTkAoPQsWDwiMkoqGLiEmSSefiERcWSs3SXlYv0NGQ1y9sMFats7OTycw-1WNbdchR6QYP7BgHUASQAVQgAJKgAFYmjn2Oi6IkJKlZhkFrItAplBoXDlmo4ZMZdKw5HtajI1E5mg5jJVkVoitdbqF8E9Xh9vr9-oDJsCZul5qAsoi8qxWDklnIZOctHY0TZeVCZIjNFpvF5ITIiX0cMoAMYACzAcoA1gJRFAaAAbLDYXi8bAK-BgZAANwEcrAuAAgp9PlRrYRno8AGqkIHJEEMzKIBT1VQdEwwppNFzmKy2XENQ5LRGmLTB7qBG4ygbypWq9WanVgPUGo0m82W9PKtUa3D0BikP6-D6Ua30UgAEQ90zScx9CE6DRR+jsOh2pSW-IUHWU7gOXQ2UbWWmlITTitLWe1uv1huNZotYBLmfLler0VrVCbj3wDbozdbKXpHfBCHxyn0xjOwpc3kqxn5facuLsdlYdZuXqdp-GTYlFwzMtszXfNNyLHcIOEfdGEPY960bFsODpdswSZWQZHcFYFH0eR9EhToNG0b9PGUJEqMMHJjHcXQpXA1NsF3aDV1zdcCy3YskKzCtUJrZ4PlPc9MOvL073whBuQULR8gUbk1EcBRVK-CNak6FRFFKORWH-GFcXnO4uJXHM8w3Qtt2UMBRAAQwAIy1SBcBk288KkWQUTsZRuRyQVSkMcMahsQ4ZDozSOn7MoDGaOd2IXTi3Ngw0m0cgQPIAcSpKh8GrZ0KFyhJsM9bzGV8hTyg0ZxNAOXwznWGioVxLlSORZ8tmS3pUvldynOQLNCDEURlQZXBJAGJzsB3JyADN5uQAAKQhL2tYgT1IOhrQATQASlwJDBrAYbRvGya5i83DqqyBxdGUEijBcADdDsfR+ScNlEQ8DRAIS0c+pTAaAHcnNmDVIl4ZAxtECa5SmwhogoChSCdK8KrbUF7r8lEn2YppNPUJTSLRLohUpoxhX0Z9zNlCGoagGG4aupG5lwSSUbRjHnlu3HO3UQ4VmY047CUYVeS0NEWgaLoiYJOmDkKK4Uos7hUG4C6NWeXhSEkRUnI1MBHlERbeFwMhCFIV1SB2l1HhtqhHgoGIBe9e96mU-tgzFBQyhacLEATFRNnaAOCX-Ps7AZtMwENhVjagLMsoQs2LdwUgAA13mtUr7abVH3Wxm87s7FwoWKYoqJ0QUEzRYUCdYzZyIDozPrjziE6NjVU7AdPzd4ZR1U+ZBeCgVBYFgabZvm5QlpW9bUfRp1HlRqhnQAWVIaIGGeY7Tp7pO+41NPtwz4fR-Hye4FgD25JqjEPBWVgSPI1ZWp0pYnufLl+0Auyeoxgu4OUTsnfug8LbKGEAAWzALwDAeBCD5xtoCUuskfJZBfMpToqk3DsjZJpbSNQJbKQ-mLdYpQlKx3VozSGyEWawxdHKLmZ4ear35hgqqQs-QBWYi+JKMcOi6Ebj4ZScgGJrA8FyEwat+oWSZow1mLDcAukIFQa2ts3RYSmGXQWXsXBPg8B0TYJF-q7B0hsHwKlCIoh0OyIw+hQFKKzCouUI9RBjwnlPGeM1sBzQWstE0q18BvC2q7XKm9Hg7z3gfE6HFlCuOhswjx18fF3wflgvySh8gbAlgHbw7glKNzpvVUOYoExGSqS4hhbjUkwIEPAxByDUG7SyXjLsbJVB-ybkpAwuJG46GisiTQH0DinB-KAuUxtLRai1MJfxgSF7BLWigigaDomxP3ofRJMzRBzIWRqDpnYWgqCViRXEAMzFuApppFYEtEQMSoj-UBqBzRgDBsJR0NtPhcL0ZgzpJEnD1DIUxYyn1ISy3ZHkCUhhCiGCAW8geOUvnlh+aQP5DoKBNioG6YgjxIj7ROfeF8IyKjaEhC0KWfIdJGSotCEofZALFHUMij5aKoBW1IAAKT5iS+SGJWKBTWJUGEhSerQoZZsIyzLHDlGKOy1Fwl1loIFTVPE+QALaFDAYHwqI6WAXqjKs42rWWKroWmd5yqNTKFNCaAQi1LBZkeBARywhsCWFwJER09sXTWjoI8XROEDHyVFdCXIGglKQlyJ9A1NRDg6GcOpPsngdDeHkaDCy1rPlZjtQ6p1Lq3WiA9V6n1ztXb+sDcGyq5d7xUOhABAkQZ+y6FHLLciKgAIbFTdodoiglW5ttfakahaNSuvdUIL1qr2ncLrYK6hgULkBxIkxWWigoQAXFu0QoUsQanRzZyzxponILIgBOktU62H4C3mecqAKeH1qaE+D6IZeS1w8LLJEeQPBDmYkYHItCFGykPXm9UJ6z0XtLdy54xB9p4tIASyITtrTOlRuqxYRgGqnCuUpNQn1Zb9OcDkLwn0NgA2cZazioHh0FudRqF03BcAQDEDucDvAVSIUSTRqA+bR30agIxhA7GZkMkSBhiEuTThFEMD4QCaxg4IGrgFNt6wujNE0IBQdR6R2OoE4x3AJpx7IGUNwLUc0LbIFgcoA9KKh28d02OwT3BhOiFNLwUTN0OASYUpKFYRReTCi8KOURdLNL1VFSRfskigrabzU5OUlpuCMJsxxLMxBlRgAEPaiALCZ7qM0aQfAnxUZFR89oX8CZXqmQ8A3Olb0nxUVAhRf9+7uN2aPQlpLKWhIagy5abLkA8tqI0WQYrpX3S0lraGp+8h6qESbvINQFKvr1Y+o1gGaaA6tbi7arrYBkt5t61AA2AgBhZlUfgP4ZBCvjYoGVudM3FilCfJG7bTROgEZ0pTFQ8gAFNVIp9MCwGrUdfi4lg7KX4HIBTuOg5vBYEXdYVd6IN2xslfuyXB986arIgaORNY7I-SnE8KFmoSl1CBX7NyUMGk2Ig+o2DvbEPDu2s1gdxyEB0uZcG7l5H137bo4mz54UuI6Jimi0AnQtLycGUCi0aXPhAdrF27x-brPeMDFhkjggAvbsY4e9jp7BExf-oOLySc3hVvk+KVT9waw+x09VwvFn80IDXtvfge9IbPbyQMFCTYjg2RIhyJpGXvpWJPTftoZEnhNgxud6gAAVpNDyklPfe+m77p+wZAr9PkOoVityrHRfyD4cooKfC11AVz2Acp2Zu493ekXxxiNdBMOyEwki0TwmcLiFEbIJafXaNMqCWYKC5jBrDFUuBUaBvRj5sWqgZVIlZWR-kXgGheF8I4LdFRR-Lg1BP7AU-kAz+iJESI8+sc+8ftgpNBhWiQjOPodv-IOhhwTII-sq6B1UeULwItItEclaHPq7DflnnfogDCE9JUn6PKi0KOPGrYJvtCEsApmcoDqAoAcAeqFaLaPaI6M6G6IvkpOOG4M+OoPkmsGTvsCLMcHTC1BcK-gEMmKILwG6vAMkEhLftkgpOyI2gBvCFyEiCiPyLTA0AcA4NoLVmLG1gNOqAlsIParwZ0kttFIcPYqYEKm4OHrUJ4NFPhs0HNoGORAfnuDBLxHBHZJaKoZ2CYHkKOHTJph9uRHoTYI4PVLoe3hyMUJmqdEuBYTxDZPxAhJZBqHYaSvIM9IlC4c+G4fyJ9hGhLEiEYP3sKOYdxNZHxPBPZMdpEfJJCmXgQgSI4DoEUIkX6MkYUmkQBMZJkVZBlKEfZI5K5O5BAAUU-APtCBUMtkFBsF0N+GoKoEiLTPHmcvTlmrKOlFYZlNlJAJ0cyM+O1GcHFIUEYOKvyDkCoGoLsVyGcEUBsNMkNCNBqPDIjNnoChXMiPkMZGKBCoPpsOIURGLKpEsNoMYHTGULUszKzOcddD5FcV7LksZIBE2nTF1MgQgAcNCOyG4FGoiv2JCKAuztrKcVAHrAbL3DAJfIsYgP2D+uUM-JGgYDLDpM0CCiiFRJoORFGu4KAsfBAmfCipaLiZAXwW2pSaUYxBUPCWiOsE9CyKREHqUGKLoAyeAqfFAOfKyUPJ4t4rfNPHiQ+DcU2pIjyebopq4HRJ8e-B-gYB4BKdiZAhfHKXAggkgsqR9E9DGBThpgmHoRLHkBQpIu8TCJ3P-skkwsgCwlaZoMRLUfhm4JpGIuUKoKHo7mUK-l4D8cog0ukoqVwTjNnphhIsDOkebiGVYn6MpMFJIk0MULurGfUj6R4uaS0laf6IiKxKvp0BiAcEMt0qMm2k8uoPTP-vsoclmMqQHAFM-I4GFCIn2I3B4PLBuh8WcArKrsqS0HkKCtGh3tHFClYh9HkOIoYOoKUG-H2M7gIBAO5MqeoDkE+IYI9PWRHOul0MmqRNyDIpoAHM7o5gJlBlOsqaHFqjmZcsiF4NbogEUMZOLiTgMocJsLuW5qenuS+Z6sqR8SKh3E0AYaLrLLyE9KSbkHLLGMxI+XRhdtwIeQSFvlRJIvYhyBsB2l4OOOYlua-kpP4e1hyuDt1t2eyZ0hRuLhKA4PULVoppIp0PkAinLG-KYEmAzqlgxczkxbasdv1lljlnljBdKtGVRHGvmXoeItFO3CyubooPIdmkzmrq7kdmlhqKdudgxnKDBVhkoAipSp4C0LQQgEoOtiTP9G4byJRqJTxi7pJbxtDrDlAGbPXojuZZZRIt4N+f+EYBsXckZMmkUlcvIISP-l5erilqiZztzgNnJRZSxULNyE4AttWdIiROyBTO0AFC5Z4G5R6Z5fpd5ZDnmlruib6blfeMKMKm3HVMZKYCujFV2v2iYA4IlSJVMaDuJQZd1gsa1fJBKOGYUAWc0H2DkBTCUM4DRQiG4G4IUInmACnkjFNcmVAQpK6dCFRMKJpH6CmtCmLiyh9K6QDJIs7s5OaFAHNFmHrG8AjmAFae0LcYUIUGKG4N4FUN9pUE4JcAOV4HoE0DXmdvXgjKnh0dNU-MsdCC0ErsHpcGiIHOQdTkZKuv2EBqNZxIEdBMfqfiqD2WGcBG-J4JpC1L+foeRKoKpAcIRO9KTNgUASAT9WmaOAcF4AiO0O-i+BGuHEtb-mrAEEAA */
- model.createMachine(
- {
- predictableActionArguments: true,
- preserveActionOrder: true,
- tsTypes: {} as import('./request.typegen').Typegen0,
- schema: {
- context: model.initialContext,
- events: {} as EventFrom,
- services: {} as {
- verifyVp: {
- data: VC;
- };
- },
- },
- invoke: {
- src: 'monitorConnection',
- },
- id: 'request',
- initial: 'inactive',
- on: {
- SCREEN_BLUR: {
- target: '.inactive',
- },
-
- SCREEN_FOCUS: [
- {
- target: '.checkingNetwork',
- cond: 'isModeOnline',
- },
- '.checkingBluetoothService',
- ],
-
- SWITCH_PROTOCOL: [
- {
- target: '.checkingNetwork',
- actions: 'switchProtocol',
- cond: 'isModeOnline',
- description: `Check internet connection for online protocol`,
- },
- {
- target: '.checkingBluetoothService',
- actions: 'switchProtocol',
- },
- ],
- },
- states: {
- inactive: {
- entry: 'removeLoggers',
- },
-
- checkingBluetoothService: {
- initial: 'checking',
-
- states: {
- checking: {
- invoke: {
- src: 'checkBluetoothService',
- },
- on: {
- BLUETOOTH_ENABLED: {
- target: 'enabled',
- },
- BLUETOOTH_DISABLED: {
- target: 'requesting',
- },
- },
- },
-
- requesting: {
- invoke: {
- src: 'requestBluetooth',
- },
- on: {
- BLUETOOTH_ENABLED: {
- target: 'enabled',
- },
- BLUETOOTH_DISABLED: {
- target: '#request.bluetoothDenied',
- },
- },
- },
-
- enabled: {
- always: {
- target: '#request.clearingConnection',
- },
- },
- },
-
- on: {
- APP_ACTIVE: 'checkingNetwork',
- },
- },
-
- bluetoothDenied: {
- on: {
- GOTO_SETTINGS: {
- actions: 'openSettings',
- },
- },
- },
-
- clearingConnection: {
- entry: 'disconnect',
- after: {
- CLEAR_DELAY: {
- target: '#request.waitingForConnection',
- actions: [],
- internal: false,
- },
- },
- },
-
- waitingForConnection: {
- entry: [
- 'removeLoggers',
- 'registerLoggers',
- 'generateConnectionParams',
- ],
- invoke: {
- src: 'advertiseDevice',
- },
- on: {
- CONNECTED: {
- actions: ['setPairId'],
- target: 'preparingToExchangeInfo',
- },
- DISCONNECT: {
- target: 'disconnected',
- },
- },
- },
-
- preparingToExchangeInfo: {
- entry: 'requestReceiverInfo',
- on: {
- RECEIVE_DEVICE_INFO: {
- target: 'exchangingDeviceInfo',
- actions: 'setReceiverInfo',
- },
- },
- },
-
- exchangingDeviceInfo: {
- invoke: {
- src: 'exchangeDeviceInfo',
- },
- initial: 'inProgress',
- states: {
- inProgress: {
- after: {
- CONNECTION_TIMEOUT: {
- target: '#request.exchangingDeviceInfo.timeout',
- actions: [],
- internal: false,
- },
- },
- },
- timeout: {
- on: {
- CANCEL: {
- target: '#request.cancelling',
- },
- },
- },
- },
- on: {
- EXCHANGE_DONE: {
- target: 'waitingForVc',
- actions: 'setSenderInfo',
- },
- },
- },
-
- waitingForVc: {
- invoke: {
- src: 'receiveVc',
- },
- initial: 'inProgress',
- states: {
- inProgress: {
- after: {
- SHARING_TIMEOUT: {
- target: '#request.waitingForVc.timeout',
- actions: [],
- internal: false,
- },
- },
- },
- timeout: {
- on: {
- CANCEL: {
- target: '#request.cancelling',
- },
- },
- },
- },
- on: {
- DISCONNECT: {
- target: 'disconnected',
- },
- VC_RECEIVED: {
- target: 'reviewing',
- actions: 'setIncomingVc',
- },
- },
- },
-
- cancelling: {
- invoke: {
- src: 'sendDisconnect',
- },
- after: {
- CANCEL_TIMEOUT: {
- target: '#request.checkingBluetoothService',
- actions: ['disconnect'],
- internal: false,
- },
- },
- },
-
- reviewing: {
- exit: 'disconnect',
- initial: 'idle',
- states: {
- idle: {},
- verifyingIdentity: {
- exit: 'clearShouldVerifyPresence',
- on: {
- FACE_VALID: {
- target: 'accepting',
- actions: 'setReceiveLogTypeVerified',
- },
- FACE_INVALID: {
- target: 'invalidIdentity',
- actions: 'setReceiveLogTypeUnverified',
- },
- CANCEL: {
- target: 'idle',
- },
- },
- },
- invalidIdentity: {
- on: {
- DISMISS: {
- target: 'accepting',
- },
- RETRY_VERIFICATION: {
- target: 'verifyingIdentity',
- },
- },
- },
- verifyingVp: {
- invoke: {
- src: 'verifyVp',
- onDone: [
- {
- target: 'accepting',
- },
- ],
- onError: [
- {
- target: 'idle',
- actions: log('Failed to verify Verifiable Presentation'),
- },
- ],
- },
- },
- accepting: {
- initial: 'requestingReceivedVcs',
- states: {
- requestingReceivedVcs: {
- entry: 'requestReceivedVcs',
- on: {
- VC_RESPONSE: [
- {
- target: 'requestingExistingVc',
- cond: 'hasExistingVc',
- },
- {
- target: 'prependingReceivedVc',
- },
- ],
- },
- },
- requestingExistingVc: {
- entry: 'requestExistingVc',
- on: {
- STORE_RESPONSE: {
- target: 'mergingIncomingVc',
- },
- },
- },
- mergingIncomingVc: {
- entry: 'mergeIncomingVc',
- on: {
- STORE_RESPONSE: {
- target: '#request.reviewing.accepted',
- },
- },
- },
- prependingReceivedVc: {
- entry: 'prependReceivedVc',
- on: {
- STORE_RESPONSE: {
- target: 'storingVc',
- },
- },
- },
- storingVc: {
- entry: 'storeVc',
- on: {
- STORE_RESPONSE: {
- target: '#request.reviewing.accepted',
- },
- },
- },
- },
- },
- accepted: {
- entry: ['updateReceivedVcs', 'logReceived'],
- invoke: {
- src: 'sendVcResponse',
- data: {
- status: 'ACCEPTED',
- },
- },
- on: {
- DISMISS: {
- target: 'navigatingToHome',
- },
- },
- },
- rejected: {
- entry: ['setReceiveLogTypeDiscarded', 'logReceived'],
- invoke: {
- src: 'sendVcResponse',
- data: {
- status: 'REJECTED',
- },
- },
- on: {
- DISMISS: {
- target: '#request.waitingForConnection',
- },
- },
- },
- navigatingToHome: {},
- },
- on: {
- ACCEPT: {
- target: '.accepting',
- actions: 'setReceiveLogTypeRegular',
- },
- ACCEPT_AND_VERIFY: {
- target: '.verifyingIdentity',
- },
- REJECT: {
- target: '.rejected',
- },
- CANCEL: {
- target: '.rejected',
- },
- },
- },
-
- disconnected: {
- entry: 'disconnect',
- on: {
- DISMISS: {
- target: 'waitingForConnection',
- },
- },
- },
-
- checkingNetwork: {
- invoke: {
- src: 'checkNetwork',
- },
-
- on: {
- ONLINE: 'checkingBluetoothService',
- OFFLINE: 'offline',
- },
- },
-
- offline: {
- on: {
- ONLINE: 'checkingBluetoothService',
- APP_ACTIVE: 'checkingNetwork',
- },
- },
- },
- },
- {
- actions: {
- setPairId: assign({
- pairId: (_context, event) => event.pairId,
- }),
-
- openSettings: () => {
- Platform.OS === 'android'
- ? BluetoothStateManager.openSettings().catch()
- : Linking.openURL('App-Prefs:Bluetooth');
- },
-
- switchProtocol: assign({
- sharingProtocol: (_context, event) =>
- event.value ? 'ONLINE' : 'OFFLINE',
- }),
-
- requestReceivedVcs: send(VcEvents.GET_RECEIVED_VCS(), {
- to: (context) => context.serviceRefs.vc,
- }),
-
- requestReceiverInfo: sendParent('REQUEST_DEVICE_INFO'),
-
- setReceiverInfo: model.assign({
- receiverInfo: (_context, event) => event.info,
- }),
-
- disconnect: (context) => {
- try {
- if (context.sharingProtocol === 'OFFLINE') {
- IdpassSmartshare.destroyConnection();
- } else {
- GoogleNearbyMessages.disconnect();
- }
- } catch (e) {
- // pass
- }
- },
-
- generateConnectionParams: assign({
- connectionParams: (context) => {
- if (context.sharingProtocol === 'OFFLINE') {
- return IdpassSmartshare.getConnectionParameters();
- } else {
- const cid = uuid.v4();
- return JSON.stringify({
- pk: '',
- cid,
- });
- }
- },
- }),
-
- setSenderInfo: model.assign({
- senderInfo: (_context, event) => event.senderInfo,
- }),
-
- setIncomingVc: assign({
- incomingVc: (_context, event) => {
- const vp = event.vc.verifiablePresentation;
- return vp != null
- ? {
- ...event.vc,
- verifiableCredential: vp.verifiableCredential[0],
- }
- : event.vc;
- },
- }),
-
- registerLoggers: assign({
- loggers: () => {
- if (__DEV__) {
- return [
- IdpassSmartshare.handleNearbyEvents((event) => {
- console.log(
- getDeviceNameSync(),
- '',
- JSON.stringify(event).slice(0, 100)
- );
- }),
- IdpassSmartshare.handleLogEvents((event) => {
- console.log(
- getDeviceNameSync(),
- '',
- JSON.stringify(event).slice(0, 100)
- );
- }),
- ];
- } else {
- return [];
- }
- },
- }),
-
- removeLoggers: assign({
- loggers: ({ loggers }) => {
- loggers?.forEach((logger) => logger.remove());
- return null;
- },
- }),
-
- prependReceivedVc: send(
- (context) =>
- StoreEvents.PREPEND(
- RECEIVED_VCS_STORE_KEY,
- VC_ITEM_STORE_KEY(context.incomingVc)
- ),
- { to: (context) => context.serviceRefs.store }
- ),
-
- requestExistingVc: send(
- (context) => StoreEvents.GET(VC_ITEM_STORE_KEY(context.incomingVc)),
- { to: (context) => context.serviceRefs.store }
- ),
-
- mergeIncomingVc: send(
- (context, event) => {
- const existing = event.response as VC;
- const updated: VC = {
- ...existing,
- reason: existing.reason.concat(context.incomingVc.reason),
- };
- return StoreEvents.SET(VC_ITEM_STORE_KEY(updated), updated);
- },
- { to: (context) => context.serviceRefs.store }
- ),
-
- storeVc: send(
- (context) =>
- StoreEvents.SET(
- VC_ITEM_STORE_KEY(context.incomingVc),
- context.incomingVc
- ),
- { to: (context) => context.serviceRefs.store }
- ),
-
- setReceiveLogTypeRegular: model.assign({
- receiveLogType: 'VC_RECEIVED',
- }),
-
- setReceiveLogTypeVerified: model.assign({
- receiveLogType: 'VC_RECEIVED_WITH_PRESENCE_VERIFIED',
- }),
-
- setReceiveLogTypeUnverified: model.assign({
- receiveLogType: 'VC_RECEIVED_BUT_PRESENCE_VERIFICATION_FAILED',
- }),
-
- setReceiveLogTypeDiscarded: model.assign({
- receiveLogType: 'VC_RECEIVED_NOT_SAVED',
- }),
-
- logReceived: send(
- (context) =>
- ActivityLogEvents.LOG_ACTIVITY({
- _vcKey: VC_ITEM_STORE_KEY(context.incomingVc),
- type: context.receiveLogType,
- timestamp: Date.now(),
- deviceName:
- context.senderInfo.name || context.senderInfo.deviceName,
- vcLabel: context.incomingVc.tag || context.incomingVc.id,
- }),
- { to: (context) => context.serviceRefs.activityLog }
- ),
-
- updateReceivedVcs: send(
- (context) => {
- return VcEvents.VC_RECEIVED(VC_ITEM_STORE_KEY(context.incomingVc));
- },
- { to: (context) => context.serviceRefs.vc }
- ),
-
- clearShouldVerifyPresence: assign({
- incomingVc: (context) => ({
- ...context.incomingVc,
- shouldVerifyPresence: false,
- }),
- }),
- },
-
- services: {
- sendDisconnect: (context) => () => {
- if (context.sharingProtocol === 'ONLINE') {
- onlineSend(
- {
- type: 'disconnect',
- data: 'rejected',
- },
- context.pairId
- );
- }
- },
-
- checkBluetoothService: () => (callback) => {
- const subscription = BluetoothStateManager.onStateChange((state) => {
- if (state === 'PoweredOn') {
- callback(model.events.BLUETOOTH_ENABLED());
- } else {
- callback(model.events.BLUETOOTH_DISABLED());
- }
- }, true);
- return () => subscription.remove();
- },
-
- checkNetwork: () => async (callback) => {
- const state = await NetInfo.fetch();
- callback({
- type: state.isInternetReachable ? 'ONLINE' : 'OFFLINE',
- });
- },
-
- requestBluetooth: () => (callback) => {
- BluetoothStateManager.requestToEnable()
- .then(() => callback(model.events.BLUETOOTH_ENABLED()))
- .catch(() => callback(model.events.BLUETOOTH_DISABLED()));
- },
-
- advertiseDevice: (context) => (callback) => {
- if (context.sharingProtocol === 'OFFLINE') {
- GoogleNearbyMessages.disconnect();
- IdpassSmartshare.createConnection('advertiser', () => {
- callback({ type: 'CONNECTED', pairId: '' });
- });
- } else {
- (async function () {
- GoogleNearbyMessages.addOnErrorListener((kind, message) =>
- console.log('\n\n[request] GNM_ERROR\n\n', kind, message)
- );
-
- try {
- IdpassSmartshare.destroyConnection();
- } catch (e) {
- /*pass*/
- }
- await GoogleNearbyMessages.connect(
- Platform.select({
- ios: {
- apiKey: GNM_API_KEY,
- },
- default: {},
- })
- );
- console.log('[request] GNM connected!');
-
- const generatedParams = JSON.parse(
- context.connectionParams
- ) as ConnectionParams;
-
- await onlineSubscribe(
- 'pairing',
- async (scannedQrParams) => {
- try {
- if (scannedQrParams.cid === generatedParams.cid) {
- const event: PairingResponseEvent = {
- type: 'pairing:response',
- data: scannedQrParams.cid,
- };
- await onlineSend(event, scannedQrParams.cid);
- callback({
- type: 'CONNECTED',
- pairId: scannedQrParams.cid,
- });
- }
- } catch (e) {
- console.error('Could not parse message.', e);
- }
- },
- null,
- { pairId: generatedParams.cid }
- );
- })();
- }
- },
-
- monitorConnection: (context) => (callback) => {
- if (context.sharingProtocol === 'OFFLINE') {
- const subscription = IdpassSmartshare.handleNearbyEvents(
- (event) => {
- if (event.type === 'onDisconnected') {
- callback({ type: 'DISCONNECT' });
- }
- }
- );
-
- return () => subscription.remove();
- }
- },
-
- exchangeDeviceInfo: (context) => (callback) => {
- const event: ExchangeReceiverInfoEvent = {
- type: 'exchange-receiver-info',
- data: context.receiverInfo,
- };
-
- if (context.sharingProtocol === 'OFFLINE') {
- const subscription = offlineSubscribe(
- 'exchange-sender-info',
- (senderInfo) => {
- offlineSend(event, () => {
- callback({ type: 'EXCHANGE_DONE', senderInfo });
- });
- }
- );
-
- return () => subscription.remove();
- } else {
- onlineSubscribe(
- 'exchange-sender-info',
- async (senderInfo) => {
- await GoogleNearbyMessages.unpublish();
- await onlineSend(event, context.pairId);
- callback({ type: 'EXCHANGE_DONE', senderInfo });
- },
- null,
- { pairId: context.pairId }
- );
- }
- },
-
- receiveVc: (context) => (callback) => {
- if (context.sharingProtocol === 'OFFLINE') {
- const subscription = offlineSubscribe('send-vc', ({ vc }) => {
- callback({ type: 'VC_RECEIVED', vc });
- });
-
- return () => subscription.remove();
- } else {
- let rawData = '';
- onlineSubscribe(
- 'send-vc',
- async ({ isChunked, vc, vcChunk }) => {
- await GoogleNearbyMessages.unpublish();
- const VcReceivedEvent: SendVcResponseEvent = {
- type: 'send-vc:response',
- data: 'RECEIVED',
- };
- if (isChunked) {
- rawData += vcChunk.rawData;
- if (vcChunk.chunk === vcChunk.total - 1) {
- const vc = JSON.parse(rawData) as VC;
- GoogleNearbyMessages.unsubscribe();
- await onlineSend(VcReceivedEvent, context.pairId);
- callback({ type: 'VC_RECEIVED', vc });
- } else {
- await onlineSend(
- {
- type: 'send-vc:response',
- data: vcChunk.chunk,
- },
- context.pairId
- );
- }
- } else {
- await onlineSend(VcReceivedEvent, context.pairId);
- callback({ type: 'VC_RECEIVED', vc });
- }
- },
- () => callback({ type: 'DISCONNECT' }),
- { keepAlive: true, pairId: context.pairId }
- );
- }
- },
-
- sendVcResponse: (context, _event, meta) => async () => {
- const event: SendVcResponseEvent = {
- type: 'send-vc:response',
- data: meta.data.status,
- };
-
- if (context.sharingProtocol === 'OFFLINE') {
- offlineSend(event, () => {
- // pass
- });
- } else {
- await GoogleNearbyMessages.unpublish();
- await onlineSend(event, context.pairId);
- }
- },
-
- verifyVp: (context) => async () => {
- const vp = context.incomingVc.verifiablePresentation;
-
- // TODO
- // const challenge = ?
- // await verifyPresentation(vp, challenge);
-
- const vc: VC = {
- ...context.incomingVc,
- verifiablePresentation: null,
- verifiableCredential: vp.verifiableCredential[0],
- };
-
- return Promise.resolve(vc);
- },
- },
-
- guards: {
- hasExistingVc: (context, event) => {
- const receivedVcs = event.response as string[];
- const vcKey = VC_ITEM_STORE_KEY(context.incomingVc);
- return receivedVcs.includes(vcKey);
- },
-
- isModeOnline: (context, event) =>
- event.type === 'SCREEN_FOCUS'
- ? context.sharingProtocol === 'ONLINE'
- : event.value,
- },
-
- delays: {
- CLEAR_DELAY: 250,
- CANCEL_TIMEOUT: 5000,
- CONNECTION_TIMEOUT: (context) => {
- return (context.sharingProtocol === 'ONLINE' ? 15 : 5) * 1000;
- },
- SHARING_TIMEOUT: (context) => {
- return (context.sharingProtocol === 'ONLINE' ? 45 : 15) * 1000;
- },
- },
- }
- );
-
-export function createRequestMachine(serviceRefs: AppServices) {
- return requestMachine.withContext({
- ...requestMachine.context,
- serviceRefs,
- });
-}
-
-type State = StateFrom;
-
-export function selectSenderInfo(state: State) {
- return state.context.senderInfo;
-}
-
-export function selectConnectionParams(state: State) {
- return state.context.connectionParams;
-}
-
-export function selectIncomingVc(state: State) {
- return state.context.incomingVc;
-}
-
-export function selectSharingProtocol(state: State) {
- return state.context.sharingProtocol;
-}
-
-export function selectIsIncomingVp(state: State) {
- return state.context.incomingVc?.verifiablePresentation != null;
-}
-
-export function selectIsCancelling(state: State) {
- return state.matches('cancelling');
-}
-
-export function selectIsReviewing(state: State) {
- return state.matches('reviewing');
-}
-
-export function selectIsAccepted(state: State) {
- return state.matches('reviewing.accepted');
-}
-
-export function selectIsRejected(state: State) {
- return state.matches('reviewing.rejected');
-}
-
-export function selectIsVerifyingIdentity(state: State) {
- return state.matches('reviewing.verifyingIdentity');
-}
-
-export function selectIsVerifyingVp(state: State) {
- return state.matches('reviewing.verifyingVp');
-}
-
-export function selectIsInvalidIdentity(state: State) {
- return state.matches('reviewing.invalidIdentity');
-}
-
-export function selectIsDisconnected(state: State) {
- return state.matches('disconnected');
-}
-
-export function selectIsWaitingForConnection(state: State) {
- return state.matches('waitingForConnection');
-}
-
-export function selectIsBluetoothDenied(state: State) {
- return state.matches('bluetoothDenied');
-}
-
-export function selectIsCheckingBluetoothService(state: State) {
- return state.matches('checkingBluetoothService');
-}
-
-export function selectIsExchangingDeviceInfo(state: State) {
- return state.matches('exchangingDeviceInfo.inProgress');
-}
-
-export function selectIsExchangingDeviceInfoTimeout(state: State) {
- return state.matches('exchangingDeviceInfo.timeout');
-}
-
-export function selectIsWaitingForVc(state: State) {
- return state.matches('waitingForVc.inProgress');
-}
-
-export function selectIsWaitingForVcTimeout(state: State) {
- return state.matches('waitingForVc.timeout');
-}
-
-export function selectIsDone(state: State) {
- return state.matches('reviewing.navigatingToHome');
-}
-
-export function selectIsOffline(state: State) {
- return state.matches('offline');
-}
diff --git a/machines/scan.ts b/machines/scan.ts
deleted file mode 100644
index c074bcff..00000000
--- a/machines/scan.ts
+++ /dev/null
@@ -1,1181 +0,0 @@
-/* eslint-disable sonarjs/no-duplicate-string */
-import SmartshareReactNative from '@idpass/smartshare-react-native';
-import { ConnectionParams } from '@idpass/smartshare-react-native/lib/typescript/IdpassSmartshare';
-const { IdpassSmartshare, GoogleNearbyMessages } = SmartshareReactNative;
-
-import {
- ActorRefFrom,
- assign,
- DoneInvokeEvent,
- EventFrom,
- send,
- sendParent,
- spawn,
- StateFrom,
-} from 'xstate';
-import { createModel } from 'xstate/lib/model';
-import { EmitterSubscription, Linking, Platform } from 'react-native';
-import { DeviceInfo } from '../components/DeviceInfoList';
-import { getDeviceNameSync } from 'react-native-device-info';
-import { VC, VerifiablePresentation } from '../types/vc';
-import { AppServices } from '../shared/GlobalContext';
-import { ActivityLogEvents, ActivityLogType } from './activityLog';
-import {
- GNM_API_KEY,
- GNM_MESSAGE_LIMIT,
- MY_LOGIN_STORE_KEY,
- VC_ITEM_STORE_KEY,
-} from '../shared/constants';
-import {
- onlineSubscribe,
- offlineSubscribe,
- offlineSend,
- onlineSend,
- ExchangeSenderInfoEvent,
- PairingEvent,
- SendVcEvent,
- SendVcStatus,
-} from '../shared/smartshare';
-import { check, PERMISSIONS, PermissionStatus } from 'react-native-permissions';
-import { checkLocation, requestLocation } from '../shared/location';
-import { CameraCapturedPicture } from 'expo-camera';
-import { log } from 'xstate/lib/actions';
-import NetInfo from '@react-native-community/netinfo';
-import { createQrLoginMachine, qrLoginMachine } from './QrLoginMachine';
-import { StoreEvents } from './store';
-
-type SharingProtocol = 'OFFLINE' | 'ONLINE';
-
-const SendVcResponseType = 'send-vc:response';
-
-const model = createModel(
- {
- serviceRefs: {} as AppServices,
- senderInfo: {} as DeviceInfo,
- receiverInfo: {} as DeviceInfo,
- selectedVc: {} as VC,
- createdVp: null as VC,
- reason: '',
- loggers: [] as EmitterSubscription[],
- vcName: '',
- verificationImage: {} as CameraCapturedPicture,
- sharingProtocol: 'OFFLINE' as SharingProtocol,
- scannedQrParams: {} as ConnectionParams,
- shareLogType: '' as ActivityLogType,
- QrLoginRef: {} as ActorRefFrom,
- linkCode: '',
- },
- {
- events: {
- EXCHANGE_DONE: (receiverInfo: DeviceInfo) => ({ receiverInfo }),
- RECEIVE_DEVICE_INFO: (info: DeviceInfo) => ({ info }),
- SELECT_VC: (vc: VC) => ({ vc }),
- SCAN: (params: string) => ({ params }),
- ACCEPT_REQUEST: () => ({}),
- VERIFY_AND_ACCEPT_REQUEST: () => ({}),
- VC_ACCEPTED: () => ({}),
- VC_REJECTED: () => ({}),
- VC_SENT: () => ({}),
- CANCEL: () => ({}),
- DISMISS: () => ({}),
- CONNECTED: () => ({}),
- DISCONNECT: () => ({}),
- SCREEN_BLUR: () => ({}),
- SCREEN_FOCUS: () => ({}),
- UPDATE_REASON: (reason: string) => ({ reason }),
- LOCATION_ENABLED: () => ({}),
- LOCATION_DISABLED: () => ({}),
- LOCATION_REQUEST: () => ({}),
- UPDATE_VC_NAME: (vcName: string) => ({ vcName }),
- STORE_RESPONSE: (response: unknown) => ({ response }),
- APP_ACTIVE: () => ({}),
- FACE_VALID: () => ({}),
- FACE_INVALID: () => ({}),
- RETRY_VERIFICATION: () => ({}),
- VP_CREATED: (vp: VerifiablePresentation) => ({ vp }),
- TOGGLE_USER_CONSENT: () => ({}),
- ONLINE: () => ({}),
- OFFLINE: () => ({}),
- },
- }
-);
-const QR_LOGIN_REF_ID = 'QrLogin';
-
-export const ScanEvents = model.events;
-
-export const scanMachine =
- /** @xstate-layout N4IgpgJg5mDOIC5SwMYEMB2BiAygYQCUBRIgOQH0AhAGQFUCBtABgF1FQAHAe1gEsAXXlwzsQAD0QBmSQDoAjAqYA2AJwAmABxMVAFgDsAViY6ANCACeUgwfkrrWg2oN79SyQF93Z1JlyESFABiAPJ4tDjMbEgg3HyCwqISCAC0TmoyKipKOmp6GvlacnZmlgiS1rb2TI7Orh5eID4YMigANmBoAE68GFB4whhgKPHYYrD8aPxgMmgAZlOdABR41EQAggTkACJE1GsAmgCUWE0t7V09fQNDI5GisQJCItFJcgZyGUpyGkpfakr-NIlRBvFRMDKZXJyST6Jj-eredDNWY9CCXfoYQbDJ5+NakO7RB4jRKIZLldKSNRyKEaMEqPR6NSmCwg2k2AwaIxMbk1JQGJSeRGYGQojBo3oYrEjXH4uRRTg8R4JF6k9QyWrvPSSAGGPTfYEIb52dWc7k8px8gUNU6i8VXTE3HH4PEMNTymKK4kqw1aDI6TkGSS0+lBg1Fb7qr61f3QnIqQWNJEyDidMAcC69AAqXElNywxDwRAAkgA1IjbIglouF8hF0ghAkKuJPEkIXKyZSGJnUpQaf3M0pqId6GQaINFLnkrIJ04oa7Y3pYPDBUikIh4TNELaNj3N5WgV56JQyJhdvtfHKMzQG-4GHTyKk6NxvLQIxPCucOhdQGQ9AAKnRcFAqawLAWBjBMUwzPMYBLMuq7rpmRYruQSEALJEMEtCZscs7zoIvS-hgAFASBsA7kSLbetSHxGPkkjGHIR5vO8N7vOCMLSL22hjuoM5Jp+UqXDIggALZgFwACu-BLnihbUBRnpUQeiDOOkGh6r2ALZNYrEsm27y0SoMI6GCchMEUxj8cKYBiCgAAWmBQJcWxgAAbrwKBgEWGCzFwWBbEW+ArmuG6KXuzwqQg1iyHo9KmT8cIMsYN6ZPeT5qMY1R2Gy1nNLZDlOS57med5vn+UQAAaeAABJ4gA4uWWwrkQ4VKpF4gghUDK6Go5T5MZcgAgaDG6DIDEaeoOj6DGeUyAVjm9MVHleT5fngeMkzTHMCzLCFiHIRQ6GYdhuFJgtRW9K5K1lX5bVelFFRfBoTj6N8vbqD8qVPjI-rZFS6gAq9c0XUtV0lat5Uibw4lSTJeBybs93KZ1CA6NyMiGOZegWVkfKZCNCgjkw5RBkwGn-Co0JzamHlgAA7sJsBgO034ligWC0H+WxrJu5DEGsOArsj+6o8kNHjSotJauoDJONqI18ho6oGFLTG-JyJk0yVDNMyzjq9OzAVBfBoWZiLHVJMk03pMY-zTW8ALqHIhNMSepP8nyzgMQY2t04zhHM6zBFQEbOC7Ih5AlngFutuLp4yJaeRKOTR5xUxI3WB8JNaurqiglaQrNLTvC64H+tsxzZYEEWgT7OQeJbA3eCFn+mb80QACKtBEDg5usPcSmi1bbiY3FaX+keVOciNfbgs4WhaDkfZS37pcBz+QcG6HHNrC3RBtx33e9-37qUcPiD6Cov3Tfy5l2-6Bo6Ex4LGU4gbaNykh6GvZebxXIcjYI1IPJWO1ExyJyHP9FOWQ5A6H5IrDQHw8hjiUHqVWSC1C-w3jILelcsCZmCPVeqqxyDhCIJseC4dSCn0HhFOObxwT0WkPoQwd44F6BGjob+ic0HGSPAxAGvtrRJhLn-FomAvKtFaJcDakFtowTgojagqEiwYSwjhE4oidY4KRFImRvQwFRXMk4dUZpVbmUkJ9DQXCijqm4Zlb+mQU46GwXrMUlwjaBWCghMKA9CRD0tiCDKKs4r-CSgyGET8owyFyGaJ8Kc3BuPLh4w2Vc8DN1bpubc-imztVbGoMa01TLQiyFYlwkholUjMa4Z2qhqjJP-qkneWBo4dwAFKIS3EY1GtIPhuDNN2Kx0IlBP1MiOfk-VtRFEyI03BYBmnsyIiRYCcAwIQS2tBXaOA6o11IPVVR6jTpaOFGInBzNFkoGWYBVZoEelJEBJjZ+fYiZxUDF9fSt9lYuOUFSXGug5kXLtEssSElpKyRAUjXJu58neiprIKW2RnmaB5AYMZbxxp3lPNURkCg3ynDOcJNAKAvIcCmBAY2OA0JBQiNC8+QSygRl+dUSm+Qc5Px+B2aaxg3BalPD-ERpydHCVTAAKxuJASl1KcC0rPoE1s1IwS-WyHkKxzzTw2P0iZWQ7zKQF2MNIOZblYK8FmOYS4RYIALMEPwcwWBAh73LCWNY1Aiw5LlfQ70Pt5CUmfkDLIug0WfKKPeRwnJVCFNPPGQVxdhWEWNd0M1FqrUYBtXah1NY6zOtde6uhsLjFHnVGCKk0JHCBs4cGoaJ4uxggDJlLBMaZCEvjSapNvRLXWoEHa4BoC6Xyu9LkEckgFCcjgSTRw38g2lCDIyDIFlpqUicFTLUcyUCpkmJ4jgWAIDCGmD0NyXAADW0wCVxp-GujogCOAIH3VwdAtxWD3MQFeWJZlybsPfmoJ+cDr5BjsL8RxfJV3rqvVgWCgFOjJlaJMPynRRK4O0f7YSF6N2G2vbe+9TxIhPoQIyWQIyARPmfpoBks8q1aFyACb+TFAzCKLk2s9RE3JoBkRADtqau1SppTh1IbtoRFC0NirUfVZ5KtxlSL4YIiNzP3Sx3gbGU1pvzEQTMBB67V1rtWXmh0cO9hPJyF6Ybn6q0ME-aooahy6ABKOow+KkxolQPhSV3jpWyrzQ9VGfIRz+mLUybhL1jI3jQeCEmKrMgkyYnYOasnWNcZlTh5+19zHwMZEePklT9LfAZL9OeONTLf2HQK+jDkhiHsuNQO9G7hA4FgjdFo9lSuXBwJBSSYFqChG0yhMgawaDdL7Z6qKvGRzqGxaZSzVmK2lHMjkItkSNIhv0HZj8DWUBld6BVzD1XaulXq413ozXJitawO1hGSEULeJ66sXNASBti39H6bh99l1HgsgaKmtsmT-CnlJ1xjaSurfK5VkYNXOh1dTAAR0knAEO2YiAYDQAAI3aMdjrZ2KDdd69dvJHnXg-TQb2DKLzvjkze84eQTErG9lVjCL4c1-tragBtqrGAQdg7AJD6HlxYfw6R2AFHp3DrbCCpdvrHr82oxyLIF6-ntDjPfgORAPx0h6hJsZVWYI9RLeaPTwHm2Wfba8rtgHvQ-ywVErwUCOITudfR6QEXWOYU4+CcefH55NDP2J5qqb2opfDr7IYLQiTC7vm1ythnTPgcG+mDrk3ZuLd8GEPzm3QucD24S9SDIgY7BMj5PoRwYZMohc-qoFOX9fvFbD7r5nrOdsOcR+0Cl1u0dHx7n3BLpivi6lUHqOKeQDR5HBNw9hnsGRwIbRXvbjOgdPBr4blNpcKVrD-H+ZuSEywJfgZjO8uo7Bqz0lNjV8gjDmU1IxbUdPK-ren1t0HteFkL6T834gx82-9fF0kNLJ4SPZAp24QLmXqgbA0F+o0EkEdItcjcGdSAwB+B6YuBOhD0sBghAhAhXU1wcNClr5Ch8h8dUtrx9JMoU5fo4F3gkEpYacICY8oBoDYD4DECVw0DWo38ncUhTFwwtJNRpBh0XYCDQRE5EsNIepi05ouBZhZgDE+cXNuNmCUYkh+RwRDBi1F5wkFcfRst+xyZVAshlAmJPAGgMAuArV4Bogmh3NZDSRTIQscgkVHZCkqQbxMpE47A74sgyCAxot4dsRjUzCL40Zxpv5tJOxNByhfgxkbAGIGIewnwxxn46dzhugJR8IUZ6UFU7xfp-gNIJorExx8CpsUtYlHB0s+Q4QNI5pbR0QkjRYUjqI+M+xVYhx0YzQ9QwwcZjxchaRh1HB-h8c5oUw0wMwoBsxcxhgfCGVkh8hE4mInxSZnoYoHCfo8hPcSCqR+Q6ckjehRi44ORYlGRiNoQnA4RQwCDJ1RxuEYQ7B0Y+xKD1ifx-wbkyJNjvR44djuwqRKQjA+oXo2JzJTiuItByC+I-sbjoZYZpJHiop0YgDGRs8hppimRvimEzjuIATx8Q95o7JFpnJwYbo1ouBwTUYRxnpXo9QfhaRNBRkCCsYMgfhEs+poiGQQYMTLooBrpSpcTrlSI1l8TXhClxptBsgGJuEpY1cbwcCcsBSeohxtQNBGTCowYWSIZbouAQSwV+BuSpArFMYXpNBAxYxITvpjxEUcgihARgZG1m0oB1TWC+QfUBNuQcZhMMtp0hwbAhoB9XAU4JNAUAFPEUArSq1AQXASYnxuR-gRpkp9NlBR0eoIjV1JEWYDFLSbt39EBdARxWijxaQXFqRFZ+QnlGQNVyZPty80SLT5lLkrSARE4c4qNqhEonTL5fV5Asoh9il4FvTLkOTbljDsdzDDQfiU4Ai+o6zBywjvksoARzIZkSzT0kMUlgUrlQU4YrTaN1RtQo0BN-ceDSgvlqz0ZJz-kZzEN14iUSU0xyUrTgii0WEJp8hIsKSdycZr4FBCl4ENJHAaM5kxUJUIB-TCkdVh0cUhomQ7xEEFCANTRBNPS5l4cPIoBUNBiuAaouBxJLyIET9Txewp5ikp1L5YEMgyZTxFVAYjVW1zV21FMu1LzTJMYXFshMg1I4pVC1V+kOR3cXoKN2zzTGMUMr0rS9QkttRkoUsBlmKpZ0gjB9ADjuR5s6NSzGMYt5N2M00rTxZn5fogxVBCt34vgHypB6RjwGIBk3ljAGQis0SHNBIfzKz0ZiCmJSSrxoQvdEBB10yKcElMpvgjzhRFLfzkyWDl4NKkFtA7w9UrEwwylmza1DjpAwRg9ZxL8p89dZ8wBVLbwMhMo8t1BMD9ADQNZ3YhpyhrBLQAQL9J8I8Z8o9ICmsWsezHc+yhtMVlBuEep6L9R9I2E1zCrqQ-MQqyrjckrq8qqIcodxgucuA4d69Ur-K+zsgx5KQLJsZuEdJ+8KhdTnwGj0YAU-tEqKqb86sqDTc4N49kj+1jFyYcs35w1OVcYwxqgEUzRtChSZ1+rw9r99db858Lcpq-LezfCcZ0hdBEoXBPogxVCepeEPyrFPK9RXqq9I9Prph59IBKy8zqR3hhTXwrFcL+zMgCji1nA7xaRuE4begaC4CEDVK8hE5x5jSXT0ZSMCDQsMgSCZKBlZlG1RDxCehpq-qGVnB544ogwQiGKxwbxlBB8SDvgBMKC9D3AgA */
- model.createMachine(
- {
- predictableActionArguments: true,
- preserveActionOrder: true,
- tsTypes: {} as import('./scan.typegen').Typegen0,
- schema: {
- context: model.initialContext,
- events: {} as EventFrom,
- services: {} as {
- createVp: {
- data: VC;
- };
- },
- },
- invoke: {
- src: 'monitorConnection',
- },
- id: 'scan',
- initial: 'inactive',
- on: {
- SCREEN_BLUR: {
- target: '.inactive',
- },
- SCREEN_FOCUS: {
- target: '.checkingLocationService',
- },
- },
- states: {
- inactive: {
- entry: 'removeLoggers',
- },
-
- clearingConnection: {
- entry: 'disconnect',
- after: {
- CLEAR_DELAY: {
- target: '#scan.findingConnection',
- actions: [],
- internal: false,
- },
- },
- },
-
- findingConnection: {
- entry: [
- 'removeLoggers',
- 'registerLoggers',
- 'clearScannedQrParams',
- 'setChildRef',
- ],
- on: {
- SCAN: [
- {
- target: 'preparingToConnect',
- cond: 'isQrOffline',
- actions: 'setConnectionParams',
- },
- {
- target: 'checkingNetwork',
- cond: 'isQrOnline',
- actions: 'setScannedQrParams',
- },
- {
- target: 'showQrLogin',
- cond: 'isQrLogin',
- actions: 'setLinkCode',
- },
- {
- target: 'invalid',
- },
- ],
- },
- },
- showQrLogin: {
- invoke: {
- id: 'QrLogin',
- src: qrLoginMachine,
- onDone: '.storing',
- },
- on: {
- DISMISS: 'findingConnection',
- },
- initial: 'idle',
- states: {
- idle: {},
- storing: {
- entry: ['storeLoginItem'],
- on: {
- STORE_RESPONSE: {
- target: 'navigatingToHome',
- actions: ['storingActivityLog'],
- },
- },
- },
- navigatingToHome: {},
- },
- entry: 'sendScanData',
- },
- preparingToConnect: {
- entry: 'requestSenderInfo',
- on: {
- RECEIVE_DEVICE_INFO: {
- target: 'connecting',
- actions: 'setSenderInfo',
- },
- },
- },
-
- connecting: {
- invoke: {
- src: 'discoverDevice',
- },
- initial: 'inProgress',
- states: {
- inProgress: {
- after: {
- CONNECTION_TIMEOUT: {
- target: '#scan.connecting.timeout',
- actions: [],
- internal: false,
- },
- },
- },
- timeout: {
- on: {
- CANCEL: {
- target: '#scan.reviewing.cancelling',
- },
- },
- },
- },
- on: {
- CONNECTED: {
- target: 'exchangingDeviceInfo',
- },
- },
- },
-
- exchangingDeviceInfo: {
- invoke: {
- src: 'exchangeDeviceInfo',
- },
- initial: 'inProgress',
- after: {
- CONNECTION_TIMEOUT: {
- target: '#scan.exchangingDeviceInfo.timeout',
- actions: [],
- internal: false,
- },
- },
- states: {
- inProgress: {},
- timeout: {
- on: {
- CANCEL: {
- target: '#scan.reviewing.cancelling',
- },
- },
- },
- },
- on: {
- DISCONNECT: {
- target: 'disconnected',
- },
- EXCHANGE_DONE: {
- target: 'reviewing',
- actions: 'setReceiverInfo',
- },
- },
- },
-
- reviewing: {
- entry: ['resetShouldVerifyPresence'],
- exit: ['disconnect', 'clearReason', 'clearCreatedVp'],
- initial: 'selectingVc',
- states: {
- selectingVc: {
- invoke: {
- src: 'monitorCancellation',
- },
- on: {
- UPDATE_REASON: {
- actions: 'setReason',
- },
- DISCONNECT: {
- target: '#scan.disconnected',
- },
- SELECT_VC: {
- actions: 'setSelectedVc',
- },
- VERIFY_AND_ACCEPT_REQUEST: {
- target: 'verifyingIdentity',
- },
- ACCEPT_REQUEST: {
- target: 'sendingVc',
- actions: 'setShareLogTypeUnverified',
- },
- CANCEL: {
- target: 'cancelling',
- },
- TOGGLE_USER_CONSENT: {
- actions: 'toggleShouldVerifyPresence',
- },
- },
- exit: ['onlineUnsubscribe'],
- },
- cancelling: {
- invoke: {
- src: 'sendDisconnect',
- },
- after: {
- CANCEL_TIMEOUT: {
- target: '#scan.findingConnection',
- actions: ['disconnect'],
- internal: false,
- },
- },
- },
- sendingVc: {
- invoke: {
- src: 'sendVc',
- },
- initial: 'inProgress',
- states: {
- inProgress: {
- after: {
- SHARING_TIMEOUT: {
- target: '#scan.reviewing.sendingVc.timeout',
- actions: [],
- internal: false,
- },
- },
- },
- timeout: {
- on: {
- CANCEL: {
- target: '#scan.reviewing.cancelling',
- },
- },
- },
- sent: {
- description:
- 'VC data has been shared and the receiver should now be viewing it',
- },
- },
- on: {
- DISCONNECT: {
- target: '#scan.findingConnection',
- },
- VC_SENT: {
- target: '.sent',
- },
- VC_ACCEPTED: {
- target: '#scan.reviewing.accepted',
- },
- VC_REJECTED: {
- target: '#scan.reviewing.rejected',
- },
- },
- },
- accepted: {
- entry: 'logShared',
- on: {
- DISMISS: {
- target: 'navigatingToHome',
- },
- },
- },
- rejected: {
- on: {
- DISMISS: {
- target: '#scan.findingConnection',
- },
- },
- },
- navigatingToHome: {},
- verifyingIdentity: {
- on: {
- FACE_VALID: {
- target: 'sendingVc',
- actions: 'setShareLogTypeVerified',
- },
- FACE_INVALID: {
- target: 'invalidIdentity',
- actions: 'logFailedVerification',
- },
- CANCEL: {
- target: 'selectingVc',
- },
- },
- },
- creatingVp: {
- invoke: {
- src: 'createVp',
- onDone: [
- {
- target: 'sendingVc',
- actions: 'setCreatedVp',
- },
- ],
- onError: [
- {
- target: 'selectingVc',
- actions: log('Could not create Verifiable Presentation'),
- },
- ],
- },
- },
- invalidIdentity: {
- on: {
- DISMISS: {
- target: 'selectingVc',
- },
- RETRY_VERIFICATION: {
- target: 'verifyingIdentity',
- },
- },
- },
- },
- },
-
- disconnected: {
- on: {
- DISMISS: {
- target: 'findingConnection',
- },
- },
- },
-
- invalid: {
- on: {
- DISMISS: {
- target: 'findingConnection',
- },
- },
- },
-
- checkingLocationService: {
- initial: 'checkingStatus',
- states: {
- checkingStatus: {
- invoke: {
- src: 'checkLocationStatus',
- },
- on: {
- LOCATION_ENABLED: {
- target: 'checkingPermission',
- },
- LOCATION_DISABLED: {
- target: 'requestingToEnable',
- },
- },
- },
- requestingToEnable: {
- entry: 'requestToEnableLocation',
- on: {
- LOCATION_ENABLED: {
- target: 'checkingPermission',
- },
- LOCATION_DISABLED: {
- target: 'disabled',
- },
- },
- },
- checkingPermission: {
- invoke: {
- src: 'checkLocationPermission',
- },
- on: {
- LOCATION_ENABLED: {
- target: '#scan.clearingConnection',
- },
- LOCATION_DISABLED: {
- target: 'denied',
- },
- },
- },
- disabled: {
- on: {
- LOCATION_REQUEST: {
- target: 'requestingToEnable',
- },
- },
- },
- denied: {
- on: {
- APP_ACTIVE: {
- target: 'checkingPermission',
- },
- LOCATION_REQUEST: {
- actions: 'openSettings',
- },
- },
- },
- },
- },
-
- checkingNetwork: {
- invoke: {
- src: 'checkNetwork',
- },
-
- on: {
- OFFLINE: 'offline',
- ONLINE: 'preparingToConnect',
- },
- },
-
- offline: {
- on: {
- DISMISS: 'findingConnection',
- },
- },
- },
- },
- {
- actions: {
- setChildRef: assign({
- QrLoginRef: (context) =>
- spawn(createQrLoginMachine(context.serviceRefs), QR_LOGIN_REF_ID),
- }),
-
- sendScanData: (context) =>
- context.QrLoginRef.send({
- type: 'GET',
- value: context.linkCode,
- }),
-
- requestSenderInfo: sendParent('REQUEST_DEVICE_INFO'),
-
- setSenderInfo: model.assign({
- senderInfo: (_context, event) => event.info,
- }),
-
- requestToEnableLocation: () => requestLocation(),
-
- disconnect: (context) => {
- try {
- if (context.sharingProtocol === 'OFFLINE') {
- IdpassSmartshare.destroyConnection();
- } else {
- GoogleNearbyMessages.disconnect();
- }
- } catch (e) {
- //
- }
- },
-
- setConnectionParams: (_context, event) => {
- IdpassSmartshare.setConnectionParameters(event.params);
- },
-
- setScannedQrParams: model.assign({
- scannedQrParams: (_context, event) =>
- JSON.parse(event.params) as ConnectionParams,
- sharingProtocol: 'ONLINE',
- }),
-
- clearScannedQrParams: assign({
- scannedQrParams: {} as ConnectionParams,
- }),
-
- setReceiverInfo: model.assign({
- receiverInfo: (_context, event) => event.receiverInfo,
- }),
-
- setReason: model.assign({
- reason: (_context, event) => event.reason,
- }),
-
- clearReason: assign({ reason: '' }),
-
- setSelectedVc: assign({
- selectedVc: (context, event) => {
- const reason = [];
- if (context.reason.trim() !== '') {
- reason.push({ message: context.reason, timestamp: Date.now() });
- }
- return {
- ...event.vc,
- reason,
- shouldVerifyPresence: context.selectedVc.shouldVerifyPresence,
- };
- },
- }),
-
- setCreatedVp: assign({
- createdVp: (_context, event) => event.data,
- }),
-
- clearCreatedVp: assign({
- createdVp: () => null,
- }),
-
- registerLoggers: assign({
- loggers: (context) => {
- if (context.sharingProtocol === 'OFFLINE' && __DEV__) {
- return [
- IdpassSmartshare.handleNearbyEvents((event) => {
- console.log(
- getDeviceNameSync(),
- '',
- JSON.stringify(event).slice(0, 100)
- );
- }),
- IdpassSmartshare.handleLogEvents((event) => {
- console.log(
- getDeviceNameSync(),
- '',
- JSON.stringify(event).slice(0, 100)
- );
- }),
- ];
- } else {
- return [];
- }
- },
- }),
-
- removeLoggers: assign({
- loggers: ({ loggers }) => {
- loggers?.forEach((logger) => logger.remove());
- return [];
- },
- }),
-
- setShareLogTypeUnverified: model.assign({
- shareLogType: 'VC_SHARED',
- }),
-
- setShareLogTypeVerified: model.assign({
- shareLogType: 'PRESENCE_VERIFIED_AND_VC_SHARED',
- }),
-
- logShared: send(
- (context) =>
- ActivityLogEvents.LOG_ACTIVITY({
- _vcKey: VC_ITEM_STORE_KEY(context.selectedVc),
- type: context.selectedVc.shouldVerifyPresence
- ? 'VC_SHARED_WITH_VERIFICATION_CONSENT'
- : context.shareLogType,
- timestamp: Date.now(),
- deviceName:
- context.receiverInfo.name || context.receiverInfo.deviceName,
- vcLabel: context.selectedVc.tag || context.selectedVc.id,
- }),
- { to: (context) => context.serviceRefs.activityLog }
- ),
-
- logFailedVerification: send(
- (context) =>
- ActivityLogEvents.LOG_ACTIVITY({
- _vcKey: VC_ITEM_STORE_KEY(context.selectedVc),
- type: 'PRESENCE_VERIFICATION_FAILED',
- timestamp: Date.now(),
- deviceName:
- context.receiverInfo.name || context.receiverInfo.deviceName,
- vcLabel: context.selectedVc.tag || context.selectedVc.id,
- }),
- { to: (context) => context.serviceRefs.activityLog }
- ),
-
- openSettings: () => Linking.openSettings(),
-
- toggleShouldVerifyPresence: assign({
- selectedVc: (context) => ({
- ...context.selectedVc,
- shouldVerifyPresence: !context.selectedVc.shouldVerifyPresence,
- }),
- }),
-
- setLinkCode: assign({
- linkCode: (_context, event) =>
- event.params.substring(
- event.params.indexOf('linkCode=') + 9,
- event.params.indexOf('&')
- ),
- }),
-
- resetShouldVerifyPresence: assign({
- selectedVc: (context) => ({
- ...context.selectedVc,
- shouldVerifyPresence: false,
- }),
- }),
-
- onlineUnsubscribe: () => {
- GoogleNearbyMessages.unsubscribe();
- },
-
- storeLoginItem: send(
- (_context, event) => {
- return StoreEvents.PREPEND(
- MY_LOGIN_STORE_KEY,
- (event as DoneInvokeEvent).data
- );
- },
- { to: (context) => context.serviceRefs.store }
- ),
-
- storingActivityLog: send(
- (_, event) =>
- ActivityLogEvents.LOG_ACTIVITY({
- _vcKey: '',
- type: 'QRLOGIN_SUCCESFULL',
- timestamp: Date.now(),
- deviceName: '',
- vcLabel: String(event.response.selectedVc.id),
- }),
- {
- to: (context) => context.serviceRefs.activityLog,
- }
- ),
- },
-
- services: {
- checkLocationPermission: () => async (callback) => {
- try {
- // wait a bit for animation to finish when app becomes active
- await new Promise((resolve) => setTimeout(resolve, 250));
-
- let response: PermissionStatus;
- if (Platform.OS === 'android') {
- response = await check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION);
- } else if (Platform.OS === 'ios') {
- return callback(model.events.LOCATION_ENABLED());
- }
-
- if (response === 'granted') {
- callback(model.events.LOCATION_ENABLED());
- } else {
- callback(model.events.LOCATION_DISABLED());
- }
- } catch (e) {
- console.error(e);
- }
- },
-
- monitorConnection: (context) => (callback) => {
- if (context.sharingProtocol === 'OFFLINE') {
- const subscription = IdpassSmartshare.handleNearbyEvents(
- (event) => {
- if (event.type === 'onDisconnected') {
- callback({ type: 'DISCONNECT' });
- }
- }
- );
-
- return () => subscription.remove();
- }
- },
-
- monitorCancellation: (context) => async (callback) => {
- if (context.sharingProtocol === 'ONLINE') {
- await onlineSubscribe(
- 'disconnect',
- null,
- () => callback({ type: 'DISCONNECT' }),
- { pairId: context.scannedQrParams.cid }
- );
- }
- },
-
- checkLocationStatus: () => (callback) => {
- checkLocation(
- () => callback(model.events.LOCATION_ENABLED()),
- () => callback(model.events.LOCATION_DISABLED())
- );
- },
-
- checkNetwork: () => async (callback) => {
- const state = await NetInfo.fetch();
- callback({ type: state.isInternetReachable ? 'ONLINE' : 'OFFLINE' });
- },
-
- discoverDevice: (context) => (callback) => {
- if (context.sharingProtocol === 'OFFLINE') {
- GoogleNearbyMessages.disconnect();
- IdpassSmartshare.createConnection('discoverer', () => {
- callback({ type: 'CONNECTED' });
- });
- } else {
- (async function () {
- GoogleNearbyMessages.addOnErrorListener((kind, message) =>
- console.log('\n\n[scan] GNM_ERROR\n\n', kind, message)
- );
-
- try {
- IdpassSmartshare.destroyConnection();
- } catch (e) {
- /*pass*/
- }
- await GoogleNearbyMessages.connect(
- Platform.select({
- ios: {
- apiKey: GNM_API_KEY,
- },
- default: {},
- })
- );
- console.log('[scan] GNM connected!');
-
- await onlineSubscribe(
- 'pairing:response',
- async (response) => {
- await GoogleNearbyMessages.unpublish();
- if (response === context.scannedQrParams.cid) {
- callback({ type: 'CONNECTED' });
- }
- },
- null,
- { pairId: context.scannedQrParams.cid }
- );
-
- const pairingEvent: PairingEvent = {
- type: 'pairing',
- data: context.scannedQrParams,
- };
-
- await onlineSend(pairingEvent, context.scannedQrParams.cid);
- })();
- }
- },
-
- exchangeDeviceInfo: (context) => (callback) => {
- const event: ExchangeSenderInfoEvent = {
- type: 'exchange-sender-info',
- data: context.senderInfo,
- };
-
- if (context.sharingProtocol === 'OFFLINE') {
- let subscription: EmitterSubscription;
- offlineSend(event, () => {
- subscription = offlineSubscribe(
- 'exchange-receiver-info',
- (receiverInfo) => {
- callback({ type: 'EXCHANGE_DONE', receiverInfo });
- }
- );
- });
- return () => subscription?.remove();
- } else {
- (async function () {
- await onlineSubscribe(
- 'exchange-receiver-info',
- async (receiverInfo) => {
- await GoogleNearbyMessages.unpublish();
- callback({ type: 'EXCHANGE_DONE', receiverInfo });
- },
- null,
- { pairId: context.scannedQrParams.cid }
- );
-
- await onlineSend(event, context.scannedQrParams.cid);
- })();
- }
- },
-
- sendVc: (context) => (callback) => {
- let subscription: EmitterSubscription;
- const vp = context.createdVp;
- const vc = {
- ...(vp != null ? vp : context.selectedVc),
- tag: '',
- };
-
- const statusCallback = (status: SendVcStatus) => {
- console.log('[scan] statusCallback', status);
- if (typeof status === 'number') return;
- if (status === 'RECEIVED') {
- callback({ type: 'VC_SENT' });
- } else {
- callback({
- type: status === 'ACCEPTED' ? 'VC_ACCEPTED' : 'VC_REJECTED',
- });
- }
- };
-
- if (context.sharingProtocol === 'OFFLINE') {
- const event: SendVcEvent = {
- type: 'send-vc',
- data: { isChunked: false, vc },
- };
- offlineSend(event, () => {
- subscription = offlineSubscribe(
- SendVcResponseType,
- statusCallback
- );
- });
- return () => subscription?.remove();
- } else {
- sendVc(
- vc,
- statusCallback,
- () => callback({ type: 'DISCONNECT' }),
- context.scannedQrParams.cid
- );
- }
- },
-
- sendDisconnect: (context) => () => {
- if (context.sharingProtocol === 'ONLINE') {
- onlineSend(
- {
- type: 'disconnect',
- data: 'rejected',
- },
- context.scannedQrParams.cid
- );
- }
- },
-
- createVp: (context) => async () => {
- // TODO
- // const verifiablePresentation = await createVerifiablePresentation(...);
-
- const verifiablePresentation: VerifiablePresentation = {
- '@context': [''],
- 'proof': null,
- 'type': 'VerifiablePresentation',
- 'verifiableCredential': [context.selectedVc.verifiableCredential],
- };
-
- const vc: VC = {
- ...context.selectedVc,
- verifiableCredential: null,
- verifiablePresentation,
- };
-
- return Promise.resolve(vc);
- },
- },
-
- guards: {
- isQrOffline: (_context, event) => {
- if (Platform.OS === 'ios') return false;
-
- const param: ConnectionParams = Object.create(null);
- try {
- Object.assign(param, JSON.parse(event.params));
- return 'cid' in param && 'pk' in param && param.pk !== '';
- } catch (e) {
- return false;
- }
- },
-
- isQrOnline: (_context, event) => {
- const param: ConnectionParams = Object.create(null);
- try {
- Object.assign(param, JSON.parse(event.params));
- return 'cid' in param && 'pk' in param && param.pk === '';
- } catch (e) {
- return false;
- }
- },
-
- isQrLogin: (_context, event) => {
- let linkCode = '';
- try {
- linkCode = event.params.substring(
- event.params.indexOf('linkCode=') + 9,
- event.params.indexOf('&')
- );
- return linkCode !== null;
- } catch (e) {
- return false;
- }
- },
- },
-
- delays: {
- CLEAR_DELAY: 250,
- CANCEL_TIMEOUT: 5000,
- CONNECTION_TIMEOUT: (context) => {
- return (context.sharingProtocol === 'ONLINE' ? 15 : 5) * 1000;
- },
- SHARING_TIMEOUT: (context) => {
- return (context.sharingProtocol === 'ONLINE' ? 45 : 15) * 1000;
- },
- },
- }
- );
-
-export function createScanMachine(serviceRefs: AppServices) {
- return scanMachine.withContext({
- ...scanMachine.context,
- serviceRefs,
- });
-}
-
-type State = StateFrom;
-
-export function selectReceiverInfo(state: State) {
- return state.context.receiverInfo;
-}
-
-export function selectReason(state: State) {
- return state.context.reason;
-}
-
-export function selectVcName(state: State) {
- return state.context.vcName;
-}
-
-export function selectSelectedVc(state: State) {
- return state.context.selectedVc;
-}
-export function selectQrLoginRef(state: State) {
- return state.context.QrLoginRef;
-}
-
-export function selectIsScanning(state: State) {
- return state.matches('findingConnection');
-}
-
-export function selectIsConnecting(state: State) {
- return state.matches('connecting.inProgress');
-}
-
-export function selectIsConnectingTimeout(state: State) {
- return state.matches('connecting.timeout');
-}
-
-export function selectIsExchangingDeviceInfo(state: State) {
- return state.matches('exchangingDeviceInfo.inProgress');
-}
-
-export function selectIsExchangingDeviceInfoTimeout(state: State) {
- return state.matches('exchangingDeviceInfo.timeout');
-}
-
-export function selectIsReviewing(state: State) {
- return state.matches('reviewing');
-}
-
-export function selectIsSelectingVc(state: State) {
- return state.matches('reviewing.selectingVc');
-}
-
-export function selectIsSendingVc(state: State) {
- return state.matches('reviewing.sendingVc.inProgress');
-}
-
-export function selectIsSendingVcTimeout(state: State) {
- return state.matches('reviewing.sendingVc.timeout');
-}
-
-export function selectIsAccepted(state: State) {
- return state.matches('reviewing.accepted');
-}
-
-export function selectIsRejected(state: State) {
- return state.matches('reviewing.rejected');
-}
-
-export function selectIsSent(state: State) {
- return state.matches('reviewing.sendingVc.sent');
-}
-
-export function selectIsInvalid(state: State) {
- return state.matches('invalid');
-}
-
-export function selectIsLocationDenied(state: State) {
- return state.matches('checkingLocationService.denied');
-}
-
-export function selectIsLocationDisabled(state: State) {
- return state.matches('checkingLocationService.disabled');
-}
-
-export function selectIsDone(state: State) {
- return state.matches('reviewing.navigatingToHome');
-}
-
-export function selectIsVerifyingIdentity(state: State) {
- return state.matches('reviewing.verifyingIdentity');
-}
-
-export function selectIsInvalidIdentity(state: State) {
- return state.matches('reviewing.invalidIdentity');
-}
-
-export function selectIsCancelling(state: State) {
- return state.matches('reviewing.cancelling');
-}
-
-export function selectIsShowQrLogin(state: State) {
- return state.matches('showQrLogin');
-}
-
-export function selectIsQrLoginDone(state: State) {
- return state.matches('showQrLogin.navigatingToHome');
-}
-
-export function selectIsQrLoginStoring(state: State) {
- return state.matches('showQrLogin.storing');
-}
-
-export function selectIsOffline(state: State) {
- return state.matches('offline');
-}
-
-export function selectIsDisconnected(state: State) {
- return state.matches('disconnected');
-}
-
-async function sendVc(
- vc: VC,
- callback: (status: SendVcStatus) => void,
- disconnectCallback: () => void,
- pairId: string
-) {
- const rawData = JSON.stringify(vc);
- const chunks = chunkString(rawData, GNM_MESSAGE_LIMIT);
- if (chunks.length > 1) {
- let chunk = 0;
- const vcChunk = {
- total: chunks.length,
- chunk,
- rawData: chunks[chunk],
- };
- const event: SendVcEvent = {
- type: 'send-vc',
- data: {
- isChunked: true,
- vcChunk,
- },
- };
-
- await onlineSubscribe(
- SendVcResponseType,
- async (status) => {
- if (typeof status === 'number' && chunk < event.data.vcChunk.total) {
- chunk += 1;
- await GoogleNearbyMessages.unpublish();
- await onlineSend(
- {
- type: 'send-vc',
- data: {
- isChunked: true,
- vcChunk: {
- total: chunks.length,
- chunk,
- rawData: chunks[chunk],
- },
- },
- },
- pairId
- );
- } else if (typeof status === 'string') {
- if (status === 'ACCEPTED' || status === 'REJECTED') {
- GoogleNearbyMessages.unsubscribe();
- }
- callback(status);
- }
- },
- disconnectCallback,
- { keepAlive: true, pairId }
- );
- await onlineSend(event, pairId);
- } else {
- const event: SendVcEvent = {
- type: 'send-vc',
- data: { isChunked: false, vc },
- };
- await onlineSubscribe(SendVcResponseType, callback, null, { pairId });
- await onlineSend(event, pairId);
- }
-}
-
-function chunkString(str: string, length: number) {
- return str.match(new RegExp('.{1,' + length + '}', 'g'));
-}
diff --git a/machines/scan.typegen.ts b/machines/scan.typegen.ts
deleted file mode 100644
index 395c23c2..00000000
--- a/machines/scan.typegen.ts
+++ /dev/null
@@ -1,230 +0,0 @@
-// This file was automatically generated. Edits will be overwritten
-
-export interface Typegen0 {
- '@@xstate/typegen': true;
- 'internalEvents': {
- 'done.invoke.QrLogin': {
- type: 'done.invoke.QrLogin';
- data: unknown;
- __tip: 'See the XState TS docs to learn how to strongly type this.';
- };
- 'done.invoke.scan.reviewing.creatingVp:invocation[0]': {
- type: 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
- data: unknown;
- __tip: 'See the XState TS docs to learn how to strongly type this.';
- };
- 'error.platform.scan.reviewing.creatingVp:invocation[0]': {
- type: 'error.platform.scan.reviewing.creatingVp:invocation[0]';
- data: unknown;
- };
- 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling': {
- type: 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling';
- };
- 'xstate.after(CLEAR_DELAY)#scan.clearingConnection': {
- type: 'xstate.after(CLEAR_DELAY)#scan.clearingConnection';
- };
- 'xstate.after(CONNECTION_TIMEOUT)#scan.connecting.inProgress': {
- type: 'xstate.after(CONNECTION_TIMEOUT)#scan.connecting.inProgress';
- };
- 'xstate.after(CONNECTION_TIMEOUT)#scan.exchangingDeviceInfo': {
- type: 'xstate.after(CONNECTION_TIMEOUT)#scan.exchangingDeviceInfo';
- };
- 'xstate.after(SHARING_TIMEOUT)#scan.reviewing.sendingVc.inProgress': {
- type: 'xstate.after(SHARING_TIMEOUT)#scan.reviewing.sendingVc.inProgress';
- };
- 'xstate.init': { type: 'xstate.init' };
- 'xstate.stop': { type: 'xstate.stop' };
- };
- 'invokeSrcNameMap': {
- checkLocationPermission: 'done.invoke.scan.checkingLocationService.checkingPermission:invocation[0]';
- checkLocationStatus: 'done.invoke.scan.checkingLocationService.checkingStatus:invocation[0]';
- checkNetwork: 'done.invoke.scan.checkingNetwork:invocation[0]';
- createVp: 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
- discoverDevice: 'done.invoke.scan.connecting:invocation[0]';
- exchangeDeviceInfo: 'done.invoke.scan.exchangingDeviceInfo:invocation[0]';
- monitorCancellation: 'done.invoke.scan.reviewing.selectingVc:invocation[0]';
- monitorConnection: 'done.invoke.scan:invocation[0]';
- sendDisconnect: 'done.invoke.scan.reviewing.cancelling:invocation[0]';
- sendVc: 'done.invoke.scan.reviewing.sendingVc:invocation[0]';
- };
- 'missingImplementations': {
- actions: never;
- delays: never;
- guards: never;
- services: 'QrLogin';
- };
- 'eventsCausingActions': {
- clearCreatedVp:
- | 'DISCONNECT'
- | 'DISMISS'
- | 'SCREEN_BLUR'
- | 'SCREEN_FOCUS'
- | 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling'
- | 'xstate.stop';
- clearReason:
- | 'DISCONNECT'
- | 'DISMISS'
- | 'SCREEN_BLUR'
- | 'SCREEN_FOCUS'
- | 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling'
- | 'xstate.stop';
- clearScannedQrParams:
- | 'DISCONNECT'
- | 'DISMISS'
- | 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling'
- | 'xstate.after(CLEAR_DELAY)#scan.clearingConnection';
- disconnect:
- | 'DISCONNECT'
- | 'DISMISS'
- | 'LOCATION_ENABLED'
- | 'SCREEN_BLUR'
- | 'SCREEN_FOCUS'
- | 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling'
- | 'xstate.stop';
- logFailedVerification: 'FACE_INVALID';
- logShared: 'VC_ACCEPTED';
- onlineUnsubscribe:
- | 'ACCEPT_REQUEST'
- | 'CANCEL'
- | 'DISCONNECT'
- | 'SCREEN_BLUR'
- | 'SCREEN_FOCUS'
- | 'VERIFY_AND_ACCEPT_REQUEST'
- | 'xstate.stop';
- openSettings: 'LOCATION_REQUEST';
- registerLoggers:
- | 'DISCONNECT'
- | 'DISMISS'
- | 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling'
- | 'xstate.after(CLEAR_DELAY)#scan.clearingConnection';
- removeLoggers:
- | 'DISCONNECT'
- | 'DISMISS'
- | 'SCREEN_BLUR'
- | 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling'
- | 'xstate.after(CLEAR_DELAY)#scan.clearingConnection'
- | 'xstate.init';
- requestSenderInfo: 'ONLINE' | 'SCAN';
- requestToEnableLocation: 'LOCATION_DISABLED' | 'LOCATION_REQUEST';
- resetShouldVerifyPresence: 'CANCEL' | 'EXCHANGE_DONE';
- sendScanData: 'SCAN';
- setChildRef:
- | 'DISCONNECT'
- | 'DISMISS'
- | 'xstate.after(CANCEL_TIMEOUT)#scan.reviewing.cancelling'
- | 'xstate.after(CLEAR_DELAY)#scan.clearingConnection';
- setConnectionParams: 'SCAN';
- setCreatedVp: 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
- setLinkCode: 'SCAN';
- setReason: 'UPDATE_REASON';
- setReceiverInfo: 'EXCHANGE_DONE';
- setScannedQrParams: 'SCAN';
- setSelectedVc: 'SELECT_VC';
- setSenderInfo: 'RECEIVE_DEVICE_INFO';
- setShareLogTypeUnverified: 'ACCEPT_REQUEST';
- setShareLogTypeVerified: 'FACE_VALID';
- storeLoginItem: 'done.invoke.QrLogin';
- storingActivityLog: 'STORE_RESPONSE';
- toggleShouldVerifyPresence: 'TOGGLE_USER_CONSENT';
- };
- 'eventsCausingDelays': {
- CANCEL_TIMEOUT: 'CANCEL';
- CLEAR_DELAY: 'LOCATION_ENABLED';
- CONNECTION_TIMEOUT:
- | 'CONNECTED'
- | 'RECEIVE_DEVICE_INFO'
- | 'xstate.after(CONNECTION_TIMEOUT)#scan.exchangingDeviceInfo';
- SHARING_TIMEOUT:
- | 'ACCEPT_REQUEST'
- | 'FACE_VALID'
- | 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
- };
- 'eventsCausingGuards': {
- isQrLogin: 'SCAN';
- isQrOffline: 'SCAN';
- isQrOnline: 'SCAN';
- };
- 'eventsCausingServices': {
- QrLogin: 'SCAN';
- checkLocationPermission: 'APP_ACTIVE' | 'LOCATION_ENABLED';
- checkLocationStatus: 'SCREEN_FOCUS';
- checkNetwork: 'SCAN';
- createVp: never;
- discoverDevice: 'RECEIVE_DEVICE_INFO';
- exchangeDeviceInfo:
- | 'CONNECTED'
- | 'xstate.after(CONNECTION_TIMEOUT)#scan.exchangingDeviceInfo';
- monitorCancellation:
- | 'CANCEL'
- | 'DISMISS'
- | 'EXCHANGE_DONE'
- | 'error.platform.scan.reviewing.creatingVp:invocation[0]';
- monitorConnection: 'xstate.init';
- sendDisconnect: 'CANCEL';
- sendVc:
- | 'ACCEPT_REQUEST'
- | 'FACE_VALID'
- | 'done.invoke.scan.reviewing.creatingVp:invocation[0]';
- };
- 'matchesStates':
- | 'checkingLocationService'
- | 'checkingLocationService.checkingPermission'
- | 'checkingLocationService.checkingStatus'
- | 'checkingLocationService.denied'
- | 'checkingLocationService.disabled'
- | 'checkingLocationService.requestingToEnable'
- | 'checkingNetwork'
- | 'clearingConnection'
- | 'connecting'
- | 'connecting.inProgress'
- | 'connecting.timeout'
- | 'disconnected'
- | 'exchangingDeviceInfo'
- | 'exchangingDeviceInfo.inProgress'
- | 'exchangingDeviceInfo.timeout'
- | 'findingConnection'
- | 'inactive'
- | 'invalid'
- | 'offline'
- | 'preparingToConnect'
- | 'reviewing'
- | 'reviewing.accepted'
- | 'reviewing.cancelling'
- | 'reviewing.creatingVp'
- | 'reviewing.invalidIdentity'
- | 'reviewing.navigatingToHome'
- | 'reviewing.rejected'
- | 'reviewing.selectingVc'
- | 'reviewing.sendingVc'
- | 'reviewing.sendingVc.inProgress'
- | 'reviewing.sendingVc.sent'
- | 'reviewing.sendingVc.timeout'
- | 'reviewing.verifyingIdentity'
- | 'showQrLogin'
- | 'showQrLogin.idle'
- | 'showQrLogin.navigatingToHome'
- | 'showQrLogin.storing'
- | {
- checkingLocationService?:
- | 'checkingPermission'
- | 'checkingStatus'
- | 'denied'
- | 'disabled'
- | 'requestingToEnable';
- connecting?: 'inProgress' | 'timeout';
- exchangingDeviceInfo?: 'inProgress' | 'timeout';
- reviewing?:
- | 'accepted'
- | 'cancelling'
- | 'creatingVp'
- | 'invalidIdentity'
- | 'navigatingToHome'
- | 'rejected'
- | 'selectingVc'
- | 'sendingVc'
- | 'verifyingIdentity'
- | { sendingVc?: 'inProgress' | 'sent' | 'timeout' };
- showQrLogin?: 'idle' | 'navigatingToHome' | 'storing';
- };
- 'tags': never;
-}
diff --git a/machines/settings.ts b/machines/settings.ts
index 84a21bcb..8aec51ec 100644
--- a/machines/settings.ts
+++ b/machines/settings.ts
@@ -1,19 +1,36 @@
-import { ContextFrom, EventFrom, send, StateFrom } from 'xstate';
+import { assign, ContextFrom, EventFrom, send, StateFrom } from 'xstate';
import { createModel } from 'xstate/lib/model';
import { AppServices } from '../shared/GlobalContext';
-import { SETTINGS_STORE_KEY } from '../shared/constants';
+import {
+ APP_ID_DICTIONARY,
+ APP_ID_LENGTH,
+ HOST,
+ isIOS,
+ SETTINGS_STORE_KEY,
+} from '../shared/constants';
import { VCLabel } from '../types/vc';
import { StoreEvents } from './store';
+import getAllConfigurations, {
+ COMMON_PROPS_KEY,
+} from '../shared/commonprops/commonProps';
+import Storage from '../shared/storage';
+import ShortUniqueId from 'short-unique-id';
+import { AppId } from '../shared/request';
+import { isCustomSecureKeystore } from '../shared/cryptoutil/cryptoUtil';
const model = createModel(
{
serviceRefs: {} as AppServices,
name: '',
vcLabel: {
- singular: 'ID',
- plural: 'IDs',
+ singular: 'Card',
+ plural: 'Cards',
} as VCLabel,
isBiometricUnlockEnabled: false,
+ credentialRegistry: HOST,
+ appId: null,
+ hasUserShownWithHardwareKeystoreNotExists: false,
+ credentialRegistryResponse: '' as string,
},
{
events: {
@@ -22,6 +39,18 @@ const model = createModel(
TOGGLE_BIOMETRIC_UNLOCK: (enable: boolean) => ({ enable }),
STORE_RESPONSE: (response: unknown) => ({ response }),
CHANGE_LANGUAGE: (language: string) => ({ language }),
+ UPDATE_CREDENTIAL_REGISTRY: (credentialRegistry: string) => ({
+ credentialRegistry,
+ }),
+ UPDATE_CREDENTIAL_REGISTRY_RESPONSE: (
+ credentialRegistryResponse: string
+ ) => ({
+ credentialRegistryResponse: credentialRegistryResponse,
+ }),
+ INJI_TOUR_GUIDE: () => ({}),
+ BACK: () => ({}),
+ CANCEL: () => ({}),
+ ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS: () => ({}),
},
}
);
@@ -44,18 +73,24 @@ export const settingsMachine = model.createMachine(
entry: ['requestStoredContext'],
on: {
STORE_RESPONSE: [
+ {
+ cond: 'hasPartialData',
+ target: 'idle',
+ actions: ['setContext', 'updatePartialDefaults', 'storeContext'],
+ },
{ cond: 'hasData', target: 'idle', actions: ['setContext'] },
{ target: 'storingDefaults' },
],
},
},
storingDefaults: {
- entry: ['storeContext'],
+ entry: ['updateDefaults', 'storeContext'],
on: {
STORE_RESPONSE: 'idle',
},
},
idle: {
+ entry: ['injiTourGuide'],
on: {
TOGGLE_BIOMETRIC_UNLOCK: {
actions: ['toggleBiometricUnlock', 'storeContext'],
@@ -66,6 +101,57 @@ export const settingsMachine = model.createMachine(
UPDATE_VC_LABEL: {
actions: ['updateVcLabel', 'storeContext'],
},
+ UPDATE_CREDENTIAL_REGISTRY: {
+ actions: ['resetCredentialRegistry'],
+ target: 'resetInjiProps',
+ },
+ CANCEL: {
+ actions: ['resetCredentialRegistry'],
+ },
+ ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS: {
+ actions: [
+ 'updateUserShownWithHardwareKeystoreNotExists',
+ 'storeContext',
+ ],
+ target: 'idle',
+ },
+ },
+ },
+ resetInjiProps: {
+ invoke: {
+ src: 'resetInjiProps',
+ onDone: {
+ actions: [
+ 'updateCredentialRegistrySuccess',
+ 'updateCredentialRegistry',
+ 'storeContext',
+ ],
+ target: 'idle',
+ },
+ onError: {
+ actions: ['updateCredentialRegistryResponse'],
+ target: 'idle',
+ },
+ },
+ on: {
+ CANCEL: {
+ actions: ['resetCredentialRegistry'],
+ target: 'idle',
+ },
+ },
+ },
+ injiTourGuide: {
+ on: {
+ INJI_TOUR_GUIDE: {
+ target: 'showInjiTourGuide',
+ },
+ },
+ },
+ showInjiTourGuide: {
+ on: {
+ BACK: {
+ target: 'idle',
+ },
},
},
},
@@ -76,6 +162,20 @@ export const settingsMachine = model.createMachine(
to: (context) => context.serviceRefs.store,
}),
+ updateDefaults: model.assign({
+ appId: () => {
+ const appId = generateAppId();
+ AppId.setValue(appId);
+ return appId;
+ },
+
+ hasUserShownWithHardwareKeystoreNotExists: () => false,
+ }),
+
+ updatePartialDefaults: model.assign({
+ appId: (context) => context.appId || generateAppId(),
+ }),
+
storeContext: send(
(context) => {
const { serviceRefs, ...data } = context;
@@ -86,6 +186,7 @@ export const settingsMachine = model.createMachine(
setContext: model.assign((context, event) => {
const newContext = event.response as ContextFrom;
+ AppId.setValue(newContext.appId);
return {
...context,
...newContext,
@@ -102,16 +203,47 @@ export const settingsMachine = model.createMachine(
plural: event.label + 's',
}),
}),
+ updateCredentialRegistry: assign({
+ credentialRegistry: (_context, event) => event.data.warningDomainName,
+ }),
+
+ updateCredentialRegistryResponse: assign({
+ credentialRegistryResponse: () => 'error',
+ }),
+
+ updateCredentialRegistrySuccess: assign({
+ credentialRegistryResponse: () => 'success',
+ }),
+
+ resetCredentialRegistry: model.assign({
+ credentialRegistryResponse: () => '',
+ }),
+
+ updateUserShownWithHardwareKeystoreNotExists: model.assign({
+ hasUserShownWithHardwareKeystoreNotExists: () => true,
+ }),
toggleBiometricUnlock: model.assign({
isBiometricUnlockEnabled: (_, event) => event.enable,
}),
},
- services: {},
+ services: {
+ resetInjiProps: async (context, event) => {
+ try {
+ await Storage.removeItem(COMMON_PROPS_KEY);
+ return await getAllConfigurations(event.credentialRegistry);
+ } catch (error) {
+ console.log('Error from resetInjiProps ', error);
+ throw error;
+ }
+ },
+ },
guards: {
hasData: (_, event) => event.response != null,
+ hasPartialData: (_, event) =>
+ event.response != null && event.response.appId == null,
},
}
);
@@ -123,16 +255,53 @@ export function createSettingsMachine(serviceRefs: AppServices) {
});
}
+function generateAppId() {
+ const shortUUID = new ShortUniqueId({
+ length: APP_ID_LENGTH,
+ dictionary: APP_ID_DICTIONARY,
+ });
+ return shortUUID.randomUUID();
+}
+
+function deviceSupportsHardwareKeystore() {
+ return isIOS() ? true : isCustomSecureKeystore();
+}
+
type State = StateFrom;
export function selectName(state: State) {
return state.context.name;
}
+export function selectAppId(state: State) {
+ return state.context.appId;
+}
+
+/** Alerting the user when the hardware keystore not supported by device and
+ * not shown to user atlease once */
+
+export function selectShowHardwareKeystoreNotExistsAlert(state: State) {
+ const hasShown = state.context.hasUserShownWithHardwareKeystoreNotExists;
+ const deviceSupports = deviceSupportsHardwareKeystore();
+ return !hasShown && !deviceSupports;
+}
+
export function selectVcLabel(state: State) {
return state.context.vcLabel;
}
+export function selectCredentialRegistry(state: State) {
+ return state.context.credentialRegistry;
+}
+
+export function selectCredentialRegistryResponse(state: State) {
+ return state.context.credentialRegistryResponse;
+}
+
export function selectBiometricUnlockEnabled(state: State) {
return state.context.isBiometricUnlockEnabled;
}
+
+export function selectIsResetInjiProps(state: State) {
+ return state.matches('resetInjiProps');
+}
diff --git a/machines/settings.typegen.ts b/machines/settings.typegen.ts
index d5acbb16..376702a4 100644
--- a/machines/settings.typegen.ts
+++ b/machines/settings.typegen.ts
@@ -3,32 +3,67 @@
export interface Typegen0 {
'@@xstate/typegen': true;
'internalEvents': {
+ 'done.invoke.settings.resetInjiProps:invocation[0]': {
+ type: 'done.invoke.settings.resetInjiProps:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
+ 'error.platform.settings.resetInjiProps:invocation[0]': {
+ type: 'error.platform.settings.resetInjiProps:invocation[0]';
+ data: unknown;
+ };
'xstate.init': { type: 'xstate.init' };
};
- 'invokeSrcNameMap': {};
+ 'invokeSrcNameMap': {
+ resetInjiProps: 'done.invoke.settings.resetInjiProps:invocation[0]';
+ };
'missingImplementations': {
- actions: never;
+ actions: 'injiTourGuide';
delays: never;
guards: never;
services: never;
};
'eventsCausingActions': {
+ injiTourGuide:
+ | 'BACK'
+ | 'CANCEL'
+ | 'STORE_RESPONSE'
+ | 'done.invoke.settings.resetInjiProps:invocation[0]'
+ | 'error.platform.settings.resetInjiProps:invocation[0]';
requestStoredContext: 'xstate.init';
+ resetCredentialRegistry: 'CANCEL' | 'UPDATE_CREDENTIAL_REGISTRY';
setContext: 'STORE_RESPONSE';
storeContext:
+ | 'ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS'
| 'STORE_RESPONSE'
| 'TOGGLE_BIOMETRIC_UNLOCK'
| 'UPDATE_NAME'
- | 'UPDATE_VC_LABEL';
+ | 'UPDATE_VC_LABEL'
+ | 'done.invoke.settings.resetInjiProps:invocation[0]';
toggleBiometricUnlock: 'TOGGLE_BIOMETRIC_UNLOCK';
+ updateCredentialRegistry: 'done.invoke.settings.resetInjiProps:invocation[0]';
+ updateCredentialRegistryResponse: 'error.platform.settings.resetInjiProps:invocation[0]';
+ updateCredentialRegistrySuccess: 'done.invoke.settings.resetInjiProps:invocation[0]';
+ updateDefaults: 'STORE_RESPONSE';
updateName: 'UPDATE_NAME';
+ updatePartialDefaults: 'STORE_RESPONSE';
+ updateUserShownWithHardwareKeystoreNotExists: 'ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS';
updateVcLabel: 'UPDATE_VC_LABEL';
};
'eventsCausingDelays': {};
'eventsCausingGuards': {
hasData: 'STORE_RESPONSE';
+ hasPartialData: 'STORE_RESPONSE';
};
- 'eventsCausingServices': {};
- 'matchesStates': 'idle' | 'init' | 'storingDefaults';
+ 'eventsCausingServices': {
+ resetInjiProps: 'UPDATE_CREDENTIAL_REGISTRY';
+ };
+ 'matchesStates':
+ | 'idle'
+ | 'init'
+ | 'injiTourGuide'
+ | 'resetInjiProps'
+ | 'showInjiTourGuide'
+ | 'storingDefaults';
'tags': never;
}
diff --git a/machines/store.ts b/machines/store.ts
index 0e9611e4..aa8e133e 100644
--- a/machines/store.ts
+++ b/machines/store.ts
@@ -1,27 +1,55 @@
import * as Keychain from 'react-native-keychain';
-import CryptoJS from 'crypto-js';
-import AsyncStorage from '@react-native-async-storage/async-storage';
+import Storage from '../shared/storage';
import binaryToBase64 from 'react-native/Libraries/Utilities/binaryToBase64';
-import { EventFrom, Receiver, sendParent, send, sendUpdate } from 'xstate';
+import {
+ EventFrom,
+ Receiver,
+ send,
+ sendParent,
+ sendUpdate,
+ StateFrom,
+} from 'xstate';
import { createModel } from 'xstate/lib/model';
import { generateSecureRandom } from 'react-native-securerandom';
import { log } from 'xstate/lib/actions';
+import { MY_VCS_STORE_KEY, VC_ITEM_STORE_KEY_REGEX } from '../shared/constants';
+import SecureKeystore from 'react-native-secure-keystore';
+import {
+ AUTH_TIMEOUT,
+ clear,
+ decryptJson,
+ DUMMY_KEY_FOR_BIOMETRIC_ALIAS,
+ ENCRYPTION_ID,
+ encryptJson,
+ HMAC_ALIAS,
+ isCustomSecureKeystore,
+} from '../shared/cryptoutil/cryptoUtil';
-const ENCRYPTION_ID = 'c7c22a6c-9759-4605-ac88-46f4041d863d';
+const vcKeyRegExp = new RegExp(VC_ITEM_STORE_KEY_REGEX);
+export const keyinvalidatedString =
+ 'Key Invalidated due to biometric enrollment';
+export const tamperedErrorMessageString = 'Data is tampered';
const model = createModel(
{
encryptionKey: '',
+ isTampered: false as boolean,
},
{
events: {
KEY_RECEIVED: (key: string) => ({ key }),
READY: () => ({}),
+ TRY_AGAIN: () => ({}),
+ IGNORE: () => ({}),
GET: (key: string) => ({ key }),
+ DECRYPT_ERROR: () => ({}),
+ KEY_INVALIDATE_ERROR: () => ({}),
SET: (key: string, value: unknown) => ({ key, value }),
APPEND: (key: string, value: unknown) => ({ key, value }),
PREPEND: (key: string, value: unknown) => ({ key, value }),
+ UPDATE: (key: string, value: string) => ({ key, value }),
REMOVE: (key: string, value: string) => ({ key, value }),
+ REMOVE_VC_METADATA: (key: string, value: string) => ({ key, value }),
REMOVE_ITEMS: (key: string, values: string[]) => ({ key, values }),
CLEAR: () => ({}),
ERROR: (error: Error) => ({ error }),
@@ -30,6 +58,8 @@ const model = createModel(
requester,
}),
STORE_ERROR: (error: Error, requester?: string) => ({ error, requester }),
+ TAMPERED_VC: () => ({}),
+ RESET_IS_TAMPERED: () => ({}),
},
}
);
@@ -41,7 +71,7 @@ export type StoreResponseEvent = EventFrom;
type ForwardedEvent = EventFrom & { requester: string };
export const storeMachine =
- /** @xstate-layout N4IgpgJg5mDOIC5SwC4HsBOYB0MUoEsA7KAUSIGMMBPAB0LSIGkxqBiJ0gTQH0AlUgGFSASQBqpACKJQtNLAIMiMkAA9EAFgCsADmxatARgBsAJgDMJ04YDspjcYA0Iaoh1bj2DYdM3DJgAZvLRtjAF8w51RMHDxCEnIqOiUWdlI+PgB5PhU5BSUVdQRjHQDsAPNTYzMdO2MNHR1nVwRDSuwTDwCATi1K7WMA0wio9CxcMCIwDABDeLJKGnoCRlSObn4hUQlpJBA8xRXlPaL3G2xjO26dbVMtIMtmxErPc3MbD0aqm26KrRGQNFxjAprN5oklilWGx0lkcnsDgUToh-AE9H5rqUtBpzNdqk9Wj5sKEDDpuuYQu5DN4AUCcFhYGB8MQoABlMYzGBsCCMHDEABuaAA1jg6dgGUz5uzMJywAgBWgKHMjgBtAIAXVy8kOjEKblCHW6tkMHg+3RsjxciBsDi89wCQ3JmJstLG9LgkpZ0tmXOmGEw2FoABs5gAzTAAW2wYolzJI3tl8qIgqVSjVmoR2qRoCKhh65n05h0gx0FIpBhsBL6pnKNncNxsARNoXCkUBbvFYBmEHYAHFSAAVLX5I561p3AvGPHdBxtDTdAl2c5BbrXXzGLSmHT2V0xTvd9iswfDnXHHMoicXaez8zzgn1Mr2Vdkm64m3mXfjLAHtgAQQACv+pAAHK7LIWajsi459FexYzsYc4LlaCAGAWGjzquU6mFU1TDG2MZdj2bD-gIQGgSe2ZqBeMFTnBN53shDieBuDpBA6bS6IYn7uj+AgALKZBIFGQee0GTteCG3khLTvN02DuOxealAE-z4R235EYIAAypC-vC4EjrqUE+DREmIQSpjkuU9qGDoJq1BoeGjHuGmHgO2SkJsrL-pkwFHsJRmiSZcnobUDpkm+vgErY5zaA6OKNI29TaNx+5Eay7kCDwsLZAFZ5UeOFrYEWCFrnmAR+E0yG-Bc9r3N0G4fMYFIRG2RBoBAcAqGKcQshCyRHKkeVjt4BYGFYKm2ah5jRQ6HQblo3SWc1tSmqlILTMqCSLANqysMNUE-AWVRBD82J+NWs1lJ0i3LUWTUumpLkenGbIcjAB2iTchheO4DR5pu1gOFWhghXWZgfOhDg3KlrmfQVPjvB05hmLi3glCjTjIduWjyT49SlgYm6Ldx8NFEWcnjWYk3uH0M3IbYtUOr4oToc1jY6K1YRAA */
+ /** @xstate-layout N4IgpgJg5mDOIC5SwC4HsBOYB0MUoEsA7KAUSIGMMBPAB0LSIGkxqBiJ0gTQH0AlUgGFSASQBqpACIBtAAwBdRKFppYBBkSUgAHogBMADj3YArAYDMAdnMBOQ5csA2AIzOTAGhDVErt9kcmzrKGznqyBgYm5gC+0Z6omDh4hCTkVHQaLOykfHwA8nxyikggKmoaWroIhsZmVrb2Tq4eXog2AaY2ACyWdjbBhgbOsfHoWLhgRGAYAIYpZJQ09ASMWRzc-EKiEjIKWmXqK5olVdYG2G4OoeYmlgb9ep7eCDYmjtgWJnp6zjaWvo49CMQAlxjAprN5mklplWGwcvlCnsSgcKidECYuu8vs4uuYAtZHBYDE9EJETKY3OZZLcTJi9OYgXEQWMcFhYGB8MQoABlMYzGBsCCMHDEABuaAA1jhQWy4Jz5nzMAKwAhxWgKHMjkUivtVIdGJUfLI-thZFjMRYrJaSa0Xu1sHo6V0TQFHHiTMDZdh2QruUrZoLphhMNhaAAbOYAM0wAFtsN7fVySAGVWqiBLNRodcjlPq0aAqt1jOFgrJbI47JYfqSEAZrJ0uq9ukMotYvayfWAZhB2ABxUgAFV1KPzRyNCFCJlk-kcljxLibekcjlrQVkM-M+IXRK6PxXHcSXZ77B5Q5HefK4-Rk6dM5X8-xuLsK9r-S6F2sNKaBmCRkP4xYCebAAIIAApgaQAByuzFJeBrHIWPh3rOj6Li+q52r+5wbu0PzmJEhjlgBcrAWBAiQTBF6lGOho3lO95zguz7Lphzz-M4HxYs4kRuE6jJdCRx69mwAgALJ5BI1GoteSG3tOqHMUur52i4FJEno873L8dw9EJQEieJkmkDwYiCDwYlDiBkggYOIHSbRiE6Mh5icdWPzOI4shOG2taBDYlI2PiNiRDc7SesyibdoZpASRIPAiIOsU8g5V50XJDGKU+ylsYge7mNgNwmDY-R3PO4ROvp0XsIIAAypAgUicE0WlTlVJlD5KRhtaMpYFx2E2ZxDBulhVcBPKDgUJkCDyYF5FBZ6pQhE5TsY87LgyFjdO0tZhB+5hdDxJrlnoeGyI4Y0iRNU08AiBRLQWzm3nO-jFS4tgVs4BG1kM2BNq4YRzncDJNrEzJEGgEBwFosp6q1E4ALS5QgSNCck3LQhkRxZHDy03nua7ro6056IdVineWo2RZ24LTFqqSLFjqysLjj1VFixj1hEXldG8XnBG+bz+GVh0hUM-xMqMR5Joq-IwKzslPXYM5dE2+IbtS-Q2G+-zYJYZhfUVNjOJYJqXc88Fs8heKFYb5UmtYhOyJxTYhdWxuVu6EWxEAA */
model.createMachine(
{
predictableActionArguments: true,
@@ -52,18 +82,57 @@ export const storeMachine =
events: {} as EventFrom,
},
id: 'store',
- initial: 'gettingEncryptionKey',
+ initial: !isCustomSecureKeystore()
+ ? 'gettingEncryptionKey'
+ : 'checkEncryptionKey',
states: {
+ checkEncryptionKey: {
+ invoke: {
+ src: 'hasAndroidEncryptionKey',
+ },
+ on: {
+ READY: {
+ target: 'ready',
+ },
+ ERROR: {
+ target: 'generatingEncryptionKey',
+ },
+ },
+ },
gettingEncryptionKey: {
invoke: {
src: 'getEncryptionKey',
},
on: {
KEY_RECEIVED: {
- actions: 'setEncryptionKey',
+ actions: ['setEncryptionKey', 'logKey'],
target: 'ready',
},
ERROR: {
+ target: 'checkStorageInitialisation',
+ },
+ },
+ },
+ checkStorageInitialisation: {
+ invoke: {
+ src: 'checkStorageInitialisedOrNot',
+ },
+ on: {
+ ERROR: {
+ target: 'failedReadingKey',
+ actions: sendParent('ERROR'),
+ },
+ READY: {
+ target: 'generatingEncryptionKey',
+ },
+ },
+ },
+ failedReadingKey: {
+ on: {
+ TRY_AGAIN: {
+ target: 'gettingEncryptionKey',
+ },
+ IGNORE: {
target: 'generatingEncryptionKey',
},
},
@@ -73,10 +142,17 @@ export const storeMachine =
src: 'generateEncryptionKey',
},
on: {
- KEY_RECEIVED: {
- actions: 'setEncryptionKey',
- target: 'resettingStorage',
- },
+ KEY_RECEIVED: [
+ {
+ cond: 'isCustomSecureKeystore',
+ target: ['ready'],
+ },
+ {
+ actions: 'setEncryptionKey',
+ target: 'resettingStorage',
+ },
+ ],
+
ERROR: {
actions: log('Generating encryption key failed'),
},
@@ -116,9 +192,15 @@ export const storeMachine =
PREPEND: {
actions: 'forwardStoreRequest',
},
+ UPDATE: {
+ actions: 'forwardStoreRequest',
+ },
REMOVE: {
actions: 'forwardStoreRequest',
},
+ REMOVE_VC_METADATA: {
+ actions: 'forwardStoreRequest',
+ },
REMOVE_ITEMS: {
actions: 'forwardStoreRequest',
},
@@ -136,20 +218,42 @@ export const storeMachine =
sendUpdate(),
],
},
- STORE_ERROR: {
- actions: send(
- (_, event) => model.events.STORE_ERROR(event.error),
- {
- to: (_, event) => event.requester,
- }
- ),
+ DECRYPT_ERROR: {
+ actions: sendParent('DECRYPT_ERROR'),
+ },
+ TAMPERED_VC: {
+ actions: ['setIsTamperedVc'],
+ },
+ RESET_IS_TAMPERED: {
+ actions: ['resetIsTamperedVc'],
},
},
},
},
+ on: {
+ STORE_ERROR: {
+ actions: [
+ send((_, event) => model.events.STORE_ERROR(event.error), {
+ to: (_, event) => event.requester,
+ }),
+ sendUpdate(),
+ ],
+ },
+ KEY_INVALIDATE_ERROR: {
+ actions: sendParent('KEY_INVALIDATE_ERROR'),
+ },
+ },
},
{
actions: {
+ setIsTamperedVc: model.assign({
+ isTampered: () => true,
+ }),
+
+ resetIsTamperedVc: model.assign({
+ isTampered: () => false,
+ }),
+
notifyParent: sendParent(model.events.READY()),
forwardStoreRequest: send(
@@ -167,6 +271,46 @@ export const storeMachine =
services: {
clear,
+ hasAndroidEncryptionKey: () => async (callback) => {
+ const hasSetCredentials = SecureKeystore.hasAlias(ENCRYPTION_ID);
+ if (hasSetCredentials) {
+ try {
+ await SecureKeystore.encryptData(
+ DUMMY_KEY_FOR_BIOMETRIC_ALIAS,
+ 'Dummy'
+ );
+ } catch (e) {
+ if (e.message.includes(keyinvalidatedString)) {
+ await clear();
+ callback(model.events.KEY_INVALIDATE_ERROR());
+ sendUpdate();
+ } else {
+ callback(model.events.STORE_ERROR(e));
+ }
+ }
+ callback(model.events.READY());
+ } else {
+ callback(
+ model.events.ERROR(
+ new Error('Could not get the android Key alias')
+ )
+ );
+ }
+ },
+ checkStorageInitialisedOrNot: () => async (callback) => {
+ const isDirectoryExist = await Storage.isVCStorageInitialised();
+ if (!isDirectoryExist) {
+ callback(model.events.READY());
+ } else {
+ callback(
+ model.events.ERROR(
+ new Error(
+ 'vc directory exists and decryption key is not available'
+ )
+ )
+ );
+ }
+ },
store: (context) => (callback, onReceive: Receiver) => {
onReceive(async (event) => {
@@ -205,6 +349,16 @@ export const storeMachine =
response = event.value;
break;
}
+ case 'UPDATE': {
+ await updateItem(
+ event.key,
+ event.value,
+ context.encryptionKey
+ );
+
+ response = event.value;
+ break;
+ }
case 'REMOVE': {
await removeItem(
event.key,
@@ -214,6 +368,15 @@ export const storeMachine =
response = event.value;
break;
}
+ case 'REMOVE_VC_METADATA': {
+ await removeVCMetaData(
+ event.key,
+ event.value,
+ context.encryptionKey
+ );
+ response = event.value;
+ break;
+ }
case 'REMOVE_ITEMS': {
await removeItems(
event.key,
@@ -232,18 +395,32 @@ export const storeMachine =
}
callback(model.events.STORE_RESPONSE(response, event.requester));
} catch (e) {
- console.error(e);
- callback(model.events.STORE_ERROR(e, event.requester));
+ if (e.message.includes(keyinvalidatedString)) {
+ await clear();
+ callback(model.events.KEY_INVALIDATE_ERROR());
+ sendUpdate();
+ } else if (e.message === tamperedErrorMessageString) {
+ callback(model.events.TAMPERED_VC());
+ } else if (
+ e.message.includes('JSON') ||
+ e.message.includes('decrypt')
+ ) {
+ callback(model.events.DECRYPT_ERROR());
+ sendUpdate();
+ } else {
+ console.error(e);
+ callback(model.events.STORE_ERROR(e, event.requester));
+ }
}
});
},
-
getEncryptionKey: () => async (callback) => {
const existingCredentials = await Keychain.getGenericPassword();
-
if (existingCredentials) {
+ console.log('Credentials successfully loaded for user');
callback(model.events.KEY_RECEIVED(existingCredentials.password));
} else {
+ console.log('Credentials failed to load for user');
callback(
model.events.ERROR(
new Error('Could not get keychain credentials.')
@@ -251,28 +428,45 @@ export const storeMachine =
);
}
},
-
generateEncryptionKey: () => async (callback) => {
const randomBytes = await generateSecureRandom(32);
const randomBytesString = binaryToBase64(randomBytes);
- const hasSetCredentials = await Keychain.setGenericPassword(
- ENCRYPTION_ID,
- randomBytesString
- );
-
- if (hasSetCredentials) {
- callback(model.events.KEY_RECEIVED(randomBytesString));
- } else {
- callback(
- model.events.ERROR(
- new Error('Could not generate keychain credentials.')
- )
+ if (!isCustomSecureKeystore()) {
+ const hasSetCredentials = await Keychain.setGenericPassword(
+ ENCRYPTION_ID,
+ randomBytesString
);
+
+ if (hasSetCredentials) {
+ callback(model.events.KEY_RECEIVED(randomBytesString));
+ } else {
+ callback(
+ model.events.ERROR(
+ new Error('Could not generate keychain credentials.')
+ )
+ );
+ }
+ } else {
+ const isBiometricsEnabled = SecureKeystore.hasBiometricsEnabled();
+ await SecureKeystore.generateKey(
+ ENCRYPTION_ID,
+ isBiometricsEnabled,
+ AUTH_TIMEOUT
+ );
+ SecureKeystore.generateHmacshaKey(HMAC_ALIAS);
+ SecureKeystore.generateKey(
+ DUMMY_KEY_FOR_BIOMETRIC_ALIAS,
+ isBiometricsEnabled,
+ 0
+ );
+ callback(model.events.KEY_RECEIVED(''));
}
},
},
- guards: {},
+ guards: {
+ isCustomSecureKeystore: () => isCustomSecureKeystore(),
+ },
}
);
@@ -283,8 +477,8 @@ export async function setItem(
) {
try {
const data = JSON.stringify(value);
- const encrypted = encryptJson(encryptionKey, data);
- await AsyncStorage.setItem(key, encrypted);
+ const encryptedData = await encryptJson(encryptionKey, data);
+ await Storage.setItem(key, encryptedData, encryptionKey);
} catch (e) {
console.error('error setItem:', e);
throw e;
@@ -297,15 +491,28 @@ export async function getItem(
encryptionKey: string
) {
try {
- const data = await AsyncStorage.getItem(key);
+ const data = await Storage.getItem(key, encryptionKey);
+ console.log('getting item for ' + key);
+ console.log(data);
if (data != null) {
- const decrypted = decryptJson(encryptionKey, data);
-
- return JSON.parse(decrypted);
+ const decryptedData = await decryptJson(encryptionKey, data);
+ return JSON.parse(decryptedData);
+ }
+ if (data === null && vcKeyRegExp.exec(key)) {
+ await removeItem(key, data, encryptionKey);
+ throw new Error(tamperedErrorMessageString);
} else {
return defaultValue;
}
} catch (e) {
+ if (
+ e.message.includes(tamperedErrorMessageString) ||
+ e.message.includes(keyinvalidatedString) ||
+ e.message.includes('Key not found') // this error happens when previous get Item calls failed due to key invalidation and data and keys are deleted
+ ) {
+ throw e;
+ }
+ console.error(`Exception in getting item for ${key}: ${e}`);
return defaultValue;
}
}
@@ -342,26 +549,77 @@ export async function prependItem(
}
}
+export async function updateItem(
+ key: string,
+ value: string,
+ encryptionKey: string
+) {
+ try {
+ const list = await getItem(key, [], encryptionKey);
+ const newList = [
+ value,
+ ...list.map((item) => {
+ const vc = item.split(':');
+ if (vc[3] !== value.split(':')[3]) {
+ vc[4] = 'false';
+ return vc.join(':');
+ }
+ }),
+ ].filter((value) => value != undefined && value !== null);
+
+ await setItem(key, newList, encryptionKey);
+ } catch (e) {
+ console.error('error prependItem:', e);
+ throw e;
+ }
+}
+
export async function removeItem(
key: string,
value: string,
encryptionKey: string
) {
try {
- const data = await AsyncStorage.getItem(key);
- const decrypted = decryptJson(encryptionKey, data);
- const list = JSON.parse(decrypted);
- const vcKeyArray = value.split(':');
- const finalVcKeyArray = vcKeyArray.pop();
- const finalVcKey = vcKeyArray.join(':');
- //console.log('finalVcKeyArray', finalVcKeyArray);
+ if (value === null && vcKeyRegExp.exec(key)) {
+ await Storage.removeItem(key);
+ await removeVCMetaData(MY_VCS_STORE_KEY, key, encryptionKey);
+ } else {
+ const data = await Storage.getItem(key, encryptionKey);
+ const decryptedData = await decryptJson(encryptionKey, data);
+ const list = JSON.parse(decryptedData);
+ const vcKeyArray = value.split(':');
+ const finalVcKeyArray = vcKeyArray.pop();
+ const finalVcKey = vcKeyArray.join(':');
+ //console.log('finalVcKeyArray', finalVcKeyArray);
+ const newList = list.filter((vc: string) => {
+ return !vc.includes(finalVcKey);
+ });
+
+ await setItem(key, newList, encryptionKey);
+ await Storage.removeItem(value);
+ }
+ } catch (e) {
+ console.error('error removeItem:', e);
+ throw e;
+ }
+}
+
+export async function removeVCMetaData(
+ key: string,
+ value: string,
+ encryptionKey: string
+) {
+ try {
+ const data = await Storage.getItem(key, encryptionKey);
+ const decryptedData = await decryptJson(encryptionKey, data);
+ const list = JSON.parse(decryptedData);
const newList = list.filter((vc: string) => {
- return !vc.includes(finalVcKey);
+ return !vc.includes(value);
});
await setItem(key, newList, encryptionKey);
} catch (e) {
- console.error('error removeItem:', e);
+ console.error('error remove VC metadata:', e);
throw e;
}
}
@@ -372,14 +630,13 @@ export async function removeItems(
encryptionKey: string
) {
try {
- const data = await AsyncStorage.getItem(key);
- const decrypted = decryptJson(encryptionKey, data);
- const list = JSON.parse(decrypted);
+ const data = await Storage.getItem(key, encryptionKey);
+ const decryptedData = await decryptJson(encryptionKey, data);
+ const list = JSON.parse(decryptedData);
const newList = list.filter(function (vc: string) {
return !values.find(function (vcKey: string) {
const vcKeyArray = vcKey.split(':');
const finalVcKeyArray = vcKeyArray.pop();
- //console.log('finalVcKeyArray', finalVcKeyArray);
const finalVcKey = vcKeyArray.join(':');
return vc.includes(finalVcKey);
});
@@ -392,26 +649,8 @@ export async function removeItems(
}
}
-export async function clear() {
- try {
- await AsyncStorage.clear();
- } catch (e) {
- console.error('error clear:', e);
- throw e;
- }
-}
+type State = StateFrom;
-export function encryptJson(encryptionKey: string, data: string): string {
- return CryptoJS.AES.encrypt(data, encryptionKey).toString();
-}
-
-export function decryptJson(encryptionKey: string, encrypted: string): string {
- try {
- return CryptoJS.AES.decrypt(encrypted, encryptionKey).toString(
- CryptoJS.enc.Utf8
- );
- } catch (e) {
- console.error('error decryptJson:', e);
- throw e;
- }
+export function selectIsTampered(state: State) {
+ return state.context.isTampered;
}
diff --git a/machines/store.typegen.ts b/machines/store.typegen.ts
index 7e8fa593..c689d514 100644
--- a/machines/store.typegen.ts
+++ b/machines/store.typegen.ts
@@ -17,13 +17,15 @@ export interface Typegen0 {
'xstate.init': { type: 'xstate.init' };
};
'invokeSrcNameMap': {
+ checkStorageInitialisedOrNot: 'done.invoke.store.checkStorageInitialisation:invocation[0]';
clear: 'done.invoke.store.resettingStorage:invocation[0]';
generateEncryptionKey: 'done.invoke.store.generatingEncryptionKey:invocation[0]';
getEncryptionKey: 'done.invoke.store.gettingEncryptionKey:invocation[0]';
+ hasAndroidEncryptionKey: 'done.invoke.store.checkEncryptionKey:invocation[0]';
store: 'done.invoke._store';
};
'missingImplementations': {
- actions: never;
+ actions: 'logKey';
delays: never;
guards: never;
services: never;
@@ -36,21 +38,37 @@ export interface Typegen0 {
| 'PREPEND'
| 'REMOVE'
| 'REMOVE_ITEMS'
- | 'SET';
+ | 'REMOVE_VC_METADATA'
+ | 'SET'
+ | 'UPDATE';
+ logKey: 'KEY_RECEIVED';
notifyParent:
| 'KEY_RECEIVED'
+ | 'READY'
| 'done.invoke.store.resettingStorage:invocation[0]';
+ resetIsTamperedVc: 'RESET_IS_TAMPERED';
setEncryptionKey: 'KEY_RECEIVED';
+ setIsTamperedVc: 'TAMPERED_VC';
};
'eventsCausingDelays': {};
- 'eventsCausingGuards': {};
+ 'eventsCausingGuards': {
+ isCustomSecureKeystore: 'KEY_RECEIVED';
+ };
'eventsCausingServices': {
+ checkStorageInitialisedOrNot: 'ERROR';
clear: 'KEY_RECEIVED';
- generateEncryptionKey: 'ERROR';
- getEncryptionKey: 'xstate.init';
- store: 'KEY_RECEIVED' | 'done.invoke.store.resettingStorage:invocation[0]';
+ generateEncryptionKey: 'ERROR' | 'IGNORE' | 'READY';
+ getEncryptionKey: 'TRY_AGAIN';
+ hasAndroidEncryptionKey: never;
+ store:
+ | 'KEY_RECEIVED'
+ | 'READY'
+ | 'done.invoke.store.resettingStorage:invocation[0]';
};
'matchesStates':
+ | 'checkEncryptionKey'
+ | 'checkStorageInitialisation'
+ | 'failedReadingKey'
| 'generatingEncryptionKey'
| 'gettingEncryptionKey'
| 'ready'
diff --git a/machines/vc.ts b/machines/vc.ts
index 8b8c1ad4..b970b2cb 100644
--- a/machines/vc.ts
+++ b/machines/vc.ts
@@ -10,6 +10,7 @@ import {
MY_VCS_STORE_KEY,
RECEIVED_VCS_STORE_KEY,
VC_ITEM_STORE_KEY,
+ isSameVC,
} from '../shared/constants';
const model = createModel(
@@ -26,8 +27,11 @@ const model = createModel(
STORE_RESPONSE: (response: unknown) => ({ response }),
STORE_ERROR: (error: Error) => ({ error }),
VC_ADDED: (vcKey: string) => ({ vcKey }),
+ REMOVE_VC_FROM_CONTEXT: (vcKey: string) => ({ vcKey }),
+ VC_UPDATED: (vcKey: string) => ({ vcKey }),
VC_RECEIVED: (vcKey: string) => ({ vcKey }),
VC_DOWNLOADED: (vc: VC) => ({ vc }),
+ VC_UPDATE: (vc: VC) => ({ vc }),
REFRESH_MY_VCS: () => ({}),
REFRESH_MY_VCS_TWO: (vc: VC) => ({ vc }),
REFRESH_RECEIVED_VCS: () => ({}),
@@ -53,6 +57,11 @@ export const vcMachine =
initial: 'init',
states: {
init: {
+ on: {
+ REFRESH_MY_VCS: {
+ target: '#vc.ready.myVcs.refreshing',
+ },
+ },
initial: 'myVcs',
states: {
myVcs: {
@@ -133,9 +142,18 @@ export const vcMachine =
VC_ADDED: {
actions: 'prependToMyVcs',
},
+ REMOVE_VC_FROM_CONTEXT: {
+ actions: 'removeVcFromMyVcs',
+ },
+ VC_UPDATED: {
+ actions: ['updateMyVcs', 'setUpdateVc'],
+ },
VC_DOWNLOADED: {
actions: 'setDownloadedVc',
},
+ VC_UPDATE: {
+ actions: 'setVcUpdate',
+ },
VC_RECEIVED: [
{
actions: 'moveExistingVcToTop',
@@ -181,10 +199,46 @@ export const vcMachine =
context.vcs[VC_ITEM_STORE_KEY(event.vc)] = event.vc;
},
+ setVcUpdate: (context, event) => {
+ Object.keys(context.vcs).map((vcKey) => {
+ if (isSameVC(vcKey, VC_ITEM_STORE_KEY(event.vc))) {
+ context.vcs[VC_ITEM_STORE_KEY(event.vc)] = context.vcs[vcKey];
+ delete context.vcs[vcKey];
+ return context.vcs[VC_ITEM_STORE_KEY(event.vc)];
+ }
+ });
+ },
+
+ setUpdateVc: send(
+ (_context, event) => {
+ return StoreEvents.UPDATE(MY_VCS_STORE_KEY, event.vcKey);
+ },
+ { to: (context) => context.serviceRefs.store }
+ ),
+
prependToMyVcs: model.assign({
myVcs: (context, event) => [event.vcKey, ...context.myVcs],
}),
+ removeVcFromMyVcs: model.assign({
+ myVcs: (context, event) =>
+ context.myVcs.filter((vc: string) => !vc.includes(event.vcKey)),
+ }),
+
+ updateMyVcs: model.assign({
+ myVcs: (context, event) =>
+ [
+ event.vcKey,
+ ...context.myVcs.map((value) => {
+ const vc = value.split(':');
+ if (vc[3] !== event.vcKey.split(':')[3]) {
+ vc[4] = 'false';
+ return vc.join(':');
+ }
+ }),
+ ].filter((value) => value != undefined),
+ }),
+
prependToReceivedVcs: model.assign({
receivedVcs: (context, event) => [
event.vcKey,
@@ -240,13 +294,18 @@ export function selectIsRefreshingReceivedVcs(state: State) {
return state.matches('ready.receivedVcs.refreshing');
}
+/*
+ this methods returns all the binded vc's in the wallet.
+ */
export function selectBindedVcs(state: State) {
- return (Object.keys(state.context.vcs) as Array).filter((key) => {
- var walletBindingResponse = state.context.vcs[key].walletBindingResponse;
+ return (state.context.myVcs as Array).filter((key) => {
+ const walletBindingResponse = state.context.vcs[key]?.walletBindingResponse;
return (
- walletBindingResponse !== null &&
- walletBindingResponse.walletBindingId !== null &&
- walletBindingResponse.walletBindingId !== ''
+ !isEmpty(walletBindingResponse) &&
+ !isEmpty(walletBindingResponse?.walletBindingId)
);
});
}
+function isEmpty(object) {
+ return object == null || object == '' || object == undefined;
+}
diff --git a/machines/vc.typegen.ts b/machines/vc.typegen.ts
index e69de29b..a6a4ef9e 100644
--- a/machines/vc.typegen.ts
+++ b/machines/vc.typegen.ts
@@ -0,0 +1,58 @@
+// This file was automatically generated. Edits will be overwritten
+
+export interface Typegen0 {
+ '@@xstate/typegen': true;
+ 'internalEvents': {
+ 'xstate.init': { type: 'xstate.init' };
+ };
+ 'invokeSrcNameMap': {};
+ 'missingImplementations': {
+ actions: never;
+ delays: never;
+ guards: never;
+ services: never;
+ };
+ 'eventsCausingActions': {
+ getReceivedVcsResponse: 'GET_RECEIVED_VCS';
+ getVcItemResponse: 'GET_VC_ITEM';
+ loadMyVcs: 'REFRESH_MY_VCS' | 'xstate.init';
+ loadReceivedVcs: 'REFRESH_RECEIVED_VCS' | 'STORE_RESPONSE';
+ moveExistingVcToTop: 'VC_RECEIVED';
+ prependToMyVcs: 'VC_ADDED';
+ prependToReceivedVcs: 'VC_RECEIVED';
+ removeVcFromMyVcs: 'REMOVE_VC_FROM_CONTEXT';
+ setDownloadedVc: 'VC_DOWNLOADED';
+ setMyVcs: 'STORE_RESPONSE';
+ setReceivedVcs: 'STORE_RESPONSE';
+ setUpdateVc: 'VC_UPDATED';
+ setVcUpdate: 'VC_UPDATE';
+ updateMyVcs: 'VC_UPDATED';
+ };
+ 'eventsCausingDelays': {};
+ 'eventsCausingGuards': {
+ hasExistingReceivedVc: 'VC_RECEIVED';
+ };
+ 'eventsCausingServices': {};
+ 'matchesStates':
+ | 'init'
+ | 'init.myVcs'
+ | 'init.receivedVcs'
+ | 'ready'
+ | 'ready.myVcs'
+ | 'ready.myVcs.idle'
+ | 'ready.myVcs.refreshing'
+ | 'ready.receivedVcs'
+ | 'ready.receivedVcs.idle'
+ | 'ready.receivedVcs.refreshing'
+ | {
+ init?: 'myVcs' | 'receivedVcs';
+ ready?:
+ | 'myVcs'
+ | 'receivedVcs'
+ | {
+ myVcs?: 'idle' | 'refreshing';
+ receivedVcs?: 'idle' | 'refreshing';
+ };
+ };
+ 'tags': never;
+}
diff --git a/machines/vcItem.ts b/machines/vcItem.ts
index a86b1b38..fa4d46e3 100644
--- a/machines/vcItem.ts
+++ b/machines/vcItem.ts
@@ -1,6 +1,11 @@
import { assign, ErrorPlatformEvent, EventFrom, send, StateFrom } from 'xstate';
import { createModel } from 'xstate/lib/model';
-import { MY_VCS_STORE_KEY, VC_ITEM_STORE_KEY } from '../shared/constants';
+import {
+ HOST,
+ MY_VCS_STORE_KEY,
+ VC_ITEM_STORE_KEY,
+ VC_ITEM_STORE_KEY_AFTER_DOWNLOAD,
+} from '../shared/constants';
import { AppServices } from '../shared/GlobalContext';
import { CredentialDownloadResponse, request } from '../shared/request';
import {
@@ -15,6 +20,7 @@ import { verifyCredential } from '../shared/vcjs/verifyCredential';
import { log } from 'xstate/lib/actions';
import {
generateKeys,
+ isCustomSecureKeystore,
WalletBindingResponse,
} from '../shared/cryptoutil/cryptoUtil';
import { KeyPair } from 'react-native-rsa-native';
@@ -25,6 +31,9 @@ import {
import getAllConfigurations, {
DownloadProps,
} from '../shared/commonprops/commonProps';
+import { VcEvents } from './vc';
+import i18n from '../i18n';
+import SecureKeystore from 'react-native-secure-keystore';
const model = createModel(
{
@@ -32,11 +41,15 @@ const model = createModel(
id: '',
idType: '' as VcIdType,
tag: '',
+ vcKey: '' as string,
+ myVcs: [] as string[],
generatedOn: null as Date,
credential: null as DecodedCredential,
verifiableCredential: null as VerifiableCredential,
+ storeVerifiableCredential: null as VerifiableCredential,
requestId: '',
isVerified: false,
+ isPinned: false,
lastVerifiedOn: null,
locked: false,
otp: '',
@@ -52,6 +65,7 @@ const model = createModel(
walletBindingError: '',
publicKey: '',
privateKey: '',
+ hashedId: '',
},
{
events: {
@@ -74,6 +88,11 @@ const model = createModel(
ADD_WALLET_BINDING_ID: () => ({}),
CANCEL: () => ({}),
CONFIRM: () => ({}),
+ STORE_ERROR: (error: Error) => ({ error }),
+ PIN_CARD: () => ({}),
+ KEBAB_POPUP: () => ({}),
+ SHOW_ACTIVITY: () => ({}),
+ REMOVE: (vcKey: string) => ({ vcKey }),
},
}
);
@@ -183,13 +202,36 @@ export const vcItemMachine =
],
CREDENTIAL_DOWNLOADED: {
actions: [
- 'setCredential',
+ 'setStoreVerifiableCredential',
'storeContext',
+ 'editVcKey',
+ ],
+ },
+ STORE_RESPONSE: {
+ actions: [
+ 'setVerifiableCredential',
'updateVc',
'logDownloaded',
],
target: '#vc-item.checkingVerificationStatus',
},
+ STORE_ERROR: {
+ target: '#vc-item.checkingServerData.savingFailed',
+ },
+ },
+ },
+ savingFailed: {
+ entry: ['removeVcMetaDataFromStorage'],
+ initial: 'idle',
+ states: {
+ idle: {},
+ viewingVc: {},
+ },
+ on: {
+ DISMISS: {
+ actions: ['removeVcMetaDataFromVcMachine'],
+ target: '.viewingVc',
+ },
},
},
},
@@ -212,6 +254,198 @@ export const vcItemMachine =
ADD_WALLET_BINDING_ID: {
target: 'showBindingWarning',
},
+ PIN_CARD: {
+ target: 'pinCard',
+ actions: 'setPinCard',
+ },
+ KEBAB_POPUP: {
+ target: 'kebabPopUp',
+ },
+ DISMISS: {
+ target: 'checkingVc',
+ },
+ },
+ },
+ pinCard: {
+ entry: 'storeContext',
+ on: {
+ STORE_RESPONSE: {
+ actions: ['sendVcUpdated', 'VcUpdated'],
+ target: 'idle',
+ },
+ },
+ },
+ kebabPopUp: {
+ on: {
+ DISMISS: {
+ target: 'idle',
+ },
+ ADD_WALLET_BINDING_ID: {
+ target: '#vc-item.kebabPopUp.showBindingWarning',
+ },
+ PIN_CARD: {
+ target: '#vc-item.pinCard',
+ actions: 'setPinCard',
+ },
+ SHOW_ACTIVITY: {
+ target: '#vc-item.kebabPopUp.showActivities',
+ },
+ REMOVE: {
+ actions: 'setVcKey',
+ target: '#vc-item.kebabPopUp.removeWallet',
+ },
+ },
+ initial: 'idle',
+ states: {
+ idle: {},
+ showBindingWarning: {
+ on: {
+ CONFIRM: {
+ target: '#vc-item.kebabPopUp.requestingBindingOtp',
+ },
+ CANCEL: {
+ target: '#vc-item.kebabPopUp',
+ },
+ },
+ },
+ requestingBindingOtp: {
+ invoke: {
+ src: 'requestBindingOtp',
+ onDone: [
+ {
+ target: '#vc-item.kebabPopUp.acceptingBindingOtp',
+ actions: [log('accceptingOTP')],
+ },
+ ],
+ onError: [
+ {
+ actions: 'setWalletBindingError',
+ target: '#vc-item.kebabPopUp.showingWalletBindingError',
+ },
+ ],
+ },
+ },
+ showingWalletBindingError: {
+ on: {
+ CANCEL: {
+ target: '#vc-item.kebabPopUp',
+ actions: 'setWalletBindingErrorEmpty',
+ },
+ },
+ },
+ acceptingBindingOtp: {
+ entry: ['clearOtp'],
+ on: {
+ INPUT_OTP: {
+ target: '#vc-item.kebabPopUp.addKeyPair',
+ actions: ['setOtp'],
+ },
+ DISMISS: {
+ target: '#vc-item.kebabPopUp',
+ actions: ['clearOtp', 'clearTransactionId'],
+ },
+ },
+ },
+ addKeyPair: {
+ invoke: {
+ src: 'generateKeyPair',
+ onDone: [
+ {
+ cond: 'isCustomSecureKeystore',
+ target: '#vc-item.kebabPopUp.addingWalletBindingId',
+ actions: ['setPublicKey'],
+ },
+ {
+ target: '#vc-item.kebabPopUp.addingWalletBindingId',
+ actions: ['setPublicKey', 'setPrivateKey'],
+ },
+ ],
+ onError: [
+ {
+ actions: 'setWalletBindingError',
+ target: '#vc-item.kebabPopUp.showingWalletBindingError',
+ },
+ ],
+ },
+ },
+ addingWalletBindingId: {
+ invoke: {
+ src: 'addWalletBindnigId',
+ onDone: [
+ {
+ cond: 'isCustomSecureKeystore',
+ target: '#vc-item.kebabPopUp',
+ actions: [
+ 'setWalletBindingId',
+ 'setThumbprintForWalletBindingId',
+ 'storeContext',
+ 'updateVc',
+ 'setWalletBindingErrorEmpty',
+ 'logWalletBindingSuccess',
+ ],
+ },
+ {
+ target: '#vc-item.kebabPopUp.updatingPrivateKey',
+ actions: [
+ 'setWalletBindingId',
+ 'setThumbprintForWalletBindingId',
+ ],
+ },
+ ],
+ onError: [
+ {
+ actions: [
+ 'setWalletBindingError',
+ 'logWalletBindingFailure',
+ ],
+ target: '#vc-item.kebabPopUp.showingWalletBindingError',
+ },
+ ],
+ },
+ },
+ updatingPrivateKey: {
+ invoke: {
+ src: 'updatePrivateKey',
+ onDone: {
+ actions: [
+ 'storeContext',
+ 'updatePrivateKey',
+ 'updateVc',
+ 'setWalletBindingErrorEmpty',
+ 'logWalletBindingSuccess',
+ ],
+ target: '#vc-item.kebabPopUp',
+ },
+ onError: {
+ actions: 'setWalletBindingError',
+ target: '#vc-item.kebabPopUp.showingWalletBindingError',
+ },
+ },
+ },
+ showActivities: {
+ on: {
+ DISMISS: '#vc-item.kebabPopUp',
+ },
+ },
+ removeWallet: {
+ on: {
+ CONFIRM: {
+ target: 'removingVc',
+ },
+ CANCEL: {
+ target: 'idle',
+ },
+ },
+ },
+ removingVc: {
+ entry: 'removeVcItem',
+ on: {
+ STORE_RESPONSE: {
+ actions: ['removedVc', 'logVCremoved'],
+ target: '#vc-item',
+ },
+ },
+ },
},
},
editingTag: {
@@ -415,7 +649,7 @@ export const vcItemMachine =
],
onError: [
{
- actions: 'setWalletBindingError',
+ actions: ['setWalletBindingError', 'logWalletBindingFailure'],
target: 'showingWalletBindingError',
},
],
@@ -445,13 +679,20 @@ export const vcItemMachine =
addKeyPair: {
invoke: {
src: 'generateKeyPair',
- onDone: {
- target: 'addingWalletBindingId',
- actions: ['setPublicKey', 'setPrivateKey'],
- },
+ onDone: [
+ {
+ cond: 'isCustomSecureKeystore',
+ target: 'addingWalletBindingId',
+ actions: ['setPublicKey'],
+ },
+ {
+ target: 'addingWalletBindingId',
+ actions: ['setPublicKey', 'setPrivateKey'],
+ },
+ ],
onError: [
{
- actions: 'setWalletBindingError',
+ actions: ['setWalletBindingError', 'logWalletBindingFailure'],
target: 'showingWalletBindingError',
},
],
@@ -461,14 +702,29 @@ export const vcItemMachine =
invoke: {
src: 'addWalletBindnigId',
onDone: [
+ {
+ cond: 'isCustomSecureKeystore',
+ target: 'idle',
+ actions: [
+ 'setWalletBindingId',
+ 'setThumbprintForWalletBindingId',
+ 'storeContext',
+ 'updateVc',
+ 'setWalletBindingErrorEmpty',
+ 'logWalletBindingSuccess',
+ ],
+ },
{
target: 'updatingPrivateKey',
- actions: ['setWalletBindingId'],
+ actions: [
+ 'setWalletBindingId',
+ 'setThumbprintForWalletBindingId',
+ ],
},
],
onError: [
{
- actions: 'setWalletBindingError',
+ actions: ['setWalletBindingError', 'logWalletBindingFailure'],
target: 'showingWalletBindingError',
},
],
@@ -478,16 +734,17 @@ export const vcItemMachine =
invoke: {
src: 'updatePrivateKey',
onDone: {
- target: 'idle',
actions: [
'storeContext',
'updatePrivateKey',
'updateVc',
'setWalletBindingErrorEmpty',
+ 'logWalletBindingSuccess',
],
+ target: 'idle',
},
onError: {
- actions: 'setWalletBindingError',
+ actions: ['setWalletBindingError', 'logWalletBindingFailure'],
target: 'showingWalletBindingError',
},
},
@@ -496,8 +753,58 @@ export const vcItemMachine =
},
{
actions: {
+ setVerifiableCredential: assign((context) => {
+ return {
+ ...context,
+ verifiableCredential: {
+ ...context.storeVerifiableCredential,
+ },
+ storeVerifiableCredential: null,
+ };
+ }),
+
+ setStoreVerifiableCredential: model.assign((context, event) => {
+ return {
+ ...context,
+ ...event.vc,
+ storeVerifiableCredential: {
+ ...event.vc.verifiableCredential,
+ },
+ verifiableCredential: null,
+ };
+ }),
+
+ removeVcMetaDataFromStorage: send(
+ (context) => {
+ const { serviceRefs, ...data } = context;
+ return StoreEvents.REMOVE_VC_METADATA(
+ MY_VCS_STORE_KEY,
+ VC_ITEM_STORE_KEY(context)
+ );
+ },
+ {
+ to: (context) => context.serviceRefs.store,
+ }
+ ),
+
+ removeVcMetaDataFromVcMachine: send(
+ (context, _event) => {
+ const { serviceRefs, ...data } = context;
+ return {
+ type: 'REMOVE_VC_FROM_CONTEXT',
+ vcKey: VC_ITEM_STORE_KEY(context),
+ };
+ },
+ {
+ to: (context) => context.serviceRefs.vc,
+ }
+ ),
+
setWalletBindingError: assign({
- walletBindingError: (context, event) => (event.data as Error).message,
+ walletBindingError: (context, event) =>
+ i18n.t(`errors.genericError`, {
+ ns: 'common',
+ }),
}),
setWalletBindingErrorEmpty: assign({
@@ -505,7 +812,12 @@ export const vcItemMachine =
}),
setPublicKey: assign({
- publicKey: (context, event) => (event.data as KeyPair).public,
+ publicKey: (context, event) => {
+ if (!isCustomSecureKeystore()) {
+ return (event.data as KeyPair).public;
+ }
+ return event.data as string;
+ },
}),
setPrivateKey: assign({
@@ -521,6 +833,21 @@ export const vcItemMachine =
event.data as WalletBindingResponse,
}),
+ setPinCard: assign((context) => {
+ return {
+ ...context,
+ isPinned: !context.isPinned,
+ };
+ }),
+
+ sendVcUpdated: send(
+ (_context, event) =>
+ VcEvents.VC_UPDATED(VC_ITEM_STORE_KEY(event.response) as string),
+ {
+ to: (context) => context.serviceRefs.vc,
+ }
+ ),
+
updateVc: send(
(context) => {
const { serviceRefs, ...vc } = context;
@@ -531,6 +858,41 @@ export const vcItemMachine =
}
),
+ VcUpdated: send(
+ (context) => {
+ const { serviceRefs, ...vc } = context;
+ return { type: 'VC_UPDATE', vc };
+ },
+ {
+ to: (context) => context.serviceRefs.vc,
+ }
+ ),
+
+ setThumbprintForWalletBindingId: send(
+ (context) => {
+ const { walletBindingResponse } = context;
+ const walletBindingIdKey = getBindingCertificateConstant(
+ walletBindingResponse.walletBindingId
+ );
+ return StoreEvents.SET(
+ walletBindingIdKey,
+ walletBindingResponse.thumbprint
+ );
+ },
+ {
+ to: (context) => context.serviceRefs.store,
+ }
+ ),
+
+ removedVc: send(
+ () => ({
+ type: 'REFRESH_MY_VCS',
+ }),
+ {
+ to: (context) => context.serviceRefs.vc,
+ }
+ ),
+
requestVcContext: send(
(context) => ({
type: 'GET_VC_ITEM',
@@ -551,6 +913,7 @@ export const vcItemMachine =
storeContext: send(
(context) => {
const { serviceRefs, ...data } = context;
+ data.credentialRegistry = HOST;
return StoreEvents.SET(VC_ITEM_STORE_KEY(context), data);
},
{
@@ -558,6 +921,14 @@ export const vcItemMachine =
}
),
+ editVcKey: send((context) => {
+ const { serviceRefs, ...data } = context;
+ return StoreEvents.SET(
+ VC_ITEM_STORE_KEY_AFTER_DOWNLOAD(context),
+ data
+ );
+ }),
+
setTag: model.assign({
tag: (_, event) => event.tag,
}),
@@ -595,13 +966,43 @@ export const vcItemMachine =
}),
logDownloaded: send(
- (_, event) =>
- ActivityLogEvents.LOG_ACTIVITY({
- _vcKey: VC_ITEM_STORE_KEY(event.vc),
+ (context) => {
+ const { serviceRefs, ...data } = context;
+ return ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: VC_ITEM_STORE_KEY(data),
type: 'VC_DOWNLOADED',
timestamp: Date.now(),
deviceName: '',
- vcLabel: event.vc.tag || event.vc.id,
+ vcLabel: data.tag || data.id,
+ });
+ },
+ {
+ to: (context) => context.serviceRefs.activityLog,
+ }
+ ),
+
+ logWalletBindingSuccess: send(
+ (context, event) =>
+ ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: VC_ITEM_STORE_KEY(context),
+ type: 'WALLET_BINDING_SUCCESSFULL',
+ timestamp: Date.now(),
+ deviceName: '',
+ vcLabel: context.tag || context.id,
+ }),
+ {
+ to: (context) => context.serviceRefs.activityLog,
+ }
+ ),
+
+ logWalletBindingFailure: send(
+ (context, event) =>
+ ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: VC_ITEM_STORE_KEY(context),
+ type: 'WALLET_BINDING_FAILURE',
+ timestamp: Date.now(),
+ deviceName: '',
+ vcLabel: context.tag || context.id,
}),
{
to: (context) => context.serviceRefs.activityLog,
@@ -652,6 +1053,10 @@ export const vcItemMachine =
otp: (_, event) => event.otp,
}),
+ setVcKey: model.assign({
+ vcKey: (_, event) => event.vcKey,
+ }),
+
setOtpError: assign({
otpError: (_context, event) =>
(event as ErrorPlatformEvent).data.message,
@@ -674,6 +1079,27 @@ export const vcItemMachine =
},
{ to: (context) => context.serviceRefs.store }
),
+
+ removeVcItem: send(
+ (_context, event) => {
+ return StoreEvents.REMOVE(MY_VCS_STORE_KEY, _context.vcKey);
+ },
+ { to: (context) => context.serviceRefs.store }
+ ),
+
+ logVCremoved: send(
+ (context, _) =>
+ ActivityLogEvents.LOG_ACTIVITY({
+ _vcKey: VC_ITEM_STORE_KEY(context),
+ type: 'VC_REMOVED',
+ timestamp: Date.now(),
+ deviceName: '',
+ vcLabel: context.id,
+ }),
+ {
+ to: (context) => context.serviceRefs.activityLog,
+ }
+ ),
},
services: {
@@ -706,7 +1132,7 @@ export const vcItemMachine =
authFactorType: 'WLA',
format: 'jwt',
individualId: context.id,
- transactionId: context.bindingTransactionId,
+ transactionId: context.transactionId,
publicKey: context.publicKey,
challengeList: [
{
@@ -745,8 +1171,15 @@ export const vcItemMachine =
},
generateKeyPair: async (context) => {
- let keyPair: KeyPair = await generateKeys();
- return keyPair;
+ if (!isCustomSecureKeystore()) {
+ return await generateKeys();
+ }
+ const isBiometricsEnabled = SecureKeystore.hasBiometricsEnabled();
+ return SecureKeystore.generateKeyPair(
+ context.id,
+ isBiometricsEnabled,
+ 0
+ );
},
requestBindingOtp: async (context) => {
@@ -819,9 +1252,11 @@ export const vcItemMachine =
tag: '',
requestId: context.requestId,
isVerified: false,
+ isPinned: context.isPinned,
lastVerifiedOn: null,
locked: context.locked,
walletBindingResponse: null,
+ credentialRegistry: '',
})
);
}
@@ -908,6 +1343,8 @@ export const vcItemMachine =
isVcValid: (context) => {
return context.isVerified;
},
+
+ isCustomSecureKeystore: () => isCustomSecureKeystore(),
},
}
);
@@ -916,13 +1353,15 @@ export const createVcItemMachine = (
serviceRefs: AppServices,
vcKey: string
) => {
- const [, idType, id, requestId] = vcKey.split(':');
+ const [, idType, hashedId, requestId, isPinned, id] = vcKey.split(':');
return vcItemMachine.withContext({
...vcItemMachine.context,
serviceRefs,
id,
idType: idType as VcIdType,
requestId,
+ isPinned: isPinned == 'true' ? true : false,
+ hashedId,
});
};
@@ -972,6 +1411,9 @@ export function selectIsOtpError(state: State) {
export function selectOtpError(state: State) {
return state.context.otpError;
}
+export function selectIsPinned(state: State) {
+ return state.context.isPinned;
+}
export function selectIsLockingVc(state: State) {
return state.matches('lockingVc');
@@ -993,34 +1435,33 @@ export function selectIsAcceptingRevokeInput(state: State) {
return state.matches('acceptingRevokeInput');
}
-export function selectIsRequestBindingOtp(state: State) {
- return state.matches('requestingBindingOtp');
-}
-
-export function selectWalletBindingId(state: State) {
- return state.context.walletBindingResponse;
-}
-
export function selectEmptyWalletBindingId(state: State) {
var val = state.context.walletBindingResponse
? state.context.walletBindingResponse.walletBindingId
: undefined;
- return val === undefined || val == null || val.length <= 0 ? true : false;
+ return val == undefined || val == null || val.length <= 0 ? true : false;
}
export function selectWalletBindingError(state: State) {
return state.context.walletBindingError;
}
+export function selectRequestBindingOtp(state: State) {
+ return state.matches('requestingBindingOtp');
+}
+
export function selectAcceptingBindingOtp(state: State) {
return state.matches('acceptingBindingOtp');
}
export function selectShowWalletBindingError(state: State) {
- return state.matches('showingWalletBindingError');
+ return (
+ state.matches('showingWalletBindingError') ||
+ state.matches('kebabPopUp.showingWalletBindingError')
+ );
}
-export function isWalletBindingInProgress(state: State) {
+export function selectWalletBindingInProgress(state: State) {
return state.matches('requestingBindingOtp') ||
state.matches('addingWalletBindingId') ||
state.matches('addKeyPair') ||
@@ -1029,6 +1470,46 @@ export function isWalletBindingInProgress(state: State) {
: false;
}
-export function isShowingBindingWarning(state: State) {
+export function selectBindingWarning(state: State) {
return state.matches('showBindingWarning');
}
+export function selectKebabPopUp(state: State) {
+ return state.matches('kebabPopUp');
+}
+
+export function selectKebabPopUpRequestBindingOtp(state: State) {
+ return state.matches('kebabPopUp.requestingBindingOtp');
+}
+
+export function selectKebabPopUpAcceptingBindingOtp(state: State) {
+ return state.matches('kebabPopUp.acceptingBindingOtp');
+}
+
+export function selectKebabPopUpShowWalletBindingError(state: State) {
+ return state.matches('kebabPopUp.showingWalletBindingError');
+}
+
+export function selectKebabPopUpWalletBindingInProgress(state: State) {
+ return state.matches('kebabPopUp.requestingBindingOtp') ||
+ state.matches('kebabPopUp.addingWalletBindingId') ||
+ state.matches('kebabPopUp.addKeyPair') ||
+ state.matches('kebabPopUp.updatingPrivateKey')
+ ? true
+ : false;
+}
+
+export function selectKebabPopUpBindingWarning(state: State) {
+ return state.matches('kebabPopUp.showBindingWarning');
+}
+
+export function selectRemoveWalletWarning(state: State) {
+ return state.matches('kebabPopUp.removeWallet');
+}
+
+export function selectShowActivities(state: State) {
+ return state.matches('kebabPopUp.showActivities');
+}
+
+export function selectIsSavingFailedInIdle(state: State) {
+ return state.matches('checkingServerData.savingFailed.idle');
+}
diff --git a/machines/vcItem.typegen.ts b/machines/vcItem.typegen.ts
index 3e96e46c..7a972e4b 100644
--- a/machines/vcItem.typegen.ts
+++ b/machines/vcItem.typegen.ts
@@ -29,6 +29,26 @@ export interface Typegen0 {
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
+ 'done.invoke.vc-item.kebabPopUp.addKeyPair:invocation[0]': {
+ type: 'done.invoke.vc-item.kebabPopUp.addKeyPair:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
+ 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]': {
+ type: 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
+ 'done.invoke.vc-item.kebabPopUp.requestingBindingOtp:invocation[0]': {
+ type: 'done.invoke.vc-item.kebabPopUp.requestingBindingOtp:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
+ 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]': {
+ type: 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
'done.invoke.vc-item.requestingBindingOtp:invocation[0]': {
type: 'done.invoke.vc-item.requestingBindingOtp:invocation[0]';
data: unknown;
@@ -75,6 +95,26 @@ export interface Typegen0 {
type: 'error.platform.vc-item.addingWalletBindingId:invocation[0]';
data: unknown;
};
+ 'error.platform.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]': {
+ type: 'error.platform.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]';
+ data: unknown;
+ };
+ 'error.platform.vc-item.kebabPopUp.addKeyPair:invocation[0]': {
+ type: 'error.platform.vc-item.kebabPopUp.addKeyPair:invocation[0]';
+ data: unknown;
+ };
+ 'error.platform.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]': {
+ type: 'error.platform.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]';
+ data: unknown;
+ };
+ 'error.platform.vc-item.kebabPopUp.requestingBindingOtp:invocation[0]': {
+ type: 'error.platform.vc-item.kebabPopUp.requestingBindingOtp:invocation[0]';
+ data: unknown;
+ };
+ 'error.platform.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]': {
+ type: 'error.platform.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]';
+ data: unknown;
+ };
'error.platform.vc-item.requestingBindingOtp:invocation[0]': {
type: 'error.platform.vc-item.requestingBindingOtp:invocation[0]';
data: unknown;
@@ -98,16 +138,24 @@ export interface Typegen0 {
'xstate.init': { type: 'xstate.init' };
};
'invokeSrcNameMap': {
- addWalletBindnigId: 'done.invoke.vc-item.addingWalletBindingId:invocation[0]';
+ addWalletBindnigId:
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]';
checkDownloadExpiryLimit: 'done.invoke.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]';
checkStatus: 'done.invoke.checkStatus';
downloadCredential: 'done.invoke.downloadCredential';
- generateKeyPair: 'done.invoke.vc-item.addKeyPair:invocation[0]';
- requestBindingOtp: 'done.invoke.vc-item.requestingBindingOtp:invocation[0]';
+ generateKeyPair:
+ | 'done.invoke.vc-item.addKeyPair:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addKeyPair:invocation[0]';
+ requestBindingOtp:
+ | 'done.invoke.vc-item.kebabPopUp.requestingBindingOtp:invocation[0]'
+ | 'done.invoke.vc-item.requestingBindingOtp:invocation[0]';
requestLock: 'done.invoke.vc-item.requestingLock:invocation[0]';
requestOtp: 'done.invoke.vc-item.requestingOtp:invocation[0]';
requestRevoke: 'done.invoke.vc-item.requestingRevoke:invocation[0]';
- updatePrivateKey: 'done.invoke.vc-item.updatingPrivateKey:invocation[0]';
+ updatePrivateKey:
+ | 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
+ | 'done.invoke.vc-item.updatingPrivateKey:invocation[0]';
verifyCredential: 'done.invoke.vc-item.verifyingCredential:invocation[0]';
};
'missingImplementations': {
@@ -117,12 +165,15 @@ export interface Typegen0 {
services: never;
};
'eventsCausingActions': {
+ VcUpdated: 'STORE_RESPONSE';
clearOtp:
| ''
| 'CANCEL'
| 'DISMISS'
| 'REVOKE_VC'
| 'STORE_RESPONSE'
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.requestingBindingOtp:invocation[0]'
| 'done.invoke.vc-item.requestingBindingOtp:invocation[0]'
| 'done.invoke.vc-item.requestingOtp:invocation[0]'
| 'done.invoke.vc-item.updatingPrivateKey:invocation[0]'
@@ -135,75 +186,131 @@ export interface Typegen0 {
| 'CANCEL'
| 'DISMISS'
| 'STORE_RESPONSE'
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
| 'done.invoke.vc-item.updatingPrivateKey:invocation[0]'
| 'done.invoke.vc-item.verifyingCredential:invocation[0]'
| 'error.platform.vc-item.verifyingCredential:invocation[0]';
+ editVcKey: 'CREDENTIAL_DOWNLOADED';
incrementDownloadCounter: 'POLL';
- logDownloaded: 'CREDENTIAL_DOWNLOADED';
+ logDownloaded: 'STORE_RESPONSE';
logRevoked: 'STORE_RESPONSE';
+ logVCremoved: 'STORE_RESPONSE';
+ logWalletBindingFailure:
+ | 'error.platform.vc-item.addKeyPair:invocation[0]'
+ | 'error.platform.vc-item.addingWalletBindingId:invocation[0]'
+ | 'error.platform.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]'
+ | 'error.platform.vc-item.requestingBindingOtp:invocation[0]'
+ | 'error.platform.vc-item.updatingPrivateKey:invocation[0]';
+ logWalletBindingSuccess:
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
+ | 'done.invoke.vc-item.updatingPrivateKey:invocation[0]';
markVcValid: 'done.invoke.vc-item.verifyingCredential:invocation[0]';
+ removeVcItem: 'CONFIRM';
+ removeVcMetaDataFromStorage: 'STORE_ERROR';
+ removeVcMetaDataFromVcMachine: 'DISMISS';
+ removedVc: 'STORE_RESPONSE';
requestStoredContext: 'GET_VC_RESPONSE' | 'REFRESH';
- requestVcContext: 'xstate.init';
+ requestVcContext: 'DISMISS' | 'xstate.init';
revokeVID: 'done.invoke.vc-item.requestingRevoke:invocation[0]';
- setCredential:
- | 'CREDENTIAL_DOWNLOADED'
- | 'GET_VC_RESPONSE'
- | 'STORE_RESPONSE';
+ sendVcUpdated: 'STORE_RESPONSE';
+ setCredential: 'GET_VC_RESPONSE' | 'STORE_RESPONSE';
+ setDownloadInterval: 'done.invoke.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]';
setLock: 'done.invoke.vc-item.requestingLock:invocation[0]';
setMaxDownloadCount: 'done.invoke.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]';
setOtp: 'INPUT_OTP';
setOtpError:
| 'error.platform.vc-item.requestingLock:invocation[0]'
| 'error.platform.vc-item.requestingRevoke:invocation[0]';
- setPrivateKey: 'done.invoke.vc-item.addKeyPair:invocation[0]';
- setPublicKey: 'done.invoke.vc-item.addKeyPair:invocation[0]';
+ setPinCard: 'PIN_CARD';
+ setPrivateKey:
+ | 'done.invoke.vc-item.addKeyPair:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addKeyPair:invocation[0]';
+ setPublicKey:
+ | 'done.invoke.vc-item.addKeyPair:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addKeyPair:invocation[0]';
setRevoke: 'done.invoke.vc-item.requestingRevoke:invocation[0]';
+ setStoreVerifiableCredential: 'CREDENTIAL_DOWNLOADED';
setTag: 'SAVE_TAG';
+ setThumbprintForWalletBindingId:
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]';
setTransactionId:
| 'INPUT_OTP'
| 'REVOKE_VC'
| 'done.invoke.vc-item.requestingOtp:invocation[0]'
| 'error.platform.vc-item.requestingLock:invocation[0]'
| 'error.platform.vc-item.requestingRevoke:invocation[0]';
+ setVcKey: 'REMOVE';
+ setVerifiableCredential: 'STORE_RESPONSE';
setWalletBindingError:
| 'error.platform.vc-item.addKeyPair:invocation[0]'
| 'error.platform.vc-item.addingWalletBindingId:invocation[0]'
+ | 'error.platform.vc-item.kebabPopUp.addKeyPair:invocation[0]'
+ | 'error.platform.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]'
+ | 'error.platform.vc-item.kebabPopUp.requestingBindingOtp:invocation[0]'
+ | 'error.platform.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
| 'error.platform.vc-item.requestingBindingOtp:invocation[0]'
| 'error.platform.vc-item.updatingPrivateKey:invocation[0]';
setWalletBindingErrorEmpty:
| 'CANCEL'
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
| 'done.invoke.vc-item.updatingPrivateKey:invocation[0]';
- setWalletBindingId: 'done.invoke.vc-item.addingWalletBindingId:invocation[0]';
+ setWalletBindingId:
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]';
storeContext:
| 'CREDENTIAL_DOWNLOADED'
+ | 'PIN_CARD'
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
| 'done.invoke.vc-item.updatingPrivateKey:invocation[0]'
| 'done.invoke.vc-item.verifyingCredential:invocation[0]';
storeLock: 'done.invoke.vc-item.requestingLock:invocation[0]';
storeTag: 'SAVE_TAG';
- updatePrivateKey: 'done.invoke.vc-item.updatingPrivateKey:invocation[0]';
+ updatePrivateKey:
+ | 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
+ | 'done.invoke.vc-item.updatingPrivateKey:invocation[0]';
updateVc:
- | 'CREDENTIAL_DOWNLOADED'
| 'STORE_RESPONSE'
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.updatingPrivateKey:invocation[0]'
| 'done.invoke.vc-item.updatingPrivateKey:invocation[0]'
| 'done.invoke.vc-item.verifyingCredential:invocation[0]';
};
'eventsCausingDelays': {};
'eventsCausingGuards': {
hasCredential: 'GET_VC_RESPONSE' | 'STORE_RESPONSE';
+ isCustomSecureKeystore:
+ | 'done.invoke.vc-item.addKeyPair:invocation[0]'
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addKeyPair:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]';
isDownloadAllowed: 'POLL';
isVcValid: '';
};
'eventsCausingServices': {
- addWalletBindnigId: 'done.invoke.vc-item.addKeyPair:invocation[0]';
+ addWalletBindnigId:
+ | 'done.invoke.vc-item.addKeyPair:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addKeyPair:invocation[0]';
checkDownloadExpiryLimit: 'STORE_RESPONSE';
- checkStatus: 'done.invoke.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]';
+ checkStatus:
+ | 'done.invoke.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]'
+ | 'error.platform.vc-item.checkingServerData.verifyingDownloadLimitExpiry:invocation[0]';
downloadCredential: 'DOWNLOAD_READY';
generateKeyPair: 'INPUT_OTP';
requestBindingOtp: 'CONFIRM';
requestLock: 'INPUT_OTP';
requestOtp: 'LOCK_VC';
requestRevoke: 'INPUT_OTP';
- updatePrivateKey: 'done.invoke.vc-item.addingWalletBindingId:invocation[0]';
+ updatePrivateKey:
+ | 'done.invoke.vc-item.addingWalletBindingId:invocation[0]'
+ | 'done.invoke.vc-item.kebabPopUp.addingWalletBindingId:invocation[0]';
verifyCredential: '' | 'VERIFY';
};
'matchesStates':
@@ -215,6 +322,9 @@ export interface Typegen0 {
| 'checkingServerData'
| 'checkingServerData.checkingStatus'
| 'checkingServerData.downloadingCredential'
+ | 'checkingServerData.savingFailed'
+ | 'checkingServerData.savingFailed.idle'
+ | 'checkingServerData.savingFailed.viewingVc'
| 'checkingServerData.verifyingDownloadLimitExpiry'
| 'checkingStore'
| 'checkingVc'
@@ -224,8 +334,21 @@ export interface Typegen0 {
| 'invalid'
| 'invalid.backend'
| 'invalid.otp'
+ | 'kebabPopUp'
+ | 'kebabPopUp.acceptingBindingOtp'
+ | 'kebabPopUp.addKeyPair'
+ | 'kebabPopUp.addingWalletBindingId'
+ | 'kebabPopUp.idle'
+ | 'kebabPopUp.removeWallet'
+ | 'kebabPopUp.removingVc'
+ | 'kebabPopUp.requestingBindingOtp'
+ | 'kebabPopUp.showActivities'
+ | 'kebabPopUp.showBindingWarning'
+ | 'kebabPopUp.showingWalletBindingError'
+ | 'kebabPopUp.updatingPrivateKey'
| 'lockingVc'
| 'loggingRevoke'
+ | 'pinCard'
| 'requestingBindingOtp'
| 'requestingLock'
| 'requestingOtp'
@@ -240,8 +363,22 @@ export interface Typegen0 {
checkingServerData?:
| 'checkingStatus'
| 'downloadingCredential'
- | 'verifyingDownloadLimitExpiry';
+ | 'savingFailed'
+ | 'verifyingDownloadLimitExpiry'
+ | { savingFailed?: 'idle' | 'viewingVc' };
invalid?: 'backend' | 'otp';
+ kebabPopUp?:
+ | 'acceptingBindingOtp'
+ | 'addKeyPair'
+ | 'addingWalletBindingId'
+ | 'idle'
+ | 'removeWallet'
+ | 'removingVc'
+ | 'requestingBindingOtp'
+ | 'showActivities'
+ | 'showBindingWarning'
+ | 'showingWalletBindingError'
+ | 'updatingPrivateKey';
};
'tags': never;
}
diff --git a/package-lock.json b/package-lock.json
index 03efecfb..6353948e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,16 +7,18 @@
"": {
"name": "mosip-resident-app",
"version": "1.0.0",
+ "hasInstallScript": true,
"dependencies": {
"@digitalbazaar/ed25519-signature-2018": "digitalbazaar/ed25519-signature-2018",
"@digitalbazaar/ed25519-verification-key-2018": "digitalbazaar/ed25519-verification-key-2018",
"@digitalbazaar/rsa-signature-2018": "digitalbazaar/rsa-signature-2018#initial",
"@digitalbazaar/rsa-verification-key-2018": "digitalbazaar/rsa-verification-key-2018#initial",
"@digitalcredentials/vc": "^1.1.2",
+ "@expo-google-fonts/inter": "^0.2.3",
"@expo-google-fonts/poppins": "^0.2.0",
"@expo/metro-config": "^0.3.12",
"@idpass/smartshare-react-native": "0.2.3-beta.2",
- "@react-native-async-storage/async-storage": "~1.15.0",
+ "@react-native-clipboard/clipboard": "^1.11.2",
"@react-native-community/netinfo": "7.1.3",
"@react-native-picker/picker": "2.2.1",
"@react-navigation/bottom-tabs": "^6.0.7",
@@ -39,21 +41,29 @@
"expo-status-bar": "~1.2.0",
"expo-updates": "~0.11.6",
"i18next": "^21.6.16",
- "mosip-inji-face-sdk": "^0.1.7",
+ "iso-639-3": "^3.0.1",
+ "mosip-inji-face-sdk": "^0.1.12",
"node-forge": "^1.3.1",
+ "patch-package": "^6.5.1",
+ "postinstall-postinstall": "^2.1.0",
"react": "17.0.1",
"react-i18next": "^11.16.6",
"react-native": "0.64.4",
+ "react-native-animated-pagination-dot": "^0.4.0",
"react-native-app-intro-slider": "^4.0.4",
+ "react-native-argon2": "^2.0.1",
"react-native-biometrics-changed": "^1.1.8",
"react-native-bluetooth-state-manager": "^1.3.2",
+ "react-native-cli": "^2.0.1",
"react-native-device-info": "^8.4.8",
"react-native-dotenv": "^3.3.1",
- "react-native-elements": "^3.4.2",
+ "react-native-elements": "3.4.2",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.1.0",
"react-native-keychain": "^8.0.0",
- "react-native-location-enabler": "^4.1.0",
+ "react-native-linear-gradient": "^2.6.2",
+ "react-native-location": "^2.5.0",
+ "react-native-mmkv-storage": "0.8.0",
"react-native-permissions": "^3.6.0",
"react-native-popable": "^0.4.3",
"react-native-qrcode-svg": "^6.1.1",
@@ -62,12 +72,14 @@
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "~3.10.1",
"react-native-secure-key-store": "^2.0.10",
+ "react-native-secure-keystore": "github:mosip/secure-keystore#v0.1.1",
"react-native-securerandom": "^1.0.0",
"react-native-simple-markdown": "^1.1.0",
"react-native-svg": "12.1.1",
"react-native-swipe-gestures": "^1.0.5",
- "react-native-uuid": "^2.0.1",
+ "react-native-tuvali": "github:mosip/tuvali#v0.4.4",
"react-native-vector-icons": "^8.1.0",
+ "short-unique-id": "^4.4.4",
"xstate": "^4.35.0"
},
"devDependencies": {
@@ -2140,6 +2152,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/@expo-google-fonts/inter": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@expo-google-fonts/inter/-/inter-0.2.3.tgz",
+ "integrity": "sha512-iHK9FI+dnE45X5c2Z5hSFwNH4zUWethizpbv3XUn0FIGw5jwvzriENz0a6wCdkI4/d+1QkurnHo5XHti7TbNJA=="
+ },
"node_modules/@expo-google-fonts/poppins": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@expo-google-fonts/poppins/-/poppins-0.2.2.tgz",
@@ -4221,15 +4238,13 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
- "node_modules/@react-native-async-storage/async-storage": {
- "version": "1.15.17",
- "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.15.17.tgz",
- "integrity": "sha512-NQCFs47aFEch9kya/bqwdpvSdZaVRtzU7YB02L8VrmLSLpKgQH/1VwzFUBPcc1/JI1s3GU4yOLVrEbwxq+Fqcw==",
- "dependencies": {
- "merge-options": "^3.0.4"
- },
+ "node_modules/@react-native-clipboard/clipboard": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/@react-native-clipboard/clipboard/-/clipboard-1.11.2.tgz",
+ "integrity": "sha512-bHyZVW62TuleiZsXNHS1Pv16fWc0fh8O9WvBzl4h2fykqZRW9a+Pv/RGTH56E3X2PqzHP38K5go8zmCZUoIsoQ==",
"peerDependencies": {
- "react-native": "^0.0.0-0 || 0.60 - 0.67 || 1000.0.0"
+ "react": ">=16.0",
+ "react-native": ">=0.57.0"
}
},
"node_modules/@react-native-community/cli": {
@@ -5471,6 +5486,11 @@
"@types/istanbul-lib-report": "*"
}
},
+ "node_modules/@types/js-cookie": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
+ "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA=="
+ },
"node_modules/@types/json-buffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
@@ -6053,6 +6073,11 @@
"node": ">=10.0.0"
}
},
+ "node_modules/@xobotyi/scrollbar-width": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
+ "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
+ },
"node_modules/@xstate/react": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@xstate/react/-/react-3.0.1.tgz",
@@ -6087,6 +6112,11 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
+ "node_modules/@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="
+ },
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -8658,6 +8688,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"node_modules/copy-webpack-plugin": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.0.4.tgz",
@@ -9045,6 +9083,14 @@
"node": ">4"
}
},
+ "node_modules/css-in-js-utils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz",
+ "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==",
+ "dependencies": {
+ "hyphenate-style-name": "^1.0.3"
+ }
+ },
"node_modules/css-loader": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz",
@@ -9301,6 +9347,14 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
"integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
},
+ "node_modules/cycle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
+ "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/cyclist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
@@ -9419,7 +9473,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
"integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dev": true,
"dependencies": {
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.1",
@@ -12800,6 +12853,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/eyes": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
+ "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
+ "engines": {
+ "node": "> 0.1.90"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -12843,11 +12904,26 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
+ "node_modules/fast-loops": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.3.tgz",
+ "integrity": "sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g=="
+ },
+ "node_modules/fast-shallow-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz",
+ "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw=="
+ },
"node_modules/fast-text-encoding": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
"integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig=="
},
+ "node_modules/fastest-stable-stringify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz",
+ "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="
+ },
"node_modules/fastq": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
@@ -13488,7 +13564,6 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.2.tgz",
"integrity": "sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA==",
- "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -13783,6 +13858,25 @@
"node": ">= 0.4.0"
}
},
+ "node_modules/has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/has-bigints": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
@@ -13826,7 +13920,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
"dependencies": {
"has-symbols": "^1.0.2"
},
@@ -14523,6 +14616,19 @@
"url": "https://github.com/sponsors/typicode"
}
},
+ "node_modules/hyphenate-style-name": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
+ },
+ "node_modules/i": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
+ "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
"node_modules/i18next": {
"version": "21.6.16",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.16.tgz",
@@ -14714,6 +14820,15 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
+ "node_modules/inline-style-prefixer": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz",
+ "integrity": "sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==",
+ "dependencies": {
+ "css-in-js-utils": "^3.1.0",
+ "fast-loops": "^1.1.3"
+ }
+ },
"node_modules/internal-ip": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
@@ -14804,7 +14919,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
- "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -14930,7 +15044,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
"dependencies": {
"has-tostringtag": "^1.0.0"
},
@@ -14966,7 +15079,6 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
- "dev": true,
"bin": {
"is-docker": "cli.js"
},
@@ -15138,14 +15250,6 @@
"node": ">=8"
}
},
- "node_modules/is-plain-obj": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
- "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -15352,7 +15456,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -15469,7 +15572,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
- "dev": true,
"dependencies": {
"is-docker": "^2.0.0"
},
@@ -15487,6 +15589,15 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
+ "node_modules/iso-639-3": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/iso-639-3/-/iso-639-3-3.0.1.tgz",
+ "integrity": "sha512-SdljCYXOexv/JmbQ0tvigHN43yECoscVpe2y2hlEqy/CStXQlroPhZLj7zKLRiGqLJfw8k7B973UAMDoQczVgQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
@@ -15551,6 +15662,11 @@
"react-native": "*"
}
},
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
+ },
"node_modules/iterall": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz",
@@ -15836,6 +15952,11 @@
"integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==",
"dev": true
},
+ "node_modules/js-cookie": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
+ "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -16206,6 +16327,14 @@
"graceful-fs": "^4.1.9"
}
},
+ "node_modules/klaw-sync": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+ "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+ "dependencies": {
+ "graceful-fs": "^4.1.11"
+ }
+ },
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -16919,17 +17048,6 @@
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
"dev": true
},
- "node_modules/merge-options": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
- "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
- "dependencies": {
- "is-plain-obj": "^2.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -17730,9 +17848,9 @@
}
},
"node_modules/mosip-inji-face-sdk": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/mosip-inji-face-sdk/-/mosip-inji-face-sdk-0.1.7.tgz",
- "integrity": "sha512-aVfYUs63M805xsk2+82nT4VHn5Ql7lb6j9qgTP/GKw/+qzd56Svu9U9GzNXbBz1wtaU5RGlV9gu0I0YpO2tXQQ==",
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/mosip-inji-face-sdk/-/mosip-inji-face-sdk-0.1.12.tgz",
+ "integrity": "sha512-lnoaa2lL0pS9u/9fwH4Q9OU2U56oqjXf2z4JjGxX80DQOqJGWvj49PfvPMYGFEfVucqIJyQBZUfvfpqfYO0+vw==",
"peerDependencies": {
"react": "*",
"react-native": "*",
@@ -17826,6 +17944,11 @@
"integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
"dev": true
},
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ },
"node_modules/mv": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
@@ -17897,6 +18020,25 @@
"dev": true,
"optional": true
},
+ "node_modules/nano-css": {
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.3.5.tgz",
+ "integrity": "sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==",
+ "dependencies": {
+ "css-tree": "^1.1.2",
+ "csstype": "^3.0.6",
+ "fastest-stable-stringify": "^2.0.2",
+ "inline-style-prefixer": "^6.0.0",
+ "rtl-css-js": "^1.14.0",
+ "sourcemap-codec": "^1.4.8",
+ "stacktrace-js": "^2.0.2",
+ "stylis": "^4.0.6"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@@ -18322,7 +18464,6 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
- "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@@ -19202,6 +19343,212 @@
"which": "bin/which"
}
},
+ "node_modules/patch-package": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.1.tgz",
+ "integrity": "sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==",
+ "dependencies": {
+ "@yarnpkg/lockfile": "^1.1.0",
+ "chalk": "^4.1.2",
+ "cross-spawn": "^6.0.5",
+ "find-yarn-workspace-root": "^2.0.0",
+ "fs-extra": "^9.0.0",
+ "is-ci": "^2.0.0",
+ "klaw-sync": "^6.0.0",
+ "minimist": "^1.2.6",
+ "open": "^7.4.2",
+ "rimraf": "^2.6.3",
+ "semver": "^5.6.0",
+ "slash": "^2.0.0",
+ "tmp": "^0.0.33",
+ "yaml": "^1.10.2"
+ },
+ "bin": {
+ "patch-package": "index.js"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">5"
+ }
+ },
+ "node_modules/patch-package/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/patch-package/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/patch-package/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/patch-package/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/patch-package/node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/patch-package/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/patch-package/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/patch-package/node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/patch-package/node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/patch-package/node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/patch-package/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/patch-package/node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/patch-package/node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/patch-package/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/patch-package/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/patch-package/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
@@ -19469,6 +19816,14 @@
"node": ">=6"
}
},
+ "node_modules/pkginfo": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz",
+ "integrity": "sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/plist": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
@@ -20182,6 +20537,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/postinstall-postinstall": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz",
+ "integrity": "sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==",
+ "hasInstallScript": true
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -20343,6 +20704,21 @@
"integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
"dev": true
},
+ "node_modules/prompt": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz",
+ "integrity": "sha512-jDK5yEbAakJmNm+260gZG1+PuzX3jT5Jy0VZAUGrrW9RQ1JEWEDEVNnhO70mL3+U5r6bSJo02xsE34wOS/LnrA==",
+ "dependencies": {
+ "pkginfo": "0.x.x",
+ "read": "1.0.x",
+ "revalidator": "0.1.x",
+ "utile": "0.2.x",
+ "winston": "0.8.x"
+ },
+ "engines": {
+ "node": ">= 0.6.6"
+ }
+ },
"node_modules/prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -21056,11 +21432,28 @@
"react": "17.0.1"
}
},
+ "node_modules/react-native-animated-pagination-dot": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/react-native-animated-pagination-dot/-/react-native-animated-pagination-dot-0.4.0.tgz",
+ "integrity": "sha512-MiIPB6qe8lc6a+nhzvQHOi5x/bZlZ8hBH4HWiorPps3gTJZgxfX3abuYvVjN94egA8Z3HlE9pptz8OQfdL5IzQ==",
+ "dependencies": {
+ "react-use": "^17.3.1"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/react-native-app-intro-slider": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/react-native-app-intro-slider/-/react-native-app-intro-slider-4.0.4.tgz",
"integrity": "sha512-Zkjaol6X3BbZkHUpVDj2LjdidpS6rCgKi0fx80xgGKa0pHxBRd4swWTv2bHnnvu5k1/HXwYk0mY2TbK+2jHl5w=="
},
+ "node_modules/react-native-argon2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/react-native-argon2/-/react-native-argon2-2.0.1.tgz",
+ "integrity": "sha512-/iOi0S+VVgS1gQGtQgL4ZxUVS4gz6Lav3bgIbtNmr9KbOunnBYzP6/yBe/XxkbpXvasHDwdQnuppOH/nuOBn7w=="
+ },
"node_modules/react-native-biometrics-changed": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/react-native-biometrics-changed/-/react-native-biometrics-changed-1.1.8.tgz",
@@ -21080,6 +21473,89 @@
"react-native": ">= 0.44"
}
},
+ "node_modules/react-native-cli": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/react-native-cli/-/react-native-cli-2.0.1.tgz",
+ "integrity": "sha512-QgkB1urUhGe9q1vcqQLIfNdCd/Qf3MdNQe19QO6lVjhIVKljlVMKtaK8RaZ8PCNB/cdXlO/G3tKUGk+ghMXE6w==",
+ "dependencies": {
+ "chalk": "^1.1.1",
+ "minimist": "^1.2.0",
+ "prompt": "^0.2.14",
+ "semver": "^5.0.3"
+ },
+ "bin": {
+ "react-native": "index.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/react-native-cli/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-native-cli/node_modules/ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-native-cli/node_modules/chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
+ "dependencies": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-native-cli/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/react-native-cli/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/react-native-cli/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-native-cli/node_modules/supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/react-native-codegen": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.6.tgz",
@@ -21169,15 +21645,35 @@
"resolved": "https://registry.npmjs.org/react-native-keychain/-/react-native-keychain-8.0.0.tgz",
"integrity": "sha512-c7Cs+YQN26UaQsRG1dmlXL7VL2ctnXwH/dl0IOMEQ7ZaL2NdN313YSAI8ZEZZjrVhNmPsyWEuvTFqWrdpItqQg=="
},
- "node_modules/react-native-location-enabler": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/react-native-location-enabler/-/react-native-location-enabler-4.1.1.tgz",
- "integrity": "sha512-1gXJ+NzH5JKpaR23t1P8afEB7TKKfBkdXk2avhNUuTBlhBrqa2HrL4uDwYHoc4ZcwchsVC2P0Q7gP9L5Ot+KJw==",
+ "node_modules/react-native-linear-gradient": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.6.2.tgz",
+ "integrity": "sha512-Z8Xxvupsex+9BBFoSYS87bilNPWcRfRsGC0cpJk72Nxb5p2nEkGSBv73xZbEHnW2mUFvP+huYxrVvjZkr/gRjQ==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
+ "node_modules/react-native-location": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/react-native-location/-/react-native-location-2.5.0.tgz",
+ "integrity": "sha512-myT54tZuFmN6d5RruMVfoa8eY+voJWkSd73xUVhjzJDnQr5uu5MFoH7hMg3trHF1CAkaY/2gIneOspUdGxv59Q==",
+ "peerDependencies": {
+ "react": "*",
+ "react-native": ">= 0.46"
+ }
+ },
+ "node_modules/react-native-mmkv-storage": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/react-native-mmkv-storage/-/react-native-mmkv-storage-0.8.0.tgz",
+ "integrity": "sha512-L782Le5IuDYlDLGXF/qimbnzvkbYsSmV5PiDleo1DSS8Kr8Q31UK8YWtUICrDGQ9Fm7Xx4PxP9ffe2XzGeWaHQ==",
+ "bin": {
+ "mmkv-link": "autolink/postlink/run.js"
+ },
+ "peerDependencies": {
+ "react-native": "*"
+ }
+ },
"node_modules/react-native-permissions": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-3.6.1.tgz",
@@ -21269,6 +21765,15 @@
"resolved": "https://registry.npmjs.org/react-native-secure-key-store/-/react-native-secure-key-store-2.0.10.tgz",
"integrity": "sha512-K7aVlIGxyklnjhCidVexVgZF3LsgUD9GIxMy2NB/xkQsS9E2SJWkD/fJ56e25L2I6a9Mp1zuJrKnCtfBs1CvAw=="
},
+ "node_modules/react-native-secure-keystore": {
+ "version": "0.1.1",
+ "resolved": "git+ssh://git@github.com/mosip/secure-keystore.git#0d3a3d06e2ff49be698eb98fee4c5a5091be218f",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/react-native-securerandom": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/react-native-securerandom/-/react-native-securerandom-1.0.1.tgz",
@@ -21318,13 +21823,13 @@
"resolved": "https://registry.npmjs.org/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.5.tgz",
"integrity": "sha512-Ns7Bn9H/Tyw278+5SQx9oAblDZ7JixyzeOczcBK8dipQk2pD7Djkcfnf1nB/8RErAmMLL9iXgW0QHqiII8AhKw=="
},
- "node_modules/react-native-uuid": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/react-native-uuid/-/react-native-uuid-2.0.1.tgz",
- "integrity": "sha512-cptnoIbL53GTCrWlb/+jrDC6tvb7ypIyzbXNJcpR3Vab0mkeaaVd5qnB3f0whXYzS+SMoSQLcUUB0gEWqkPC0g==",
- "engines": {
- "node": ">=10.0.0",
- "npm": ">=6.0.0"
+ "node_modules/react-native-tuvali": {
+ "version": "0.4.4",
+ "resolved": "git+ssh://git@github.com/mosip/tuvali.git#a71e8bc391545a2d2a1a237670ee353fe96b7c0c",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
}
},
"node_modules/react-native-vector-icons": {
@@ -21418,6 +21923,56 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-universal-interface": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz",
+ "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==",
+ "peerDependencies": {
+ "react": "*",
+ "tslib": "*"
+ }
+ },
+ "node_modules/react-use": {
+ "version": "17.4.0",
+ "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.4.0.tgz",
+ "integrity": "sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==",
+ "dependencies": {
+ "@types/js-cookie": "^2.2.6",
+ "@xobotyi/scrollbar-width": "^1.9.5",
+ "copy-to-clipboard": "^3.3.1",
+ "fast-deep-equal": "^3.1.3",
+ "fast-shallow-equal": "^1.0.0",
+ "js-cookie": "^2.2.1",
+ "nano-css": "^5.3.1",
+ "react-universal-interface": "^0.6.2",
+ "resize-observer-polyfill": "^1.5.1",
+ "screenfull": "^5.1.0",
+ "set-harmonic-interval": "^1.0.1",
+ "throttle-debounce": "^3.0.1",
+ "ts-easing": "^0.2.0",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-use/node_modules/tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
+ },
+ "node_modules/read": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
+ "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
+ "dependencies": {
+ "mute-stream": "~0.0.4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/read-chunk": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz",
@@ -21579,7 +22134,6 @@
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
- "dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
@@ -21913,6 +22467,11 @@
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz",
"integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ=="
},
+ "node_modules/resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ },
"node_modules/resolve": {
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
@@ -22018,6 +22577,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/revalidator": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
+ "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/rfdc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
@@ -22098,6 +22665,14 @@
"node": "6.* || >= 7.*"
}
},
+ "node_modules/rtl-css-js": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz",
+ "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==",
+ "dependencies": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
"node_modules/rtl-detect": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz",
@@ -22492,6 +23067,17 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/screenfull": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz",
+ "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==",
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/security-context": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/security-context/-/security-context-4.0.0.tgz",
@@ -22810,6 +23396,14 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
+ "node_modules/set-harmonic-interval": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz",
+ "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==",
+ "engines": {
+ "node": ">=6.9"
+ }
+ },
"node_modules/set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@@ -22945,6 +23539,15 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/short-unique-id": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
+ "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw==",
+ "bin": {
+ "short-unique-id": "bin/short-unique-id",
+ "suid": "bin/short-unique-id"
+ }
+ },
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -23330,6 +23933,12 @@
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
"deprecated": "See https://github.com/lydell/source-map-url#deprecated"
},
+ "node_modules/sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "deprecated": "Please use @jridgewell/sourcemap-codec instead"
+ },
"node_modules/spdy": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
@@ -23429,10 +24038,53 @@
"deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility",
"dev": true
},
+ "node_modules/stack-generator": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
+ "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/stackframe": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz",
- "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg=="
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
+ },
+ "node_modules/stacktrace-gps": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
+ "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
+ "dependencies": {
+ "source-map": "0.5.6",
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stacktrace-gps/node_modules/source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stacktrace-js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
+ "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
+ "dependencies": {
+ "error-stack-parser": "^2.0.6",
+ "stack-generator": "^2.0.5",
+ "stacktrace-gps": "^3.0.4"
+ }
},
"node_modules/stacktrace-parser": {
"version": "0.1.10",
@@ -23830,6 +24482,11 @@
"node": ">=8"
}
},
+ "node_modules/stylis": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz",
+ "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="
+ },
"node_modules/subscriptions-transport-ws": {
"version": "0.9.8",
"resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.8.tgz",
@@ -24403,6 +25060,14 @@
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
},
+ "node_modules/throttle-debounce": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
+ "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -24446,7 +25111,6 @@
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
- "dev": true,
"dependencies": {
"os-tmpdir": "~1.0.2"
},
@@ -24529,6 +25193,11 @@
"node": ">=8.0"
}
},
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ },
"node_modules/toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
@@ -24558,6 +25227,11 @@
"tree-kill": "cli.js"
}
},
+ "node_modules/ts-easing": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz",
+ "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ=="
+ },
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
@@ -24589,8 +25263,7 @@
"node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "dev": true
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/tsutils": {
"version": "3.21.0",
@@ -25138,6 +25811,76 @@
"integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
"dev": true
},
+ "node_modules/utile": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz",
+ "integrity": "sha512-ltfvuCJNa/JFOhKBBiQ9qDyyFwLstoMMO1ru0Yg/Mcl8dp1Z3IBaL7n+5dHpyma+d3lCogkgBQnWKtGxzNyqhg==",
+ "dependencies": {
+ "async": "~0.2.9",
+ "deep-equal": "*",
+ "i": "0.3.x",
+ "mkdirp": "0.x.x",
+ "ncp": "0.4.x",
+ "rimraf": "2.x.x"
+ },
+ "engines": {
+ "node": ">= 0.6.4"
+ }
+ },
+ "node_modules/utile/node_modules/async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
+ },
+ "node_modules/utile/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/utile/node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/utile/node_modules/ncp": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz",
+ "integrity": "sha512-PfGU8jYWdRl4FqJfCy0IzbkGyFHntfWygZg46nFk/dJD/XRrk2cj0SsKSX9n5u5gE0E0YfEpKWrEkfjnlZSTXA==",
+ "bin": {
+ "ncp": "bin/ncp"
+ }
+ },
+ "node_modules/utile/node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@@ -25251,6 +25994,274 @@
"node": "<8.10.0"
}
},
+ "node_modules/watchpack/chokidar2/node_modules/chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ },
+ "optionalDependencies": {
+ "fsevents": "^1.2.7"
+ }
+ },
+ "node_modules/watchpack/node_modules/anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "node_modules/watchpack/node_modules/anymatch/node_modules/normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "remove-trailing-separator": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/braces/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/fill-range/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ },
+ "engines": {
+ "node": ">= 4.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/glob-parent/node_modules/is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "is-extglob": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "binary-extensions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/is-number/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/watchpack/node_modules/readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/watchpack/node_modules/to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/wbuf": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
@@ -26876,6 +27887,44 @@
"node": ">=8"
}
},
+ "node_modules/winston": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz",
+ "integrity": "sha512-fPoamsHq8leJ62D1M9V/f15mjQ1UHe4+7j1wpAT3fqgA5JqhJkk4aIfPEjfMTI9x6ZTjaLOpMAjluLtmgO5b6g==",
+ "dependencies": {
+ "async": "0.2.x",
+ "colors": "0.6.x",
+ "cycle": "1.0.x",
+ "eyes": "0.1.x",
+ "isstream": "0.1.x",
+ "pkginfo": "0.3.x",
+ "stack-trace": "0.0.x"
+ },
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/winston/node_modules/async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
+ },
+ "node_modules/winston/node_modules/colors": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
+ "integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/winston/node_modules/pkginfo": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz",
+ "integrity": "sha512-yO5feByMzAp96LtP58wvPKSbaKAi/1C4kV9XpTctr6EepnP6F33RBNOiVrdz9BrPA98U2BMFsTNHo44TWcbQ2A==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/with-open-file": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz",
@@ -27453,7 +28502,6 @@
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -28975,6 +30023,11 @@
}
}
},
+ "@expo-google-fonts/inter": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@expo-google-fonts/inter/-/inter-0.2.3.tgz",
+ "integrity": "sha512-iHK9FI+dnE45X5c2Z5hSFwNH4zUWethizpbv3XUn0FIGw5jwvzriENz0a6wCdkI4/d+1QkurnHo5XHti7TbNJA=="
+ },
"@expo-google-fonts/poppins": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@expo-google-fonts/poppins/-/poppins-0.2.2.tgz",
@@ -30641,13 +31694,11 @@
}
}
},
- "@react-native-async-storage/async-storage": {
- "version": "1.15.17",
- "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.15.17.tgz",
- "integrity": "sha512-NQCFs47aFEch9kya/bqwdpvSdZaVRtzU7YB02L8VrmLSLpKgQH/1VwzFUBPcc1/JI1s3GU4yOLVrEbwxq+Fqcw==",
- "requires": {
- "merge-options": "^3.0.4"
- }
+ "@react-native-clipboard/clipboard": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/@react-native-clipboard/clipboard/-/clipboard-1.11.2.tgz",
+ "integrity": "sha512-bHyZVW62TuleiZsXNHS1Pv16fWc0fh8O9WvBzl4h2fykqZRW9a+Pv/RGTH56E3X2PqzHP38K5go8zmCZUoIsoQ==",
+ "requires": {}
},
"@react-native-community/cli": {
"version": "5.0.1",
@@ -31628,6 +32679,11 @@
"@types/istanbul-lib-report": "*"
}
},
+ "@types/js-cookie": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
+ "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA=="
+ },
"@types/json-buffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
@@ -32107,6 +33163,11 @@
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.8.tgz",
"integrity": "sha512-PrJx38EfpitFhwmILRl37jAdBlsww6AZ6rRVK4QS7T7RHLhX7mSs647sTmgr9GIxe3qjXdesmomEgbgaokrVFg=="
},
+ "@xobotyi/scrollbar-width": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
+ "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
+ },
"@xstate/react": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@xstate/react/-/react-3.0.1.tgz",
@@ -32128,6 +33189,11 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
+ "@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="
+ },
"abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -33533,6 +34599,29 @@
"version": "file:node_modules/watchpack/chokidar2",
"requires": {
"chokidar": "^2.1.8"
+ },
+ "dependencies": {
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ }
}
},
"chownr": {
@@ -34197,6 +35286,14 @@
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
},
+ "copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "requires": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"copy-webpack-plugin": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.0.4.tgz",
@@ -34500,6 +35597,14 @@
"timsort": "^0.3.0"
}
},
+ "css-in-js-utils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz",
+ "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==",
+ "requires": {
+ "hyphenate-style-name": "^1.0.3"
+ }
+ },
"css-loader": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz",
@@ -34695,6 +35800,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz",
"integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw=="
},
+ "cycle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
+ "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA=="
+ },
"cyclist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
@@ -34776,7 +35886,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
"integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dev": true,
"requires": {
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.1",
@@ -37489,6 +38598,11 @@
}
}
},
+ "eyes": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
+ "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ=="
+ },
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -37528,11 +38642,26 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
+ "fast-loops": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.3.tgz",
+ "integrity": "sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g=="
+ },
+ "fast-shallow-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz",
+ "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw=="
+ },
"fast-text-encoding": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
"integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig=="
},
+ "fastest-stable-stringify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz",
+ "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="
+ },
"fastq": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
@@ -38033,8 +39162,7 @@
"functions-have-names": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.2.tgz",
- "integrity": "sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA==",
- "dev": true
+ "integrity": "sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA=="
},
"gensync": {
"version": "1.0.0-beta.2",
@@ -38254,6 +39382,21 @@
"function-bind": "^1.1.1"
}
},
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
+ }
+ }
+ },
"has-bigints": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
@@ -38282,7 +39425,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
"requires": {
"has-symbols": "^1.0.2"
}
@@ -38858,6 +40000,16 @@
"integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==",
"dev": true
},
+ "hyphenate-style-name": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
+ },
+ "i": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
+ "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q=="
+ },
"i18next": {
"version": "21.6.16",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.16.tgz",
@@ -38983,6 +40135,15 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
+ "inline-style-prefixer": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz",
+ "integrity": "sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==",
+ "requires": {
+ "css-in-js-utils": "^3.1.0",
+ "fast-loops": "^1.1.3"
+ }
+ },
"internal-ip": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
@@ -39052,7 +40213,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -39145,7 +40305,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
"requires": {
"has-tostringtag": "^1.0.0"
}
@@ -39168,8 +40327,7 @@
"is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
- "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
- "dev": true
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="
},
"is-extendable": {
"version": "1.0.1",
@@ -39282,11 +40440,6 @@
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
"dev": true
},
- "is-plain-obj": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
- "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="
- },
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -39457,7 +40610,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
@@ -39535,7 +40687,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
- "dev": true,
"requires": {
"is-docker": "^2.0.0"
}
@@ -39550,6 +40701,11 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
+ "iso-639-3": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/iso-639-3/-/iso-639-3-3.0.1.tgz",
+ "integrity": "sha512-SdljCYXOexv/JmbQ0tvigHN43yECoscVpe2y2hlEqy/CStXQlroPhZLj7zKLRiGqLJfw8k7B973UAMDoQczVgQ=="
+ },
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
@@ -39607,6 +40763,11 @@
}
}
},
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
+ },
"iterall": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz",
@@ -39822,6 +40983,11 @@
"integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==",
"dev": true
},
+ "js-cookie": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
+ "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -40130,6 +41296,14 @@
"graceful-fs": "^4.1.9"
}
},
+ "klaw-sync": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+ "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+ "requires": {
+ "graceful-fs": "^4.1.11"
+ }
+ },
"kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -40674,14 +41848,6 @@
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
"dev": true
},
- "merge-options": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
- "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
- "requires": {
- "is-plain-obj": "^2.1.0"
- }
- },
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -41350,9 +42516,9 @@
"dev": true
},
"mosip-inji-face-sdk": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/mosip-inji-face-sdk/-/mosip-inji-face-sdk-0.1.7.tgz",
- "integrity": "sha512-aVfYUs63M805xsk2+82nT4VHn5Ql7lb6j9qgTP/GKw/+qzd56Svu9U9GzNXbBz1wtaU5RGlV9gu0I0YpO2tXQQ==",
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/mosip-inji-face-sdk/-/mosip-inji-face-sdk-0.1.12.tgz",
+ "integrity": "sha512-lnoaa2lL0pS9u/9fwH4Q9OU2U56oqjXf2z4JjGxX80DQOqJGWvj49PfvPMYGFEfVucqIJyQBZUfvfpqfYO0+vw==",
"requires": {}
},
"move-concurrently": {
@@ -41429,6 +42595,11 @@
"integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
"dev": true
},
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ },
"mv": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
@@ -41490,6 +42661,21 @@
"dev": true,
"optional": true
},
+ "nano-css": {
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.3.5.tgz",
+ "integrity": "sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==",
+ "requires": {
+ "css-tree": "^1.1.2",
+ "csstype": "^3.0.6",
+ "fastest-stable-stringify": "^2.0.2",
+ "inline-style-prefixer": "^6.0.0",
+ "rtl-css-js": "^1.14.0",
+ "sourcemap-codec": "^1.4.8",
+ "stacktrace-js": "^2.0.2",
+ "stylis": "^4.0.6"
+ }
+ },
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@@ -41832,7 +43018,6 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@@ -42511,6 +43696,150 @@
}
}
},
+ "patch-package": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.1.tgz",
+ "integrity": "sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==",
+ "requires": {
+ "@yarnpkg/lockfile": "^1.1.0",
+ "chalk": "^4.1.2",
+ "cross-spawn": "^6.0.5",
+ "find-yarn-workspace-root": "^2.0.0",
+ "fs-extra": "^9.0.0",
+ "is-ci": "^2.0.0",
+ "klaw-sync": "^6.0.0",
+ "minimist": "^1.2.6",
+ "open": "^7.4.2",
+ "rimraf": "^2.6.3",
+ "semver": "^5.6.0",
+ "slash": "^2.0.0",
+ "tmp": "^0.0.33",
+ "yaml": "^1.10.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "requires": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ }
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A=="
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
"path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
@@ -42707,6 +44036,11 @@
}
}
},
+ "pkginfo": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz",
+ "integrity": "sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ=="
+ },
"plist": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
@@ -43331,6 +44665,11 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
+ "postinstall-postinstall": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz",
+ "integrity": "sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ=="
+ },
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -43454,6 +44793,18 @@
"integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
"dev": true
},
+ "prompt": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz",
+ "integrity": "sha512-jDK5yEbAakJmNm+260gZG1+PuzX3jT5Jy0VZAUGrrW9RQ1JEWEDEVNnhO70mL3+U5r6bSJo02xsE34wOS/LnrA==",
+ "requires": {
+ "pkginfo": "0.x.x",
+ "read": "1.0.x",
+ "revalidator": "0.1.x",
+ "utile": "0.2.x",
+ "winston": "0.8.x"
+ }
+ },
"prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -44026,11 +45377,24 @@
}
}
},
+ "react-native-animated-pagination-dot": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/react-native-animated-pagination-dot/-/react-native-animated-pagination-dot-0.4.0.tgz",
+ "integrity": "sha512-MiIPB6qe8lc6a+nhzvQHOi5x/bZlZ8hBH4HWiorPps3gTJZgxfX3abuYvVjN94egA8Z3HlE9pptz8OQfdL5IzQ==",
+ "requires": {
+ "react-use": "^17.3.1"
+ }
+ },
"react-native-app-intro-slider": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/react-native-app-intro-slider/-/react-native-app-intro-slider-4.0.4.tgz",
"integrity": "sha512-Zkjaol6X3BbZkHUpVDj2LjdidpS6rCgKi0fx80xgGKa0pHxBRd4swWTv2bHnnvu5k1/HXwYk0mY2TbK+2jHl5w=="
},
+ "react-native-argon2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/react-native-argon2/-/react-native-argon2-2.0.1.tgz",
+ "integrity": "sha512-/iOi0S+VVgS1gQGtQgL4ZxUVS4gz6Lav3bgIbtNmr9KbOunnBYzP6/yBe/XxkbpXvasHDwdQnuppOH/nuOBn7w=="
+ },
"react-native-biometrics-changed": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/react-native-biometrics-changed/-/react-native-biometrics-changed-1.1.8.tgz",
@@ -44043,6 +45407,64 @@
"integrity": "sha512-aPSoNYoz1lRC5UorRajzAzME8UUanrEIIbvzdnPFrMDrKiJNCdjwcsyEZlNBKPdDAUrSSWyGaCZ4jHVGnd4bwA==",
"requires": {}
},
+ "react-native-cli": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/react-native-cli/-/react-native-cli-2.0.1.tgz",
+ "integrity": "sha512-QgkB1urUhGe9q1vcqQLIfNdCd/Qf3MdNQe19QO6lVjhIVKljlVMKtaK8RaZ8PCNB/cdXlO/G3tKUGk+ghMXE6w==",
+ "requires": {
+ "chalk": "^1.1.1",
+ "minimist": "^1.2.0",
+ "prompt": "^0.2.14",
+ "semver": "^5.0.3"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="
+ }
+ }
+ },
"react-native-codegen": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.6.tgz",
@@ -44115,10 +45537,22 @@
"resolved": "https://registry.npmjs.org/react-native-keychain/-/react-native-keychain-8.0.0.tgz",
"integrity": "sha512-c7Cs+YQN26UaQsRG1dmlXL7VL2ctnXwH/dl0IOMEQ7ZaL2NdN313YSAI8ZEZZjrVhNmPsyWEuvTFqWrdpItqQg=="
},
- "react-native-location-enabler": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/react-native-location-enabler/-/react-native-location-enabler-4.1.1.tgz",
- "integrity": "sha512-1gXJ+NzH5JKpaR23t1P8afEB7TKKfBkdXk2avhNUuTBlhBrqa2HrL4uDwYHoc4ZcwchsVC2P0Q7gP9L5Ot+KJw==",
+ "react-native-linear-gradient": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.6.2.tgz",
+ "integrity": "sha512-Z8Xxvupsex+9BBFoSYS87bilNPWcRfRsGC0cpJk72Nxb5p2nEkGSBv73xZbEHnW2mUFvP+huYxrVvjZkr/gRjQ==",
+ "requires": {}
+ },
+ "react-native-location": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/react-native-location/-/react-native-location-2.5.0.tgz",
+ "integrity": "sha512-myT54tZuFmN6d5RruMVfoa8eY+voJWkSd73xUVhjzJDnQr5uu5MFoH7hMg3trHF1CAkaY/2gIneOspUdGxv59Q==",
+ "requires": {}
+ },
+ "react-native-mmkv-storage": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/react-native-mmkv-storage/-/react-native-mmkv-storage-0.8.0.tgz",
+ "integrity": "sha512-L782Le5IuDYlDLGXF/qimbnzvkbYsSmV5PiDleo1DSS8Kr8Q31UK8YWtUICrDGQ9Fm7Xx4PxP9ffe2XzGeWaHQ==",
"requires": {}
},
"react-native-permissions": {
@@ -44181,6 +45615,11 @@
"resolved": "https://registry.npmjs.org/react-native-secure-key-store/-/react-native-secure-key-store-2.0.10.tgz",
"integrity": "sha512-K7aVlIGxyklnjhCidVexVgZF3LsgUD9GIxMy2NB/xkQsS9E2SJWkD/fJ56e25L2I6a9Mp1zuJrKnCtfBs1CvAw=="
},
+ "react-native-secure-keystore": {
+ "version": "git+ssh://git@github.com/mosip/secure-keystore.git#0d3a3d06e2ff49be698eb98fee4c5a5091be218f",
+ "from": "react-native-secure-keystore@github:mosip/secure-keystore#v0.1.1",
+ "requires": {}
+ },
"react-native-securerandom": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/react-native-securerandom/-/react-native-securerandom-1.0.1.tgz",
@@ -44218,10 +45657,10 @@
"resolved": "https://registry.npmjs.org/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.5.tgz",
"integrity": "sha512-Ns7Bn9H/Tyw278+5SQx9oAblDZ7JixyzeOczcBK8dipQk2pD7Djkcfnf1nB/8RErAmMLL9iXgW0QHqiII8AhKw=="
},
- "react-native-uuid": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/react-native-uuid/-/react-native-uuid-2.0.1.tgz",
- "integrity": "sha512-cptnoIbL53GTCrWlb/+jrDC6tvb7ypIyzbXNJcpR3Vab0mkeaaVd5qnB3f0whXYzS+SMoSQLcUUB0gEWqkPC0g=="
+ "react-native-tuvali": {
+ "version": "git+ssh://git@github.com/mosip/tuvali.git#a71e8bc391545a2d2a1a237670ee353fe96b7c0c",
+ "from": "react-native-tuvali@github:mosip/tuvali#v0.4.4",
+ "requires": {}
},
"react-native-vector-icons": {
"version": "8.1.0",
@@ -44279,6 +45718,48 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz",
"integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA=="
},
+ "react-universal-interface": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz",
+ "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==",
+ "requires": {}
+ },
+ "react-use": {
+ "version": "17.4.0",
+ "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.4.0.tgz",
+ "integrity": "sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==",
+ "requires": {
+ "@types/js-cookie": "^2.2.6",
+ "@xobotyi/scrollbar-width": "^1.9.5",
+ "copy-to-clipboard": "^3.3.1",
+ "fast-deep-equal": "^3.1.3",
+ "fast-shallow-equal": "^1.0.0",
+ "js-cookie": "^2.2.1",
+ "nano-css": "^5.3.1",
+ "react-universal-interface": "^0.6.2",
+ "resize-observer-polyfill": "^1.5.1",
+ "screenfull": "^5.1.0",
+ "set-harmonic-interval": "^1.0.1",
+ "throttle-debounce": "^3.0.1",
+ "ts-easing": "^0.2.0",
+ "tslib": "^2.1.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
+ }
+ }
+ },
+ "read": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
+ "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
+ "requires": {
+ "mute-stream": "~0.0.4"
+ }
+ },
"read-chunk": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz",
@@ -44419,7 +45900,6 @@
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
- "dev": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3",
@@ -44674,6 +46154,11 @@
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz",
"integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ=="
},
+ "resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ },
"resolve": {
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
@@ -44752,6 +46237,11 @@
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
},
+ "revalidator": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
+ "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg=="
+ },
"rfdc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
@@ -44816,6 +46306,14 @@
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA=="
},
+ "rtl-css-js": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz",
+ "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==",
+ "requires": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
"rtl-detect": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz",
@@ -45118,6 +46616,11 @@
"ajv-keywords": "^3.5.2"
}
},
+ "screenfull": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz",
+ "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA=="
+ },
"security-context": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/security-context/-/security-context-4.0.0.tgz",
@@ -45388,6 +46891,11 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
+ "set-harmonic-interval": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz",
+ "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g=="
+ },
"set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@@ -45494,6 +47002,11 @@
}
}
},
+ "short-unique-id": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/short-unique-id/-/short-unique-id-4.4.4.tgz",
+ "integrity": "sha512-oLF1NCmtbiTWl2SqdXZQbo5KM1b7axdp0RgQLq8qCBBLoq+o3A5wmLrNM6bZIh54/a8BJ3l69kTXuxwZ+XCYuw=="
+ },
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -45820,6 +47333,11 @@
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
},
+ "sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
+ },
"spdy": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
@@ -45902,10 +47420,49 @@
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
"dev": true
},
+ "stack-generator": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
+ "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
+ "requires": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="
+ },
"stackframe": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz",
- "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg=="
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
+ },
+ "stacktrace-gps": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
+ "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
+ "requires": {
+ "source-map": "0.5.6",
+ "stackframe": "^1.3.4"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA=="
+ }
+ }
+ },
+ "stacktrace-js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
+ "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
+ "requires": {
+ "error-stack-parser": "^2.0.6",
+ "stack-generator": "^2.0.5",
+ "stacktrace-gps": "^3.0.4"
+ }
},
"stacktrace-parser": {
"version": "0.1.10",
@@ -46226,6 +47783,11 @@
}
}
},
+ "stylis": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz",
+ "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="
+ },
"subscriptions-transport-ws": {
"version": "0.9.8",
"resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.8.tgz",
@@ -46659,6 +48221,11 @@
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
},
+ "throttle-debounce": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
+ "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg=="
+ },
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -46699,7 +48266,6 @@
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
- "dev": true,
"requires": {
"os-tmpdir": "~1.0.2"
}
@@ -46763,6 +48329,11 @@
"is-number": "^7.0.0"
}
},
+ "toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ },
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
@@ -46786,6 +48357,11 @@
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
"dev": true
},
+ "ts-easing": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz",
+ "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ=="
+ },
"ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
@@ -46809,8 +48385,7 @@
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "dev": true
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"tsutils": {
"version": "3.21.0",
@@ -47237,6 +48812,60 @@
"integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
"dev": true
},
+ "utile": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz",
+ "integrity": "sha512-ltfvuCJNa/JFOhKBBiQ9qDyyFwLstoMMO1ru0Yg/Mcl8dp1Z3IBaL7n+5dHpyma+d3lCogkgBQnWKtGxzNyqhg==",
+ "requires": {
+ "async": "~0.2.9",
+ "deep-equal": "*",
+ "i": "0.3.x",
+ "mkdirp": "0.x.x",
+ "ncp": "0.4.x",
+ "rimraf": "2.x.x"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "requires": {
+ "minimist": "^1.2.6"
+ }
+ },
+ "ncp": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz",
+ "integrity": "sha512-PfGU8jYWdRl4FqJfCy0IzbkGyFHntfWygZg46nFk/dJD/XRrk2cj0SsKSX9n5u5gE0E0YfEpKWrEkfjnlZSTXA=="
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
+ }
+ },
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@@ -47318,6 +48947,212 @@
"chokidar2": "file:chokidar2",
"graceful-fs": "^4.1.2",
"neo-async": "^2.5.0"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "dev": true,
+ "optional": true
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
+ "dev": true,
+ "optional": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
}
},
"wbuf": {
@@ -48654,6 +50489,37 @@
"string-width": "^4.0.0"
}
},
+ "winston": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz",
+ "integrity": "sha512-fPoamsHq8leJ62D1M9V/f15mjQ1UHe4+7j1wpAT3fqgA5JqhJkk4aIfPEjfMTI9x6ZTjaLOpMAjluLtmgO5b6g==",
+ "requires": {
+ "async": "0.2.x",
+ "colors": "0.6.x",
+ "cycle": "1.0.x",
+ "eyes": "0.1.x",
+ "isstream": "0.1.x",
+ "pkginfo": "0.3.x",
+ "stack-trace": "0.0.x"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
+ },
+ "colors": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
+ "integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw=="
+ },
+ "pkginfo": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz",
+ "integrity": "sha512-yO5feByMzAp96LtP58wvPKSbaKAi/1C4kV9XpTctr6EepnP6F33RBNOiVrdz9BrPA98U2BMFsTNHo44TWcbQ2A=="
+ }
+ }
+ },
"with-open-file": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz",
@@ -49125,8 +50991,7 @@
"yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
- "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
- "dev": true
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
},
"yargs": {
"version": "15.4.1",
diff --git a/package.json b/package.json
index d16e6edc..73749d92 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,8 @@
"build:android:newlogic": "cd android && ./gradlew :app:assembleNewlogicRelease && cd ..",
"build:android:ph": "cd android && ./gradlew :app:assemblePhRelease && cd ..",
"i18n:compile-strings": "node scripts/compile-strings.js",
- "lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
+ "postinstall": "patch-package"
},
"dependencies": {
"@digitalbazaar/ed25519-signature-2018": "digitalbazaar/ed25519-signature-2018",
@@ -18,10 +19,11 @@
"@digitalbazaar/rsa-signature-2018": "digitalbazaar/rsa-signature-2018#initial",
"@digitalbazaar/rsa-verification-key-2018": "digitalbazaar/rsa-verification-key-2018#initial",
"@digitalcredentials/vc": "^1.1.2",
+ "@expo-google-fonts/inter": "^0.2.3",
"@expo-google-fonts/poppins": "^0.2.0",
"@expo/metro-config": "^0.3.12",
"@idpass/smartshare-react-native": "0.2.3-beta.2",
- "@react-native-async-storage/async-storage": "~1.15.0",
+ "@react-native-clipboard/clipboard": "^1.11.2",
"@react-native-community/netinfo": "7.1.3",
"@react-native-picker/picker": "2.2.1",
"@react-navigation/bottom-tabs": "^6.0.7",
@@ -44,21 +46,29 @@
"expo-status-bar": "~1.2.0",
"expo-updates": "~0.11.6",
"i18next": "^21.6.16",
- "mosip-inji-face-sdk": "^0.1.7",
+ "iso-639-3": "^3.0.1",
+ "mosip-inji-face-sdk": "^0.1.12",
"node-forge": "^1.3.1",
+ "patch-package": "^6.5.1",
+ "postinstall-postinstall": "^2.1.0",
"react": "17.0.1",
"react-i18next": "^11.16.6",
"react-native": "0.64.4",
+ "react-native-animated-pagination-dot": "^0.4.0",
"react-native-app-intro-slider": "^4.0.4",
+ "react-native-argon2": "^2.0.1",
"react-native-biometrics-changed": "^1.1.8",
"react-native-bluetooth-state-manager": "^1.3.2",
+ "react-native-cli": "^2.0.1",
"react-native-device-info": "^8.4.8",
"react-native-dotenv": "^3.3.1",
- "react-native-elements": "^3.4.2",
+ "react-native-elements": "3.4.2",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.1.0",
"react-native-keychain": "^8.0.0",
- "react-native-location-enabler": "^4.1.0",
+ "react-native-linear-gradient": "^2.6.2",
+ "react-native-location": "^2.5.0",
+ "react-native-mmkv-storage": "0.8.0",
"react-native-permissions": "^3.6.0",
"react-native-popable": "^0.4.3",
"react-native-qrcode-svg": "^6.1.1",
@@ -67,12 +77,14 @@
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "~3.10.1",
"react-native-secure-key-store": "^2.0.10",
+ "react-native-secure-keystore": "github:mosip/secure-keystore#v0.1.1",
"react-native-securerandom": "^1.0.0",
"react-native-simple-markdown": "^1.1.0",
"react-native-svg": "12.1.1",
"react-native-swipe-gestures": "^1.0.5",
- "react-native-uuid": "^2.0.1",
+ "react-native-tuvali": "github:mosip/tuvali#v0.4.4",
"react-native-vector-icons": "^8.1.0",
+ "short-unique-id": "^4.4.4",
"xstate": "^4.35.0"
},
"devDependencies": {
diff --git a/patches/date-fns+2.28.0.patch b/patches/date-fns+2.28.0.patch
new file mode 100644
index 00000000..f809226d
--- /dev/null
+++ b/patches/date-fns+2.28.0.patch
@@ -0,0 +1,1085 @@
+diff --git a/node_modules/date-fns/.DS_Store b/node_modules/date-fns/.DS_Store
+new file mode 100644
+index 0000000..1a39c02
+Binary files /dev/null and b/node_modules/date-fns/.DS_Store differ
+diff --git a/node_modules/date-fns/locale/.DS_Store b/node_modules/date-fns/locale/.DS_Store
+new file mode 100644
+index 0000000..c1ab597
+Binary files /dev/null and b/node_modules/date-fns/locale/.DS_Store differ
+diff --git a/node_modules/date-fns/locale/fil/_lib/formatDistance/index.js b/node_modules/date-fns/locale/fil/_lib/formatDistance/index.js
+new file mode 100644
+index 0000000..387cbe5
+--- /dev/null
++++ b/node_modules/date-fns/locale/fil/_lib/formatDistance/index.js
+@@ -0,0 +1,96 @@
++"use strict";
++
++Object.defineProperty(exports, "__esModule", {
++ value: true
++});
++exports.default = void 0;
++var formatDistanceLocale = {
++ lessThanXSeconds: {
++ one: 'wala pang isang segundo',
++ other: 'wala pang {{count}} na segundo'
++ },
++ xSeconds: {
++ one: 'isang segundo',
++ other: '{{count}} segundo'
++ },
++ halfAMinute: 'kalahating minuto',
++ lessThanXMinutes: {
++ one: 'wala pang isang minuto',
++ other: 'wala pang {{count}} na minuto'
++ },
++ xMinutes: {
++ one: 'isang minuto',
++ other: '{{count}} minuto'
++ },
++ aboutXHours: {
++ one: 'mga isang oras',
++ other: 'mga {{count}} na oras'
++ },
++ xHours: {
++ one: 'isang oras',
++ other: '{{count}} na oras'
++ },
++ xDays: {
++ one: 'isang araw',
++ other: '{{count}} na araw'
++ },
++ aboutXWeeks: {
++ one: 'mga isang linggo',
++ other: 'mga {{count}} na linggo'
++ },
++ xWeeks: {
++ one: 'isang linggo',
++ other: '{{count}} na linggo'
++ },
++ aboutXMonths: {
++ one: 'mga isang buwan',
++ other: 'mga {{count}} na buwan'
++ },
++ xMonths: {
++ one: 'isang buwan',
++ other: '{{count}} na buwan'
++ },
++ aboutXYears: {
++ one: 'mga isang taon',
++ other: 'mga {{count}} na taon'
++ },
++ xYears: {
++ one: 'isang taon',
++ other: '{{count}} na taon'
++ },
++ overXYears: {
++ one: 'mahigit isang taon',
++ other: 'mahigit {{count}} na taon'
++ },
++ almostXYears: {
++ one: 'halos isang taon',
++ other: 'halos {{count}} na taon'
++ }
++};
++
++var formatDistance = function formatDistance(token, count, options) {
++ var result;
++ var tokenValue = formatDistanceLocale[token];
++
++ if (typeof tokenValue === 'string') {
++ result = tokenValue;
++ } else if (count === 1) {
++ result = tokenValue.one;
++ } else {
++ result = tokenValue.other.replace('{{count}}', count.toString());
++ }
++
++ if (options !== null && options !== void 0 && options.addSuffix) {
++ if (options.comparison && options.comparison > 0) {
++ return 'sa ' + result;
++ } else {
++ return result + ' nakaraan';
++ }
++ }
++
++ return result;
++};
++
++var _default = formatDistance;
++exports.default = _default;
++module.exports = exports.default;
+\ No newline at end of file
+diff --git a/node_modules/date-fns/locale/fil/_lib/formatLong/index.js b/node_modules/date-fns/locale/fil/_lib/formatLong/index.js
+new file mode 100644
+index 0000000..2a9ee6d
+--- /dev/null
++++ b/node_modules/date-fns/locale/fil/_lib/formatLong/index.js
+@@ -0,0 +1,46 @@
++"use strict";
++
++Object.defineProperty(exports, "__esModule", {
++ value: true
++});
++exports.default = void 0;
++
++var _index = _interopRequireDefault(require("../../../_lib/buildFormatLongFn/index.js"));
++
++function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
++
++var dateFormats = {
++ full: 'EEEE, MMMM do, y',
++ long: 'MMMM do, y',
++ medium: 'MMM d, y',
++ short: 'MM/dd/yyyy'
++};
++var timeFormats = {
++ full: 'h:mm:ss a zzzz',
++ long: 'h:mm:ss a z',
++ medium: 'h:mm:ss a',
++ short: 'h:mm a'
++};
++var dateTimeFormats = {
++ full: "{{date}} 'at' {{time}}",
++ long: "{{date}} 'at' {{time}}",
++ medium: '{{date}}, {{time}}',
++ short: '{{date}}, {{time}}'
++};
++var formatLong = {
++ date: (0, _index.default)({
++ formats: dateFormats,
++ defaultWidth: 'full'
++ }),
++ time: (0, _index.default)({
++ formats: timeFormats,
++ defaultWidth: 'full'
++ }),
++ dateTime: (0, _index.default)({
++ formats: dateTimeFormats,
++ defaultWidth: 'full'
++ })
++};
++var _default = formatLong;
++exports.default = _default;
++module.exports = exports.default;
+\ No newline at end of file
+diff --git a/node_modules/date-fns/locale/fil/_lib/formatRelative/index.js b/node_modules/date-fns/locale/fil/_lib/formatRelative/index.js
+new file mode 100644
+index 0000000..15a7812
+--- /dev/null
++++ b/node_modules/date-fns/locale/fil/_lib/formatRelative/index.js
+@@ -0,0 +1,22 @@
++"use strict";
++
++Object.defineProperty(exports, "__esModule", {
++ value: true
++});
++exports.default = void 0;
++var formatRelativeLocale = {
++ lastWeek: "'last' eeee 'at' p",
++ yesterday: "'yesterday at' p",
++ today: "'today at' p",
++ tomorrow: "'tomorrow at' p",
++ nextWeek: "eeee 'at' p",
++ other: 'P'
++};
++
++var formatRelative = function formatRelative(token, _date, _baseDate, _options) {
++ return formatRelativeLocale[token];
++};
++
++var _default = formatRelative;
++exports.default = _default;
++module.exports = exports.default;
+\ No newline at end of file
+diff --git a/node_modules/date-fns/locale/fil/_lib/localize/index.js b/node_modules/date-fns/locale/fil/_lib/localize/index.js
+new file mode 100644
+index 0000000..48da019
+--- /dev/null
++++ b/node_modules/date-fns/locale/fil/_lib/localize/index.js
+@@ -0,0 +1,154 @@
++"use strict";
++
++Object.defineProperty(exports, "__esModule", {
++ value: true
++});
++exports.default = void 0;
++
++var _index = _interopRequireDefault(require("../../../_lib/buildLocalizeFn/index.js"));
++
++function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
++
++var eraValues = {
++ narrow: ['B', 'A'],
++ abbreviated: ['BC', 'AD'],
++ wide: ['Before Christ', 'Anno Domini']
++};
++var quarterValues = {
++ narrow: ['1', '2', '3', '4'],
++ abbreviated: ['Q1', 'Q2', 'Q3', 'Q4'],
++ wide: ['Unang sangkapat', 'Ikalawang sangkapat', 'Ikatlong sangkapat', 'Ikaapat sangkapat']
++}; // Note: in English, the names of days of the week and months are capitalized.
++// If you are making a new locale based on this one, check if the same is true for the language you're working on.
++// Generally, formatted dates should look like they are in the middle of a sentence,
++// e.g. in Spanish language the weekdays and months should be in the lowercase.
++
++var monthValues = {
++ narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
++ abbreviated: ['Enero', 'Peb', 'Marso', 'Abr', 'Mayo', 'Hun', 'Hul', 'Agosto', 'Set', 'Okt', 'Nob', 'Dis'],
++ wide: ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre']
++};
++var dayValues = {
++ narrow: ['L', 'L', 'M', 'M', 'H', 'B', 'S'],
++ short: ['Li', 'Lu', 'Ma', 'Mi', 'Hu', 'Bi', 'Sa'],
++ abbreviated: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
++ wide: ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes', 'Sabado']
++};
++var dayPeriodValues = {
++ narrow: {
++ am: 'a',
++ pm: 'p',
++ midnight: 'mi',
++ noon: 'n',
++ morning: 'umaga',
++ afternoon: 'hapon',
++ evening: 'gabi',
++ night: 'gabi'
++ },
++ abbreviated: {
++ am: 'AM',
++ pm: 'PM',
++ midnight: 'hatinggabi',
++ noon: 'tanghali',
++ morning: 'umaga',
++ afternoon: 'hapon',
++ evening: 'gabi',
++ night: 'gabi'
++ },
++ wide: {
++ am: 'a.m.',
++ pm: 'p.m.',
++ midnight: 'hatinggabi',
++ noon: 'tanghali',
++ morning: 'umaga',
++ afternoon: 'hapon',
++ evening: 'gabi',
++ night: 'gabi'
++ }
++};
++var formattingDayPeriodValues = {
++ narrow: {
++ am: 'a',
++ pm: 'p',
++ midnight: 'mi',
++ noon: 'n',
++ morning: 'sa umaga',
++ afternoon: 'sa hapon',
++ evening: 'sa gabi',
++ night: 'sa gabi'
++ },
++ abbreviated: {
++ am: 'AM',
++ pm: 'PM',
++ midnight: 'midnight',
++ noon: 'noon',
++ morning: 'sa umaga',
++ afternoon: 'sa hapon',
++ evening: 'sa gabi',
++ night: 'sa gabi'
++ },
++ wide: {
++ am: 'a.m.',
++ pm: 'p.m.',
++ midnight: 'midnight',
++ noon: 'noon',
++ morning: 'sa umaga',
++ afternoon: 'sa hapon',
++ evening: 'sa gabi',
++ night: 'sa gabi'
++ }
++};
++
++var ordinalNumber = function ordinalNumber(dirtyNumber, _options) {
++ var number = Number(dirtyNumber); // If ordinal numbers depend on context, for example,
++ // if they are different for different grammatical genders,
++ // use `options.unit`.
++ //
++ // `unit` can be 'year', 'quarter', 'month', 'week', 'date', 'dayOfYear',
++ // 'day', 'hour', 'minute', 'second'.
++ // const rem100 = number % 100
++ // if (rem100 > 20 || rem100 < 10) {
++ // switch (rem100 % 10) {
++ // case 1:
++ // return number + 'st'
++ // case 2:
++ // return number + 'nd'
++ // case 3:
++ // return number + 'rd'
++ // }
++ // }
++
++ return 'ika-' + number;
++};
++
++var localize = {
++ ordinalNumber: ordinalNumber,
++ era: (0, _index.default)({
++ values: eraValues,
++ defaultWidth: 'wide'
++ }),
++ quarter: (0, _index.default)({
++ values: quarterValues,
++ defaultWidth: 'wide',
++ argumentCallback: function argumentCallback(quarter) {
++ return quarter - 1;
++ }
++ }),
++ month: (0, _index.default)({
++ values: monthValues,
++ defaultWidth: 'wide'
++ }),
++ day: (0, _index.default)({
++ values: dayValues,
++ defaultWidth: 'wide'
++ }),
++ dayPeriod: (0, _index.default)({
++ values: dayPeriodValues,
++ defaultWidth: 'wide',
++ formattingValues: formattingDayPeriodValues,
++ defaultFormattingWidth: 'wide'
++ })
++};
++var _default = localize;
++exports.default = _default;
++module.exports = exports.default;
+\ No newline at end of file
+diff --git a/node_modules/date-fns/locale/fil/_lib/match/index.js b/node_modules/date-fns/locale/fil/_lib/match/index.js
+new file mode 100644
+index 0000000..9222d63
+--- /dev/null
++++ b/node_modules/date-fns/locale/fil/_lib/match/index.js
+@@ -0,0 +1,111 @@
++"use strict";
++
++Object.defineProperty(exports, "__esModule", {
++ value: true
++});
++exports.default = void 0;
++
++var _index = _interopRequireDefault(require("../../../_lib/buildMatchFn/index.js"));
++
++var _index2 = _interopRequireDefault(require("../../../_lib/buildMatchPatternFn/index.js"));
++
++function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
++
++var matchOrdinalNumberPattern = /^(\d+)(th|st|nd|rd)?/i;
++var parseOrdinalNumberPattern = /\d+/i;
++var matchEraPatterns = {
++ narrow: /^(b|a)/i,
++ abbreviated: /^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,
++ wide: /^(before christ|before common era|anno domini|common era)/i
++};
++var parseEraPatterns = {
++ any: [/^b/i, /^(a|c)/i]
++};
++var matchQuarterPatterns = {
++ narrow: /^[1234]/i,
++ abbreviated: /^q[1234]/i,
++ wide: /^[1234](th|st|nd|rd)? quarter/i
++};
++var parseQuarterPatterns = {
++ any: [/1/i, /2/i, /3/i, /4/i]
++};
++var matchMonthPatterns = {
++ narrow: /^[jfmasond]/i,
++ abbreviated: /^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,
++ wide: /^(january|february|march|april|may|june|july|august|september|october|november|december)/i
++};
++var parseMonthPatterns = {
++ narrow: [/^j/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],
++ any: [/^ja/i, /^f/i, /^mar/i, /^ap/i, /^may/i, /^jun/i, /^jul/i, /^au/i, /^s/i, /^o/i, /^n/i, /^d/i]
++};
++var matchDayPatterns = {
++ narrow: /^[smtwf]/i,
++ short: /^(su|mo|tu|we|th|fr|sa)/i,
++ abbreviated: /^(sun|mon|tue|wed|thu|fri|sat)/i,
++ wide: /^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i
++};
++var parseDayPatterns = {
++ narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i],
++ any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i]
++};
++var matchDayPeriodPatterns = {
++ narrow: /^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,
++ any: /^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i
++};
++var parseDayPeriodPatterns = {
++ any: {
++ am: /^a/i,
++ pm: /^p/i,
++ midnight: /^mi/i,
++ noon: /^no/i,
++ morning: /morning/i,
++ afternoon: /afternoon/i,
++ evening: /evening/i,
++ night: /night/i
++ }
++};
++var match = {
++ ordinalNumber: (0, _index2.default)({
++ matchPattern: matchOrdinalNumberPattern,
++ parsePattern: parseOrdinalNumberPattern,
++ valueCallback: function valueCallback(value) {
++ return parseInt(value, 10);
++ }
++ }),
++ era: (0, _index.default)({
++ matchPatterns: matchEraPatterns,
++ defaultMatchWidth: 'wide',
++ parsePatterns: parseEraPatterns,
++ defaultParseWidth: 'any'
++ }),
++ quarter: (0, _index.default)({
++ matchPatterns: matchQuarterPatterns,
++ defaultMatchWidth: 'wide',
++ parsePatterns: parseQuarterPatterns,
++ defaultParseWidth: 'any',
++ valueCallback: function valueCallback(index) {
++ return index + 1;
++ }
++ }),
++ month: (0, _index.default)({
++ matchPatterns: matchMonthPatterns,
++ defaultMatchWidth: 'wide',
++ parsePatterns: parseMonthPatterns,
++ defaultParseWidth: 'any'
++ }),
++ day: (0, _index.default)({
++ matchPatterns: matchDayPatterns,
++ defaultMatchWidth: 'wide',
++ parsePatterns: parseDayPatterns,
++ defaultParseWidth: 'any'
++ }),
++ dayPeriod: (0, _index.default)({
++ matchPatterns: matchDayPeriodPatterns,
++ defaultMatchWidth: 'any',
++ parsePatterns: parseDayPeriodPatterns,
++ defaultParseWidth: 'any'
++ })
++};
++var _default = match;
++exports.default = _default;
++module.exports = exports.default;
+\ No newline at end of file
+diff --git a/node_modules/date-fns/locale/fil/index.js b/node_modules/date-fns/locale/fil/index.js
+new file mode 100644
+index 0000000..91fb872
+--- /dev/null
++++ b/node_modules/date-fns/locale/fil/index.js
+@@ -0,0 +1,44 @@
++"use strict";
++
++Object.defineProperty(exports, "__esModule", {
++ value: true
++});
++exports.default = void 0;
++
++var _index = _interopRequireDefault(require("./_lib/formatDistance/index.js"));
++
++var _index2 = _interopRequireDefault(require("./_lib/formatLong/index.js"));
++
++var _index3 = _interopRequireDefault(require("./_lib/formatRelative/index.js"));
++
++var _index4 = _interopRequireDefault(require("./_lib/localize/index.js"));
++
++var _index5 = _interopRequireDefault(require("./_lib/match/index.js"));
++
++function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
++
++/**
++ * @type {Locale}
++ * @category Locales
++ * @summary Filipino locale (Philippines)
++ * @language Filipino
++ * @iso-639-2 fil
++ * @author Paolo Miguel de Leon [@pmigueld]{@link https://github.com/pmigueld}
++ */
++var locale = {
++ code: 'fil',
++ formatDistance: _index.default,
++ formatLong: _index2.default,
++ formatRelative: _index3.default,
++ localize: _index4.default,
++ match: _index5.default,
++ options: {
++ weekStartsOn: 0
++ /* Sunday */
++ ,
++ firstWeekContainsDate: 1
++ }
++};
++var _default = locale;
++exports.default = _default;
++module.exports = exports.default;
+\ No newline at end of file
+diff --git a/node_modules/date-fns/locale/fil/snapshot.md b/node_modules/date-fns/locale/fil/snapshot.md
+new file mode 100644
+index 0000000..02d36d9
+--- /dev/null
++++ b/node_modules/date-fns/locale/fil/snapshot.md
+@@ -0,0 +1,530 @@
++# Filipino (fil) locale
++
++## `format` and `parse`
++
++| Title | Token string | Date | `format` result | `parse` result |
++| ------------------------------- | ------------ | ------------------------ | ----------------------------------------------------------- | ------------------------ |
++| Calendar year | yo | 1987-02-11T12:13:14.015Z | ika-1987 | Invalid Date |
++| | | 0005-01-01T12:13:14.015Z | ika-5 | Invalid Date |
++| Local week-numbering year | Yo | 1987-02-11T12:13:14.015Z | ika-1987 | Invalid Date |
++| | | 0005-01-01T12:13:14.015Z | ika-5 | Invalid Date |
++| Quarter (formatting) | Qo | 2019-01-01T12:13:14.015Z | ika-1 | Invalid Date |
++| | | 2019-04-01T12:13:14.015Z | ika-2 | Invalid Date |
++| | QQQ | 2019-01-01T12:13:14.015Z | Q1 | 2019-01-01T00:00:00.000Z |
++| | | 2019-04-01T12:13:14.015Z | Q2 | 2019-04-01T00:00:00.000Z |
++| | QQQQ | 2019-01-01T12:13:14.015Z | Unang sangkapat | Invalid Date |
++| | | 2019-04-01T12:13:14.015Z | Ikalawang sangkapat | Invalid Date |
++| | QQQQQ | 2019-01-01T12:13:14.015Z | 1 | 2019-01-01T00:00:00.000Z |
++| | | 2019-04-01T12:13:14.015Z | 2 | 2019-04-01T00:00:00.000Z |
++| Quarter (stand-alone) | qo | 2019-01-01T12:13:14.015Z | ika-1 | Invalid Date |
++| | | 2019-04-01T12:13:14.015Z | ika-2 | Invalid Date |
++| | qqq | 2019-01-01T12:13:14.015Z | Q1 | 2019-01-01T00:00:00.000Z |
++| | | 2019-04-01T12:13:14.015Z | Q2 | 2019-04-01T00:00:00.000Z |
++| | qqqq | 2019-01-01T12:13:14.015Z | Unang sangkapat | Invalid Date |
++| | | 2019-04-01T12:13:14.015Z | Ikalawang sangkapat | Invalid Date |
++| Month (formatting) | Mo | 2019-01-11T12:13:14.015Z | ika-1 | Invalid Date |
++| | | 2019-02-11T12:13:14.015Z | ika-2 | Invalid Date |
++| | | 2019-03-11T12:13:14.015Z | ika-3 | Invalid Date |
++| | | 2019-04-10T12:13:14.015Z | ika-4 | Invalid Date |
++| | | 2019-05-10T12:13:14.015Z | ika-5 | Invalid Date |
++| | | 2019-06-10T12:13:14.015Z | ika-6 | Invalid Date |
++| | | 2019-07-10T12:13:14.015Z | ika-7 | Invalid Date |
++| | | 2019-08-10T12:13:14.015Z | ika-8 | Invalid Date |
++| | | 2019-09-10T12:13:14.015Z | ika-9 | Invalid Date |
++| | | 2019-10-10T12:13:14.015Z | ika-10 | Invalid Date |
++| | | 2019-11-10T12:13:14.015Z | ika-11 | Invalid Date |
++| | | 2019-12-10T12:13:14.015Z | ika-12 | Invalid Date |
++| | MMM | 2019-01-11T12:13:14.015Z | Enero | Invalid Date |
++| | | 2019-02-11T12:13:14.015Z | Peb | Invalid Date |
++| | | 2019-03-11T12:13:14.015Z | Marso | Invalid Date |
++| | | 2019-04-10T12:13:14.015Z | Abr | Invalid Date |
++| | | 2019-05-10T12:13:14.015Z | Mayo | Invalid Date |
++| | | 2019-06-10T12:13:14.015Z | Hun | Invalid Date |
++| | | 2019-07-10T12:13:14.015Z | Hul | Invalid Date |
++| | | 2019-08-10T12:13:14.015Z | Agosto | Invalid Date |
++| | | 2019-09-10T12:13:14.015Z | Set | Invalid Date |
++| | | 2019-10-10T12:13:14.015Z | Okt | Invalid Date |
++| | | 2019-11-10T12:13:14.015Z | Nob | Invalid Date |
++| | | 2019-12-10T12:13:14.015Z | Dis | Invalid Date |
++| | MMMM | 2019-01-11T12:13:14.015Z | Enero | Invalid Date |
++| | | 2019-02-11T12:13:14.015Z | Pebrero | Invalid Date |
++| | | 2019-03-11T12:13:14.015Z | Marso | Invalid Date |
++| | | 2019-04-10T12:13:14.015Z | Abril | Invalid Date |
++| | | 2019-05-10T12:13:14.015Z | Mayo | Invalid Date |
++| | | 2019-06-10T12:13:14.015Z | Hunyo | Invalid Date |
++| | | 2019-07-10T12:13:14.015Z | Hulyo | Invalid Date |
++| | | 2019-08-10T12:13:14.015Z | Agosto | Invalid Date |
++| | | 2019-09-10T12:13:14.015Z | Setyembre | Invalid Date |
++| | | 2019-10-10T12:13:14.015Z | Oktubre | Invalid Date |
++| | | 2019-11-10T12:13:14.015Z | Nobyembre | Invalid Date |
++| | | 2019-12-10T12:13:14.015Z | Disyembre | Invalid Date |
++| | MMMMM | 2019-01-11T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
++| | | 2019-02-11T12:13:14.015Z | F | 2019-02-01T00:00:00.000Z |
++| | | 2019-03-11T12:13:14.015Z | M | 2019-03-01T00:00:00.000Z |
++| | | 2019-04-10T12:13:14.015Z | A | 2019-04-01T00:00:00.000Z |
++| | | 2019-05-10T12:13:14.015Z | M | 2019-03-01T00:00:00.000Z |
++| | | 2019-06-10T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
++| | | 2019-07-10T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
++| | | 2019-08-10T12:13:14.015Z | A | 2019-04-01T00:00:00.000Z |
++| | | 2019-09-10T12:13:14.015Z | S | 2019-09-01T00:00:00.000Z |
++| | | 2019-10-10T12:13:14.015Z | O | 2019-10-01T00:00:00.000Z |
++| | | 2019-11-10T12:13:14.015Z | N | 2019-11-01T00:00:00.000Z |
++| | | 2019-12-10T12:13:14.015Z | D | 2019-12-01T00:00:00.000Z |
++| Month (stand-alone) | Lo | 2019-01-11T12:13:14.015Z | ika-1 | Invalid Date |
++| | | 2019-02-11T12:13:14.015Z | ika-2 | Invalid Date |
++| | | 2019-03-11T12:13:14.015Z | ika-3 | Invalid Date |
++| | | 2019-04-10T12:13:14.015Z | ika-4 | Invalid Date |
++| | | 2019-05-10T12:13:14.015Z | ika-5 | Invalid Date |
++| | | 2019-06-10T12:13:14.015Z | ika-6 | Invalid Date |
++| | | 2019-07-10T12:13:14.015Z | ika-7 | Invalid Date |
++| | | 2019-08-10T12:13:14.015Z | ika-8 | Invalid Date |
++| | | 2019-09-10T12:13:14.015Z | ika-9 | Invalid Date |
++| | | 2019-10-10T12:13:14.015Z | ika-10 | Invalid Date |
++| | | 2019-11-10T12:13:14.015Z | ika-11 | Invalid Date |
++| | | 2019-12-10T12:13:14.015Z | ika-12 | Invalid Date |
++| | LLL | 2019-01-11T12:13:14.015Z | Enero | Invalid Date |
++| | | 2019-02-11T12:13:14.015Z | Peb | Invalid Date |
++| | | 2019-03-11T12:13:14.015Z | Marso | Invalid Date |
++| | | 2019-04-10T12:13:14.015Z | Abr | Invalid Date |
++| | | 2019-05-10T12:13:14.015Z | Mayo | Invalid Date |
++| | | 2019-06-10T12:13:14.015Z | Hun | Invalid Date |
++| | | 2019-07-10T12:13:14.015Z | Hul | Invalid Date |
++| | | 2019-08-10T12:13:14.015Z | Agosto | Invalid Date |
++| | | 2019-09-10T12:13:14.015Z | Set | Invalid Date |
++| | | 2019-10-10T12:13:14.015Z | Okt | Invalid Date |
++| | | 2019-11-10T12:13:14.015Z | Nob | Invalid Date |
++| | | 2019-12-10T12:13:14.015Z | Dis | Invalid Date |
++| | LLLL | 2019-01-11T12:13:14.015Z | Enero | Invalid Date |
++| | | 2019-02-11T12:13:14.015Z | Pebrero | Invalid Date |
++| | | 2019-03-11T12:13:14.015Z | Marso | Invalid Date |
++| | | 2019-04-10T12:13:14.015Z | Abril | Invalid Date |
++| | | 2019-05-10T12:13:14.015Z | Mayo | Invalid Date |
++| | | 2019-06-10T12:13:14.015Z | Hunyo | Invalid Date |
++| | | 2019-07-10T12:13:14.015Z | Hulyo | Invalid Date |
++| | | 2019-08-10T12:13:14.015Z | Agosto | Invalid Date |
++| | | 2019-09-10T12:13:14.015Z | Setyembre | Invalid Date |
++| | | 2019-10-10T12:13:14.015Z | Oktubre | Invalid Date |
++| | | 2019-11-10T12:13:14.015Z | Nobyembre | Invalid Date |
++| | | 2019-12-10T12:13:14.015Z | Disyembre | Invalid Date |
++| | LLLLL | 2019-01-11T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
++| | | 2019-02-11T12:13:14.015Z | F | 2019-02-01T00:00:00.000Z |
++| | | 2019-03-11T12:13:14.015Z | M | 2019-03-01T00:00:00.000Z |
++| | | 2019-04-10T12:13:14.015Z | A | 2019-04-01T00:00:00.000Z |
++| | | 2019-05-10T12:13:14.015Z | M | 2019-03-01T00:00:00.000Z |
++| | | 2019-06-10T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
++| | | 2019-07-10T12:13:14.015Z | J | 2019-01-01T00:00:00.000Z |
++| | | 2019-08-10T12:13:14.015Z | A | 2019-04-01T00:00:00.000Z |
++| | | 2019-09-10T12:13:14.015Z | S | 2019-09-01T00:00:00.000Z |
++| | | 2019-10-10T12:13:14.015Z | O | 2019-10-01T00:00:00.000Z |
++| | | 2019-11-10T12:13:14.015Z | N | 2019-11-01T00:00:00.000Z |
++| | | 2019-12-10T12:13:14.015Z | D | 2019-12-01T00:00:00.000Z |
++| Local week of year | wo | 2019-01-01T12:13:14.015Z | ika-1 | Invalid Date |
++| | | 2019-12-01T12:13:14.015Z | ika-49 | Invalid Date |
++| ISO week of year | Io | 2019-01-01T12:13:14.015Z | ika-1 | Invalid Date |
++| | | 2019-12-01T12:13:14.015Z | ika-48 | Invalid Date |
++| Day of month | do | 2019-02-11T12:13:14.015Z | ika-11 | Invalid Date |
++| | | 2019-02-28T12:13:14.015Z | ika-28 | Invalid Date |
++| Day of year | Do | 2019-02-11T12:13:14.015Z | ika-42 | Invalid Date |
++| | | 2019-12-31T12:13:14.015Z | ika-365 | Invalid Date |
++| Day of week (formatting) | E | 2019-02-11T12:13:14.015Z | Lun | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biy | Invalid Date |
++| | EE | 2019-02-11T12:13:14.015Z | Lun | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biy | Invalid Date |
++| | EEE | 2019-02-11T12:13:14.015Z | Lun | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biy | Invalid Date |
++| | EEEE | 2019-02-11T12:13:14.015Z | Lunes | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biyernes | Invalid Date |
++| | EEEEE | 2019-02-11T12:13:14.015Z | L | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | B | Invalid Date |
++| | EEEEEE | 2019-02-11T12:13:14.015Z | Lu | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Bi | Invalid Date |
++| ISO day of week (formatting) | io | 2019-02-11T12:13:14.015Z | ika-1 | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | ika-5 | Invalid Date |
++| | iii | 2019-02-11T12:13:14.015Z | Lun | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biy | Invalid Date |
++| | iiii | 2019-02-11T12:13:14.015Z | Lunes | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biyernes | Invalid Date |
++| | iiiii | 2019-02-11T12:13:14.015Z | L | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | B | Invalid Date |
++| | iiiiii | 2019-02-11T12:13:14.015Z | Lu | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Bi | Invalid Date |
++| Local day of week (formatting) | eo | 2019-02-11T12:13:14.015Z | ika-2 | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | ika-6 | Invalid Date |
++| | eee | 2019-02-11T12:13:14.015Z | Lun | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biy | Invalid Date |
++| | eeee | 2019-02-11T12:13:14.015Z | Lunes | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biyernes | Invalid Date |
++| | eeeee | 2019-02-11T12:13:14.015Z | L | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | B | Invalid Date |
++| | eeeeee | 2019-02-11T12:13:14.015Z | Lu | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Bi | Invalid Date |
++| Local day of week (stand-alone) | co | 2019-02-11T12:13:14.015Z | ika-2 | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | ika-6 | Invalid Date |
++| | ccc | 2019-02-11T12:13:14.015Z | Lun | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biy | Invalid Date |
++| | cccc | 2019-02-11T12:13:14.015Z | Lunes | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Biyernes | Invalid Date |
++| | ccccc | 2019-02-11T12:13:14.015Z | L | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | B | Invalid Date |
++| | cccccc | 2019-02-11T12:13:14.015Z | Lu | Invalid Date |
++| | | 2019-02-15T12:13:14.015Z | Bi | Invalid Date |
++| AM, PM | a | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | aa | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | aaa | 2019-02-11T11:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
++| | aaaa | 2019-02-11T11:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
++| | aaaaa | 2019-02-11T11:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
++| AM, PM, noon, midnight | b | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | bb | 2019-02-11T11:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | PM | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | AM | 2019-02-11T00:00:00.000Z |
++| | bbb | 2019-02-11T11:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | pm | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | am | 2019-02-11T00:00:00.000Z |
++| | bbbb | 2019-02-11T11:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | p.m. | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | a.m. | 2019-02-11T00:00:00.000Z |
++| | bbbbb | 2019-02-11T11:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
++| | | 2019-02-11T14:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T19:13:14.015Z | p | 2019-02-11T12:00:00.000Z |
++| | | 2019-02-11T02:13:14.015Z | a | 2019-02-11T00:00:00.000Z |
++| Flexible day period | B | 2019-02-11T11:13:14.015Z | sa umaga | Invalid Date |
++| | | 2019-02-11T14:13:14.015Z | sa hapon | Invalid Date |
++| | | 2019-02-11T19:13:14.015Z | sa gabi | Invalid Date |
++| | | 2019-02-11T02:13:14.015Z | sa gabi | Invalid Date |
++| | BB | 2019-02-11T11:13:14.015Z | sa umaga | Invalid Date |
++| | | 2019-02-11T14:13:14.015Z | sa hapon | Invalid Date |
++| | | 2019-02-11T19:13:14.015Z | sa gabi | Invalid Date |
++| | | 2019-02-11T02:13:14.015Z | sa gabi | Invalid Date |
++| | BBB | 2019-02-11T11:13:14.015Z | sa umaga | Invalid Date |
++| | | 2019-02-11T14:13:14.015Z | sa hapon | Invalid Date |
++| | | 2019-02-11T19:13:14.015Z | sa gabi | Invalid Date |
++| | | 2019-02-11T02:13:14.015Z | sa gabi | Invalid Date |
++| | BBBB | 2019-02-11T11:13:14.015Z | sa umaga | Invalid Date |
++| | | 2019-02-11T14:13:14.015Z | sa hapon | Invalid Date |
++| | | 2019-02-11T19:13:14.015Z | sa gabi | Invalid Date |
++| | | 2019-02-11T02:13:14.015Z | sa gabi | Invalid Date |
++| | BBBBB | 2019-02-11T11:13:14.015Z | sa umaga | Invalid Date |
++| | | 2019-02-11T14:13:14.015Z | sa hapon | Invalid Date |
++| | | 2019-02-11T19:13:14.015Z | sa gabi | Invalid Date |
++| | | 2019-02-11T02:13:14.015Z | sa gabi | Invalid Date |
++| Hour [1-12] | ho | 2019-02-11T11:13:14.015Z | ika-11 | Invalid Date |
++| | | 2019-02-11T23:13:14.015Z | ika-11 | Invalid Date |
++| Hour [0-23] | Ho | 2019-02-11T11:13:14.015Z | ika-11 | Invalid Date |
++| | | 2019-02-11T23:13:14.015Z | ika-23 | Invalid Date |
++| Hour [0-11] | Ko | 2019-02-11T11:13:14.015Z | ika-11 | Invalid Date |
++| | | 2019-02-11T23:13:14.015Z | ika-11 | Invalid Date |
++| Hour [1-24] | ko | 2019-02-11T11:13:14.015Z | ika-11 | Invalid Date |
++| | | 2019-02-11T23:13:14.015Z | ika-23 | Invalid Date |
++| Minute | mo | 2019-01-01T12:01:14.015Z | ika-1 | Invalid Date |
++| | | 2019-04-01T12:55:14.015Z | ika-55 | Invalid Date |
++| Second | so | 2019-01-01T12:13:01.015Z | ika-1 | Invalid Date |
++| | | 2019-04-01T12:13:55.015Z | ika-55 | Invalid Date |
++| Long localized date | P | 1987-01-11T12:13:14.015Z | 01/11/1987 | 1987-01-11T00:00:00.000Z |
++| | | 1987-02-11T12:13:14.015Z | 02/11/1987 | 1987-02-11T00:00:00.000Z |
++| | | 1987-03-11T12:13:14.015Z | 03/11/1987 | 1987-03-11T00:00:00.000Z |
++| | | 1987-04-11T12:13:14.015Z | 04/11/1987 | 1987-04-11T00:00:00.000Z |
++| | | 1453-05-29T23:59:59.999Z | 05/29/1453 | 1453-05-29T00:00:00.000Z |
++| | | 1987-06-11T12:13:14.015Z | 06/11/1987 | 1987-06-11T00:00:00.000Z |
++| | | 1987-07-11T12:13:14.015Z | 07/11/1987 | 1987-07-11T00:00:00.000Z |
++| | | 1987-08-11T12:13:14.015Z | 08/11/1987 | 1987-08-11T00:00:00.000Z |
++| | | 1987-09-11T12:13:14.015Z | 09/11/1987 | 1987-09-11T00:00:00.000Z |
++| | | 1987-10-11T12:13:14.015Z | 10/11/1987 | 1987-10-11T00:00:00.000Z |
++| | | 1987-11-11T12:13:14.015Z | 11/11/1987 | 1987-11-11T00:00:00.000Z |
++| | | 1987-12-11T12:13:14.015Z | 12/11/1987 | 1987-12-11T00:00:00.000Z |
++| | PP | 1987-01-11T12:13:14.015Z | Enero 11, 1987 | Invalid Date |
++| | | 1987-02-11T12:13:14.015Z | Peb 11, 1987 | Invalid Date |
++| | | 1987-03-11T12:13:14.015Z | Marso 11, 1987 | Invalid Date |
++| | | 1987-04-11T12:13:14.015Z | Abr 11, 1987 | Invalid Date |
++| | | 1453-05-29T23:59:59.999Z | Mayo 29, 1453 | Invalid Date |
++| | | 1987-06-11T12:13:14.015Z | Hun 11, 1987 | Invalid Date |
++| | | 1987-07-11T12:13:14.015Z | Hul 11, 1987 | Invalid Date |
++| | | 1987-08-11T12:13:14.015Z | Agosto 11, 1987 | Invalid Date |
++| | | 1987-09-11T12:13:14.015Z | Set 11, 1987 | Invalid Date |
++| | | 1987-10-11T12:13:14.015Z | Okt 11, 1987 | Invalid Date |
++| | | 1987-11-11T12:13:14.015Z | Nob 11, 1987 | Invalid Date |
++| | | 1987-12-11T12:13:14.015Z | Dis 11, 1987 | Invalid Date |
++| | PPP | 1987-01-11T12:13:14.015Z | Enero ika-11, 1987 | Invalid Date |
++| | | 1987-02-11T12:13:14.015Z | Pebrero ika-11, 1987 | Invalid Date |
++| | | 1987-03-11T12:13:14.015Z | Marso ika-11, 1987 | Invalid Date |
++| | | 1987-04-11T12:13:14.015Z | Abril ika-11, 1987 | Invalid Date |
++| | | 1453-05-29T23:59:59.999Z | Mayo ika-29, 1453 | Invalid Date |
++| | | 1987-06-11T12:13:14.015Z | Hunyo ika-11, 1987 | Invalid Date |
++| | | 1987-07-11T12:13:14.015Z | Hulyo ika-11, 1987 | Invalid Date |
++| | | 1987-08-11T12:13:14.015Z | Agosto ika-11, 1987 | Invalid Date |
++| | | 1987-09-11T12:13:14.015Z | Setyembre ika-11, 1987 | Invalid Date |
++| | | 1987-10-11T12:13:14.015Z | Oktubre ika-11, 1987 | Invalid Date |
++| | | 1987-11-11T12:13:14.015Z | Nobyembre ika-11, 1987 | Invalid Date |
++| | | 1987-12-11T12:13:14.015Z | Disyembre ika-11, 1987 | Invalid Date |
++| | PPPP | 1987-01-11T12:13:14.015Z | Linggo, Enero ika-11, 1987 | Invalid Date |
++| | | 1987-02-11T12:13:14.015Z | Miyerkules, Pebrero ika-11, 1987 | Invalid Date |
++| | | 1987-03-11T12:13:14.015Z | Miyerkules, Marso ika-11, 1987 | Invalid Date |
++| | | 1987-04-11T12:13:14.015Z | Sabado, Abril ika-11, 1987 | Invalid Date |
++| | | 1453-05-29T23:59:59.999Z | Linggo, Mayo ika-29, 1453 | Invalid Date |
++| | | 1987-06-11T12:13:14.015Z | Huwebes, Hunyo ika-11, 1987 | Invalid Date |
++| | | 1987-07-11T12:13:14.015Z | Sabado, Hulyo ika-11, 1987 | Invalid Date |
++| | | 1987-08-11T12:13:14.015Z | Martes, Agosto ika-11, 1987 | Invalid Date |
++| | | 1987-09-11T12:13:14.015Z | Biyernes, Setyembre ika-11, 1987 | Invalid Date |
++| | | 1987-10-11T12:13:14.015Z | Linggo, Oktubre ika-11, 1987 | Invalid Date |
++| | | 1987-11-11T12:13:14.015Z | Miyerkules, Nobyembre ika-11, 1987 | Invalid Date |
++| | | 1987-12-11T12:13:14.015Z | Biyernes, Disyembre ika-11, 1987 | Invalid Date |
++| Long localized time | p | 1987-01-11T12:13:14.015Z | 12:13 PM | 1987-01-11T12:13:00.000Z |
++| | | 1987-02-11T12:13:14.015Z | 12:13 PM | 1987-02-11T12:13:00.000Z |
++| | | 1987-03-11T12:13:14.015Z | 12:13 PM | 1987-03-11T12:13:00.000Z |
++| | | 1987-04-11T12:13:14.015Z | 12:13 PM | 1987-04-11T12:13:00.000Z |
++| | | 1453-05-29T23:59:59.999Z | 11:59 PM | 1453-05-29T23:59:00.000Z |
++| | | 1987-06-11T12:13:14.015Z | 12:13 PM | 1987-06-11T12:13:00.000Z |
++| | | 1987-07-11T12:13:14.015Z | 12:13 PM | 1987-07-11T12:13:00.000Z |
++| | | 1987-08-11T12:13:14.015Z | 12:13 PM | 1987-08-11T12:13:00.000Z |
++| | | 1987-09-11T12:13:14.015Z | 12:13 PM | 1987-09-11T12:13:00.000Z |
++| | | 1987-10-11T12:13:14.015Z | 12:13 PM | 1987-10-11T12:13:00.000Z |
++| | | 1987-11-11T12:13:14.015Z | 12:13 PM | 1987-11-11T12:13:00.000Z |
++| | | 1987-12-11T12:13:14.015Z | 12:13 PM | 1987-12-11T12:13:00.000Z |
++| | pp | 1987-01-11T12:13:14.015Z | 12:13:14 PM | 1987-01-11T12:13:14.000Z |
++| | | 1987-02-11T12:13:14.015Z | 12:13:14 PM | 1987-02-11T12:13:14.000Z |
++| | | 1987-03-11T12:13:14.015Z | 12:13:14 PM | 1987-03-11T12:13:14.000Z |
++| | | 1987-04-11T12:13:14.015Z | 12:13:14 PM | 1987-04-11T12:13:14.000Z |
++| | | 1453-05-29T23:59:59.999Z | 11:59:59 PM | 1453-05-29T23:59:59.000Z |
++| | | 1987-06-11T12:13:14.015Z | 12:13:14 PM | 1987-06-11T12:13:14.000Z |
++| | | 1987-07-11T12:13:14.015Z | 12:13:14 PM | 1987-07-11T12:13:14.000Z |
++| | | 1987-08-11T12:13:14.015Z | 12:13:14 PM | 1987-08-11T12:13:14.000Z |
++| | | 1987-09-11T12:13:14.015Z | 12:13:14 PM | 1987-09-11T12:13:14.000Z |
++| | | 1987-10-11T12:13:14.015Z | 12:13:14 PM | 1987-10-11T12:13:14.000Z |
++| | | 1987-11-11T12:13:14.015Z | 12:13:14 PM | 1987-11-11T12:13:14.000Z |
++| | | 1987-12-11T12:13:14.015Z | 12:13:14 PM | 1987-12-11T12:13:14.000Z |
++| | ppp | 1987-01-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-02-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-03-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-04-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1453-05-29T23:59:59.999Z | 11:59:59 PM GMT+0 | Errored |
++| | | 1987-06-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-07-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-08-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-09-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-10-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-11-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | | 1987-12-11T12:13:14.015Z | 12:13:14 PM GMT+0 | Errored |
++| | pppp | 1987-01-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-02-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-03-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-04-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1453-05-29T23:59:59.999Z | 11:59:59 PM GMT+00:00 | Errored |
++| | | 1987-06-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-07-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-08-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-09-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-10-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-11-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| | | 1987-12-11T12:13:14.015Z | 12:13:14 PM GMT+00:00 | Errored |
++| Combination of date and time | Pp | 1987-01-11T12:13:14.015Z | 01/11/1987, 12:13 PM | 1987-01-11T12:13:00.000Z |
++| | | 1987-02-11T12:13:14.015Z | 02/11/1987, 12:13 PM | 1987-02-11T12:13:00.000Z |
++| | | 1987-03-11T12:13:14.015Z | 03/11/1987, 12:13 PM | 1987-03-11T12:13:00.000Z |
++| | | 1987-04-11T12:13:14.015Z | 04/11/1987, 12:13 PM | 1987-04-11T12:13:00.000Z |
++| | | 1453-05-29T23:59:59.999Z | 05/29/1453, 11:59 PM | 1453-05-29T23:59:00.000Z |
++| | | 1987-06-11T12:13:14.015Z | 06/11/1987, 12:13 PM | 1987-06-11T12:13:00.000Z |
++| | | 1987-07-11T12:13:14.015Z | 07/11/1987, 12:13 PM | 1987-07-11T12:13:00.000Z |
++| | | 1987-08-11T12:13:14.015Z | 08/11/1987, 12:13 PM | 1987-08-11T12:13:00.000Z |
++| | | 1987-09-11T12:13:14.015Z | 09/11/1987, 12:13 PM | 1987-09-11T12:13:00.000Z |
++| | | 1987-10-11T12:13:14.015Z | 10/11/1987, 12:13 PM | 1987-10-11T12:13:00.000Z |
++| | | 1987-11-11T12:13:14.015Z | 11/11/1987, 12:13 PM | 1987-11-11T12:13:00.000Z |
++| | | 1987-12-11T12:13:14.015Z | 12/11/1987, 12:13 PM | 1987-12-11T12:13:00.000Z |
++| | PPpp | 1987-01-11T12:13:14.015Z | Enero 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-02-11T12:13:14.015Z | Peb 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-03-11T12:13:14.015Z | Marso 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-04-11T12:13:14.015Z | Abr 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1453-05-29T23:59:59.999Z | Mayo 29, 1453, 11:59:59 PM | Invalid Date |
++| | | 1987-06-11T12:13:14.015Z | Hun 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-07-11T12:13:14.015Z | Hul 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-08-11T12:13:14.015Z | Agosto 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-09-11T12:13:14.015Z | Set 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-10-11T12:13:14.015Z | Okt 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-11-11T12:13:14.015Z | Nob 11, 1987, 12:13:14 PM | Invalid Date |
++| | | 1987-12-11T12:13:14.015Z | Dis 11, 1987, 12:13:14 PM | Invalid Date |
++| | PPPppp | 1987-01-11T12:13:14.015Z | Enero ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-02-11T12:13:14.015Z | Pebrero ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-03-11T12:13:14.015Z | Marso ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-04-11T12:13:14.015Z | Abril ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1453-05-29T23:59:59.999Z | Mayo ika-29, 1453 at 11:59:59 PM GMT+0 | Invalid Date |
++| | | 1987-06-11T12:13:14.015Z | Hunyo ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-07-11T12:13:14.015Z | Hulyo ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-08-11T12:13:14.015Z | Agosto ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-09-11T12:13:14.015Z | Setyembre ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-10-11T12:13:14.015Z | Oktubre ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-11-11T12:13:14.015Z | Nobyembre ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | | 1987-12-11T12:13:14.015Z | Disyembre ika-11, 1987 at 12:13:14 PM GMT+0 | Invalid Date |
++| | PPPPpppp | 1987-01-11T12:13:14.015Z | Linggo, Enero ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-02-11T12:13:14.015Z | Miyerkules, Pebrero ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-03-11T12:13:14.015Z | Miyerkules, Marso ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-04-11T12:13:14.015Z | Sabado, Abril ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1453-05-29T23:59:59.999Z | Linggo, Mayo ika-29, 1453 at 11:59:59 PM GMT+00:00 | Invalid Date |
++| | | 1987-06-11T12:13:14.015Z | Huwebes, Hunyo ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-07-11T12:13:14.015Z | Sabado, Hulyo ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-08-11T12:13:14.015Z | Martes, Agosto ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-09-11T12:13:14.015Z | Biyernes, Setyembre ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-10-11T12:13:14.015Z | Linggo, Oktubre ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-11-11T12:13:14.015Z | Miyerkules, Nobyembre ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++| | | 1987-12-11T12:13:14.015Z | Biyernes, Disyembre ika-11, 1987 at 12:13:14 PM GMT+00:00 | Invalid Date |
++
++## `formatDistance`
++
++If now is January 1st, 2000, 00:00.
++
++| Date | Result | `includeSeconds: true` | `addSuffix: true` |
++| ------------------------ | ---------------------- | ----------------------- | ------------------------------- |
++| 2006-01-01T00:00:00.000Z | mga 6 na taon | mga 6 na taon | sa mga 6 na taon |
++| 2005-01-01T00:00:00.000Z | mga 5 na taon | mga 5 na taon | sa mga 5 na taon |
++| 2004-01-01T00:00:00.000Z | mga 4 na taon | mga 4 na taon | sa mga 4 na taon |
++| 2003-01-01T00:00:00.000Z | mga 3 na taon | mga 3 na taon | sa mga 3 na taon |
++| 2002-01-01T00:00:00.000Z | mga 2 na taon | mga 2 na taon | sa mga 2 na taon |
++| 2001-06-01T00:00:00.000Z | mahigit isang taon | mahigit isang taon | sa mahigit isang taon |
++| 2001-02-01T00:00:00.000Z | mga isang taon | mga isang taon | sa mga isang taon |
++| 2001-01-01T00:00:00.000Z | mga isang taon | mga isang taon | sa mga isang taon |
++| 2000-06-01T00:00:00.000Z | 5 na buwan | 5 na buwan | sa 5 na buwan |
++| 2000-03-01T00:00:00.000Z | 2 na buwan | 2 na buwan | sa 2 na buwan |
++| 2000-02-01T00:00:00.000Z | mga isang buwan | mga isang buwan | sa mga isang buwan |
++| 2000-01-15T00:00:00.000Z | 14 na araw | 14 na araw | sa 14 na araw |
++| 2000-01-02T00:00:00.000Z | isang araw | isang araw | sa isang araw |
++| 2000-01-01T06:00:00.000Z | mga 6 na oras | mga 6 na oras | sa mga 6 na oras |
++| 2000-01-01T01:00:00.000Z | mga isang oras | mga isang oras | sa mga isang oras |
++| 2000-01-01T00:45:00.000Z | mga isang oras | mga isang oras | sa mga isang oras |
++| 2000-01-01T00:30:00.000Z | 30 minuto | 30 minuto | sa 30 minuto |
++| 2000-01-01T00:15:00.000Z | 15 minuto | 15 minuto | sa 15 minuto |
++| 2000-01-01T00:01:00.000Z | isang minuto | isang minuto | sa isang minuto |
++| 2000-01-01T00:00:25.000Z | wala pang isang minuto | kalahating minuto | sa wala pang isang minuto |
++| 2000-01-01T00:00:15.000Z | wala pang isang minuto | wala pang 20 na segundo | sa wala pang isang minuto |
++| 2000-01-01T00:00:05.000Z | wala pang isang minuto | wala pang 10 na segundo | sa wala pang isang minuto |
++| 2000-01-01T00:00:00.000Z | wala pang isang minuto | wala pang 5 na segundo | wala pang isang minuto nakaraan |
++| 1999-12-31T23:59:55.000Z | wala pang isang minuto | wala pang 10 na segundo | wala pang isang minuto nakaraan |
++| 1999-12-31T23:59:45.000Z | wala pang isang minuto | wala pang 20 na segundo | wala pang isang minuto nakaraan |
++| 1999-12-31T23:59:35.000Z | wala pang isang minuto | kalahating minuto | wala pang isang minuto nakaraan |
++| 1999-12-31T23:59:00.000Z | isang minuto | isang minuto | isang minuto nakaraan |
++| 1999-12-31T23:45:00.000Z | 15 minuto | 15 minuto | 15 minuto nakaraan |
++| 1999-12-31T23:30:00.000Z | 30 minuto | 30 minuto | 30 minuto nakaraan |
++| 1999-12-31T23:15:00.000Z | mga isang oras | mga isang oras | mga isang oras nakaraan |
++| 1999-12-31T23:00:00.000Z | mga isang oras | mga isang oras | mga isang oras nakaraan |
++| 1999-12-31T18:00:00.000Z | mga 6 na oras | mga 6 na oras | mga 6 na oras nakaraan |
++| 1999-12-30T00:00:00.000Z | 2 na araw | 2 na araw | 2 na araw nakaraan |
++| 1999-12-15T00:00:00.000Z | 17 na araw | 17 na araw | 17 na araw nakaraan |
++| 1999-12-01T00:00:00.000Z | mga isang buwan | mga isang buwan | mga isang buwan nakaraan |
++| 1999-11-01T00:00:00.000Z | 2 na buwan | 2 na buwan | 2 na buwan nakaraan |
++| 1999-06-01T00:00:00.000Z | 7 na buwan | 7 na buwan | 7 na buwan nakaraan |
++| 1999-01-01T00:00:00.000Z | mga isang taon | mga isang taon | mga isang taon nakaraan |
++| 1998-12-01T00:00:00.000Z | mga isang taon | mga isang taon | mga isang taon nakaraan |
++| 1998-06-01T00:00:00.000Z | mahigit isang taon | mahigit isang taon | mahigit isang taon nakaraan |
++| 1998-01-01T00:00:00.000Z | mga 2 na taon | mga 2 na taon | mga 2 na taon nakaraan |
++| 1997-01-01T00:00:00.000Z | mga 3 na taon | mga 3 na taon | mga 3 na taon nakaraan |
++| 1996-01-01T00:00:00.000Z | mga 4 na taon | mga 4 na taon | mga 4 na taon nakaraan |
++| 1995-01-01T00:00:00.000Z | mga 5 na taon | mga 5 na taon | mga 5 na taon nakaraan |
++| 1994-01-01T00:00:00.000Z | mga 6 na taon | mga 6 na taon | mga 6 na taon nakaraan |
++
++## `formatDistanceStrict`
++
++If now is January 1st, 2000, 00:00.
++
++| Date | Result | `addSuffix: true` | With forced unit (i.e. `hour`) |
++| ------------------------ | ------------ | --------------------- | ------------------------------ |
++| 2006-01-01T00:00:00.000Z | 6 na taon | sa 6 na taon | 52608 na oras |
++| 2005-01-01T00:00:00.000Z | 5 na taon | sa 5 na taon | 43848 na oras |
++| 2004-01-01T00:00:00.000Z | 4 na taon | sa 4 na taon | 35064 na oras |
++| 2003-01-01T00:00:00.000Z | 3 na taon | sa 3 na taon | 26304 na oras |
++| 2002-01-01T00:00:00.000Z | 2 na taon | sa 2 na taon | 17544 na oras |
++| 2001-06-01T00:00:00.000Z | isang taon | sa isang taon | 12408 na oras |
++| 2001-02-01T00:00:00.000Z | isang taon | sa isang taon | 9528 na oras |
++| 2001-01-01T00:00:00.000Z | isang taon | sa isang taon | 8784 na oras |
++| 2000-06-01T00:00:00.000Z | 5 na buwan | sa 5 na buwan | 3648 na oras |
++| 2000-03-01T00:00:00.000Z | 2 na buwan | sa 2 na buwan | 1440 na oras |
++| 2000-02-01T00:00:00.000Z | isang buwan | sa isang buwan | 744 na oras |
++| 2000-01-15T00:00:00.000Z | 14 na araw | sa 14 na araw | 336 na oras |
++| 2000-01-02T00:00:00.000Z | isang araw | sa isang araw | 24 na oras |
++| 2000-01-01T06:00:00.000Z | 6 na oras | sa 6 na oras | 6 na oras |
++| 2000-01-01T01:00:00.000Z | isang oras | sa isang oras | isang oras |
++| 2000-01-01T00:45:00.000Z | 45 minuto | sa 45 minuto | isang oras |
++| 2000-01-01T00:30:00.000Z | 30 minuto | sa 30 minuto | isang oras |
++| 2000-01-01T00:15:00.000Z | 15 minuto | sa 15 minuto | 0 na oras |
++| 2000-01-01T00:01:00.000Z | isang minuto | sa isang minuto | 0 na oras |
++| 2000-01-01T00:00:25.000Z | 25 segundo | sa 25 segundo | 0 na oras |
++| 2000-01-01T00:00:15.000Z | 15 segundo | sa 15 segundo | 0 na oras |
++| 2000-01-01T00:00:05.000Z | 5 segundo | sa 5 segundo | 0 na oras |
++| 2000-01-01T00:00:00.000Z | 0 segundo | 0 segundo nakaraan | 0 na oras |
++| 1999-12-31T23:59:55.000Z | 5 segundo | 5 segundo nakaraan | 0 na oras |
++| 1999-12-31T23:59:45.000Z | 15 segundo | 15 segundo nakaraan | 0 na oras |
++| 1999-12-31T23:59:35.000Z | 25 segundo | 25 segundo nakaraan | 0 na oras |
++| 1999-12-31T23:59:00.000Z | isang minuto | isang minuto nakaraan | 0 na oras |
++| 1999-12-31T23:45:00.000Z | 15 minuto | 15 minuto nakaraan | 0 na oras |
++| 1999-12-31T23:30:00.000Z | 30 minuto | 30 minuto nakaraan | isang oras |
++| 1999-12-31T23:15:00.000Z | 45 minuto | 45 minuto nakaraan | isang oras |
++| 1999-12-31T23:00:00.000Z | isang oras | isang oras nakaraan | isang oras |
++| 1999-12-31T18:00:00.000Z | 6 na oras | 6 na oras nakaraan | 6 na oras |
++| 1999-12-30T00:00:00.000Z | 2 na araw | 2 na araw nakaraan | 48 na oras |
++| 1999-12-15T00:00:00.000Z | 17 na araw | 17 na araw nakaraan | 408 na oras |
++| 1999-12-01T00:00:00.000Z | isang buwan | isang buwan nakaraan | 744 na oras |
++| 1999-11-01T00:00:00.000Z | 2 na buwan | 2 na buwan nakaraan | 1464 na oras |
++| 1999-06-01T00:00:00.000Z | 7 na buwan | 7 na buwan nakaraan | 5136 na oras |
++| 1999-01-01T00:00:00.000Z | isang taon | isang taon nakaraan | 8760 na oras |
++| 1998-12-01T00:00:00.000Z | isang taon | isang taon nakaraan | 9504 na oras |
++| 1998-06-01T00:00:00.000Z | 2 na taon | 2 na taon nakaraan | 13896 na oras |
++| 1998-01-01T00:00:00.000Z | 2 na taon | 2 na taon nakaraan | 17520 na oras |
++| 1997-01-01T00:00:00.000Z | 3 na taon | 3 na taon nakaraan | 26280 na oras |
++| 1996-01-01T00:00:00.000Z | 4 na taon | 4 na taon nakaraan | 35064 na oras |
++| 1995-01-01T00:00:00.000Z | 5 na taon | 5 na taon nakaraan | 43824 na oras |
++| 1994-01-01T00:00:00.000Z | 6 na taon | 6 na taon nakaraan | 52584 na oras |
++
++## `formatRelative`
++
++If now is January 1st, 2000, 00:00.
++
++| Date | Result |
++| ------------------------ | ---------------------- |
++| 2000-01-10T00:00:00.000Z | 01/10/2000 |
++| 2000-01-05T00:00:00.000Z | Miyerkules at 12:00 AM |
++| 2000-01-02T00:00:00.000Z | tomorrow at 12:00 AM |
++| 2000-01-01T00:00:00.000Z | today at 12:00 AM |
++| 1999-12-31T00:00:00.000Z | yesterday at 12:00 AM |
++| 1999-12-27T00:00:00.000Z | last Lunes at 12:00 AM |
++| 1999-12-21T00:00:00.000Z | 12/21/1999 |
++
++## `formatDuration`
++
++| Duration | Result |
++| ------------- | ------------- |
++| {"years":0} | 0 na taon |
++| {"years":1} | isang taon |
++| {"years":2} | 2 na taon |
++| {"months":0} | 0 na buwan |
++| {"months":1} | isang buwan |
++| {"months":2} | 2 na buwan |
++| {"weeks":0} | 0 na linggo |
++| {"weeks":1} | isang linggo |
++| {"weeks":2} | 2 na linggo |
++| {"days":0} | 0 na araw |
++| {"days":1} | isang araw |
++| {"days":2} | 2 na araw |
++| {"hours":0} | 0 na oras |
++| {"hours":1} | isang oras |
++| {"hours":2} | 2 na oras |
++| {"minutes":0} | 0 minuto |
++| {"minutes":1} | isang minuto |
++| {"minutes":2} | 2 minuto |
++| {"seconds":0} | 0 segundo |
++| {"seconds":1} | isang segundo |
++| {"seconds":2} | 2 segundo |
+diff --git a/node_modules/date-fns/locale/index.js b/node_modules/date-fns/locale/index.js
+index ddb817a..ecfff3e 100644
+--- a/node_modules/date-fns/locale/index.js
++++ b/node_modules/date-fns/locale/index.js
+@@ -544,6 +544,13 @@ Object.defineProperty(exports, "zhTW", {
+ }
+ });
+
++Object.defineProperty(exports, "fil", {
++ enumerable: true,
++ get: function () {
++ return _index91.default;
++ }
++});
++
+ var _index = _interopRequireDefault(require("./af/index.js"));
+
+ var _index2 = _interopRequireDefault(require("./ar/index.js"));
+@@ -724,4 +731,6 @@ var _index89 = _interopRequireDefault(require("./zh-HK/index.js"));
+
+ var _index90 = _interopRequireDefault(require("./zh-TW/index.js"));
+
++var _index91 = _interopRequireDefault(require("./fil/index.js"));
++
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+\ No newline at end of file
diff --git a/patches/react-native-elements+3.4.2.patch b/patches/react-native-elements+3.4.2.patch
new file mode 100644
index 00000000..f684a7cb
--- /dev/null
+++ b/patches/react-native-elements+3.4.2.patch
@@ -0,0 +1,26 @@
+diff --git a/node_modules/react-native-elements/dist/tab/Tab.js b/node_modules/react-native-elements/dist/tab/Tab.js
+index 1204a46..bcce099 100644
+--- a/node_modules/react-native-elements/dist/tab/Tab.js
++++ b/node_modules/react-native-elements/dist/tab/Tab.js
+@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
+ return t;
+ };
+ import React from 'react';
+-import { View, Animated, StyleSheet, } from 'react-native';
++import { View, Animated, StyleSheet, I18nManager } from 'react-native';
+ import Button from '../buttons/Button';
+ import { withTheme } from '../config';
+ import Color from 'color';
+@@ -69,7 +69,11 @@ const TabContainer = (_a) => {
+ {
+ translateX: animation.interpolate({
+ inputRange: [0, 1],
+- outputRange: [0, WIDTH],
++ /**
++ * The Fix has been raised as PR in the upstream, This patch has to removed once the fix is made in the upstream.
++ * PR : https://github.com/react-native-elements/react-native-elements/pull/3779
++ */
++ outputRange: [0, I18nManager.isRTL ? -WIDTH : WIDTH],
+ }),
+ },
+ ],
diff --git a/patches/react-native-mmkv-storage+0.8.0.patch b/patches/react-native-mmkv-storage+0.8.0.patch
new file mode 100644
index 00000000..bf067937
--- /dev/null
+++ b/patches/react-native-mmkv-storage+0.8.0.patch
@@ -0,0 +1,13 @@
+diff --git a/node_modules/react-native-mmkv-storage/ios/SecureStorage.m b/node_modules/react-native-mmkv-storage/ios/SecureStorage.m
+index dbea26b..1b465af 100644
+--- a/node_modules/react-native-mmkv-storage/ios/SecureStorage.m
++++ b/node_modules/react-native-mmkv-storage/ios/SecureStorage.m
+@@ -224,7 +224,7 @@ NSString *serviceName = nil;
+ serviceName = _serviceName;
+ }
+
+-NSError * secureKeyStoreError(NSString *errMsg)
++NSError * secureKeyStoreErrorHandler(NSString *errMsg)
+ {
+ NSError *error = [NSError errorWithDomain:serviceName code:200 userInfo:@{@"reason": errMsg}];
+ return error;
diff --git a/purpleAassets/logo.png b/purpleAassets/logo.png
deleted file mode 100644
index 25ae27cb..00000000
Binary files a/purpleAassets/logo.png and /dev/null differ
diff --git a/purpleAassets/_cart_sel.png b/purpleAssets/_cart_sel.png
similarity index 100%
rename from purpleAassets/_cart_sel.png
rename to purpleAssets/_cart_sel.png
diff --git a/purpleAassets/bg_cart_one.png b/purpleAssets/bg_cart_one.png
similarity index 100%
rename from purpleAassets/bg_cart_one.png
rename to purpleAssets/bg_cart_one.png
diff --git a/purpleAassets/cart_unsel.png b/purpleAssets/cart_unsel.png
similarity index 100%
rename from purpleAassets/cart_unsel.png
rename to purpleAssets/cart_unsel.png
diff --git a/purpleAassets/idpass-logo.png b/purpleAssets/idpass-logo.png
similarity index 100%
rename from purpleAassets/idpass-logo.png
rename to purpleAssets/idpass-logo.png
diff --git a/purpleAssets/logo.png b/purpleAssets/logo.png
new file mode 100644
index 00000000..e065ff5c
Binary files /dev/null and b/purpleAssets/logo.png differ
diff --git a/purpleAssets/otp-mobile-logo.png b/purpleAssets/otp-mobile-logo.png
new file mode 100644
index 00000000..5f313226
Binary files /dev/null and b/purpleAssets/otp-mobile-logo.png differ
diff --git a/purpleAssets/profile_icon.png b/purpleAssets/profile_icon.png
new file mode 100644
index 00000000..0dd08417
Binary files /dev/null and b/purpleAssets/profile_icon.png differ
diff --git a/purpleAassets/profile_icon_unsel.png b/purpleAssets/profile_icon_unsel.png
similarity index 100%
rename from purpleAassets/profile_icon_unsel.png
rename to purpleAssets/profile_icon_unsel.png
diff --git a/purpleAassets/splash.png b/purpleAssets/splash.png
similarity index 100%
rename from purpleAassets/splash.png
rename to purpleAssets/splash.png
diff --git a/routes/index.ts b/routes/index.ts
index e088f054..f14009a3 100644
--- a/routes/index.ts
+++ b/routes/index.ts
@@ -9,19 +9,26 @@ import { WelcomeScreen } from '../screens/WelcomeScreen';
import { PasscodeScreen } from '../screens/PasscodeScreen';
import { MainLayout } from '../screens/MainLayout';
import { NotificationsScreen } from '../screens/NotificationsScreen';
-import { Image } from 'react-native';
+import { SetupLanguageScreen } from '../screens/SetupLanguageScreen';
+import { IntroSlidersScreen } from '../screens/Home/IntroSlidersScreen';
+import { RequestLayout } from '../screens/Request/RequestLayout';
+import { RequestStackParamList } from '../screens/Request/RequestLayoutController';
export const baseRoutes: Screen[] = [
+ {
+ name: 'Language',
+ component: SetupLanguageScreen,
+ },
+ {
+ name: 'IntroSliders',
+ component: IntroSlidersScreen,
+ options: {
+ headerShown: false,
+ },
+ },
{
name: 'Welcome',
component: WelcomeScreen,
- options: {
- headerLeft: () =>
- React.createElement(Image, {
- source: require('../assets/idpass-logo.png'),
- style: { width: 124, height: 27, resizeMode: 'contain' },
- }),
- },
},
{
name: 'Auth',
@@ -35,6 +42,13 @@ export const baseRoutes: Screen[] = [
name: 'Biometric',
component: BiometricScreen,
},
+ {
+ name: 'Request',
+ component: RequestLayout,
+ options: {
+ headerShown: false,
+ },
+ },
];
export const authRoutes: Screen[] = [
@@ -52,6 +66,8 @@ export const authRoutes: Screen[] = [
];
export type RootStackParamList = {
+ Language: undefined;
+ IntroSliders: undefined;
Welcome: undefined;
Auth: undefined;
Passcode: {
@@ -82,3 +98,8 @@ export type BiometricRouteProps = NativeStackScreenProps<
RootStackParamList,
'Biometric'
>;
+
+export type RequestRouteProps = NativeStackScreenProps<
+ RequestStackParamList,
+ 'Request'
+>;
diff --git a/routes/main.ts b/routes/main.ts
index 2914c44f..96cf7e1c 100644
--- a/routes/main.ts
+++ b/routes/main.ts
@@ -3,57 +3,56 @@ import {
BottomTabNavigationOptions,
BottomTabScreenProps,
} from '@react-navigation/bottom-tabs';
+import { Image } from 'react-native';
import { HomeScreen } from '../screens/Home/HomeScreen';
-import { ProfileScreen } from '../screens/Profile/ProfileScreen';
import { RootStackParamList } from './index';
-import { RequestLayout } from '../screens/Request/RequestLayout';
import { ScanLayout } from '../screens/Scan/ScanLayout';
+import { HistoryScreen } from '../screens/History/HistoryScreen';
import i18n from '../i18n';
-export const mainRoutes: TabScreen[] = [
- {
- name: 'Home',
- component: HomeScreen,
- icon: 'home',
- options: {
- title: i18n.t('MainLayout:home'),
- },
+const home: TabScreen = {
+ name: 'home',
+ component: HomeScreen,
+ icon: 'home',
+ options: {
+ headerTitle: '',
+ headerLeft: () =>
+ React.createElement(Image, {
+ source: require('../assets/inji-home-logo.png'),
+ style: { width: 124, height: 27, resizeMode: 'contain' },
+ }),
},
- {
- name: 'Scan',
- component: ScanLayout,
- icon: 'qr-code-scanner',
- options: {
- title: i18n.t('MainLayout:scan'),
- headerShown: false,
- },
+};
+export const scan: TabScreen = {
+ name: 'scan',
+ component: ScanLayout,
+ icon: 'qr-code-scanner',
+ options: {
+ title: i18n.t('MainLayout:scan'),
+ headerShown: false,
},
- {
- name: 'Request',
- component: RequestLayout,
- icon: 'file-download',
- options: {
- title: i18n.t('MainLayout:request'),
- headerShown: false,
- },
+};
+const history: TabScreen = {
+ name: 'history',
+ component: HistoryScreen,
+ icon: 'history',
+ options: {
+ title: i18n.t('MainLayout:history'),
+ headerRight: null,
},
- {
- name: 'Profile',
- component: ProfileScreen,
- icon: 'person',
- options: {
- title: i18n.t('MainLayout:profile'),
- },
- },
-];
+};
+
+export const mainRoutes: TabScreen[] = [];
+mainRoutes.push(home);
+mainRoutes.push(scan);
+mainRoutes.push(history);
export type MainBottomTabParamList = {
- Home: {
+ home: {
activeTab: number;
};
Scan: undefined;
- Request: undefined;
- Profile: undefined;
+ History: undefined;
};
export interface TabScreen {
@@ -69,5 +68,5 @@ export type MainRouteProps = BottomTabScreenProps<
export type HomeRouteProps = BottomTabScreenProps<
MainBottomTabParamList & RootStackParamList,
- 'Home'
+ 'home'
>;
diff --git a/screens/AppController.ts b/screens/AppController.ts
new file mode 100644
index 00000000..05608c43
--- /dev/null
+++ b/screens/AppController.ts
@@ -0,0 +1,16 @@
+import { useContext } from 'react';
+import { GlobalContext } from '../shared/GlobalContext';
+import { StoreEvents } from '../machines/store';
+import { APP_EVENTS } from '../machines/app';
+
+export function useApp() {
+ const { appService } = useContext(GlobalContext);
+ const storeService = appService.children.get('store');
+ return {
+ ignoreDecrypt: () => appService.send('DECRYPT_ERROR_DISMISS'),
+ IGNORE: () => storeService.send(StoreEvents.IGNORE()),
+ TRY_AGAIN: () => storeService.send(StoreEvents.TRY_AGAIN()),
+ RESET: () =>
+ appService.send(APP_EVENTS.RESET_KEY_INVALIDATE_ERROR_DISMISS()),
+ };
+}
diff --git a/screens/AppLayout.tsx b/screens/AppLayout.tsx
index c8800db3..18044d0c 100644
--- a/screens/AppLayout.tsx
+++ b/screens/AppLayout.tsx
@@ -4,34 +4,32 @@ import {
NativeStackNavigationOptions,
createNativeStackNavigator,
} from '@react-navigation/native-stack';
-import { LanguageSelector } from '../components/LanguageSelector';
import { authRoutes, baseRoutes } from '../routes';
import { useAppLayout } from './AppLayoutController';
-import { Icon } from 'react-native-elements';
-import { Theme } from '../components/ui/styleUtils';
import { StatusBar } from 'react-native';
const { Navigator, Screen } = createNativeStackNavigator();
-
export const AppLayout: React.FC = () => {
const controller = useAppLayout();
-
const options: NativeStackNavigationOptions = {
title: '',
headerTitleAlign: 'center',
headerShadowVisible: false,
- headerRight: () => (
- }
- />
- ),
headerBackVisible: false,
};
return (
-
+
{baseRoutes.map((route) => (
))}
diff --git a/screens/AppLayoutController.ts b/screens/AppLayoutController.ts
index 2f693dc7..85e2469f 100644
--- a/screens/AppLayoutController.ts
+++ b/screens/AppLayoutController.ts
@@ -1,13 +1,19 @@
import { useSelector } from '@xstate/react';
import { useContext } from 'react';
-import { selectAuthorized } from '../machines/auth';
+import {
+ selectAuthorized,
+ selectLanguagesetup,
+ selectUnauthorized,
+} from '../machines/auth';
import { GlobalContext } from '../shared/GlobalContext';
export function useAppLayout() {
const { appService } = useContext(GlobalContext);
const authService = appService.children.get('auth');
-
+ const isLanguagesetup = useSelector(authService, selectLanguagesetup);
return {
isAuthorized: useSelector(authService, selectAuthorized),
+ isUnAuthorized: useSelector(authService, selectUnauthorized),
+ isLanguagesetup,
};
}
diff --git a/screens/AuthScreen.tsx b/screens/AuthScreen.tsx
index 6913a276..a2beedf3 100644
--- a/screens/AuthScreen.tsx
+++ b/screens/AuthScreen.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { Icon } from 'react-native-elements';
import { MessageOverlay } from '../components/MessageOverlay';
-import { Button, Centered, Column, Text } from '../components/ui';
+import { Button, Column, Text } from '../components/ui';
import { Theme } from '../components/ui/styleUtils';
import { RootRouteProps } from '../routes';
import { useAuthScreen } from './AuthScreenController';
@@ -15,21 +15,33 @@ export const AuthScreen: React.FC = (props) => {
+ backgroundColor={Theme.Colors.whiteBackgroundColor}
+ align="space-between">
- {t('header')}
+
+
+
+ {t('header')}
+
+
+ {t('Description')}
+
+
-
-
-
+
= (props) => {
- const { t } = useTranslation('HistoryTab');
+export const HistoryScreen: React.FC = () => {
+ const { t } = useTranslation('HistoryScreen');
const controller = useHistoryTab();
return (
-
+
= (props) => {
return (
-
- {TabItem(t('myVcsTab', { vcLabel: controller.vcLabel.plural }))}
- {TabItem(t('receivedVcsTab', { vcLabel: controller.vcLabel.plural }))}
- {TabItem(t('historyTab'))}
-
{controller.haveTabsLoaded && (
= (props) => {
service={controller.tabRefs.receivedVcs}
vcItemActor={controller.selectedVc}
/>
-
)}
@@ -56,6 +42,7 @@ export const HomeScreen: React.FC = (props) => {
onRevokeDelete={() => {
controller.REVOKE();
}}
+ activeTab={controller.activeTab}
/>
)}
diff --git a/screens/Home/HomeScreenController.ts b/screens/Home/HomeScreenController.ts
index 3bce275a..83b9cb7a 100644
--- a/screens/Home/HomeScreenController.ts
+++ b/screens/Home/HomeScreenController.ts
@@ -1,6 +1,5 @@
import { useInterpret, useSelector } from '@xstate/react';
import { useContext, useEffect, useRef } from 'react';
-import { selectVcLabel } from '../../machines/settings';
import { HomeRouteProps } from '../../routes/main';
import { GlobalContext } from '../../shared/GlobalContext';
import {
@@ -23,7 +22,6 @@ export function useHomeScreen(props: HomeRouteProps) {
})
);
const service = useInterpret(machine.current);
- const settingsService = appService.children.get('settings');
const vcService = appService.children.get('vc');
useEffect(() => {
@@ -36,7 +34,6 @@ export function useHomeScreen(props: HomeRouteProps) {
service,
activeTab: useSelector(service, selectActiveTab),
- vcLabel: useSelector(settingsService, selectVcLabel),
selectedVc: useSelector(service, selectSelectedVc),
tabRefs: useSelector(service, selectTabRefs),
diff --git a/screens/Home/HomeScreenMachine.ts b/screens/Home/HomeScreenMachine.ts
index 285d05e5..ef35b8a4 100644
--- a/screens/Home/HomeScreenMachine.ts
+++ b/screens/Home/HomeScreenMachine.ts
@@ -9,10 +9,6 @@ import {
import { createModel } from 'xstate/lib/model';
import { vcItemMachine } from '../../machines/vcItem';
import { AppServices } from '../../shared/GlobalContext';
-import {
- createHistoryTabMachine,
- HistoryTabMachine,
-} from './HistoryTabMachine';
import { createMyVcsTabMachine, MyVcsTabMachine } from './MyVcsTabMachine';
import {
createReceivedVcsTabMachine,
@@ -25,7 +21,6 @@ const model = createModel(
tabRefs: {
myVcs: {} as ActorRefFrom,
receivedVcs: {} as ActorRefFrom,
- history: {} as ActorRefFrom,
},
selectedVc: null as ActorRefFrom,
activeTab: 0,
@@ -45,14 +40,12 @@ const model = createModel(
const MY_VCS_TAB_REF_ID = 'myVcsTab';
const RECEIVED_VCS_TAB_REF_ID = 'receivedVcsTab';
-const HISTORY_TAB_REF_ID = 'historyTab';
export const HomeScreenEvents = model.events;
export type TabRef =
| ActorRefFrom
- | ActorRefFrom
- | ActorRefFrom;
+ | ActorRefFrom;
export const HomeScreenMachine = model.createMachine(
{
@@ -143,10 +136,6 @@ export const HomeScreenMachine = model.createMachine(
createReceivedVcsTabMachine(context.serviceRefs),
RECEIVED_VCS_TAB_REF_ID
),
- history: spawn(
- createHistoryTabMachine(context.serviceRefs),
- HISTORY_TAB_REF_ID
- ),
}),
}),
diff --git a/screens/Home/IntroSlidersScreen.tsx b/screens/Home/IntroSlidersScreen.tsx
new file mode 100644
index 00000000..614062ba
--- /dev/null
+++ b/screens/Home/IntroSlidersScreen.tsx
@@ -0,0 +1,155 @@
+import React, { useRef } from 'react';
+import AppIntroSlider from 'react-native-app-intro-slider';
+import { Dimensions, Image, StatusBar, View } from 'react-native';
+import { Centered, Column, Row, Text, Button } from '../../components/ui';
+import { Theme } from '../../components/ui/styleUtils';
+import { useTranslation } from 'react-i18next';
+import { RootRouteProps } from '../../routes';
+import { useWelcomeScreen } from '../WelcomeScreenController';
+import LinearGradient from 'react-native-linear-gradient';
+
+export const IntroSlidersScreen: React.FC = (props) => {
+ const slider = useRef();
+
+ const { t } = useTranslation('OnboardingOverlay');
+ const controller = useWelcomeScreen(props);
+
+ const slides = [
+ {
+ key: 'one',
+ title: t('stepOneTitle'),
+ text: t('stepOneText'),
+ image: Theme.protectPrivacy,
+ },
+ {
+ key: 'two',
+ title: t('stepTwoTitle'),
+ text: t('stepTwoText'),
+ image: Theme.sharingIntro,
+ },
+ {
+ key: 'three',
+ title: t('stepThreeTitle'),
+ text: t('stepThreeText'),
+ image: Theme.walletIntro,
+ },
+ {
+ key: 'four',
+ title: t('stepFourTitle'),
+ text: t('stepFourText'),
+ image: Theme.IntroScanner,
+ },
+ ];
+
+ const renderItem = ({ item }) => {
+ return (
+
+
+
+
+
+
+
+
+ {controller.isPasscodeSet() ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ {item.title}
+
+
+ {item.text}
+
+
+
+
+ );
+ };
+
+ const renderNextButton = () => {
+ return (
+
+
+
+ {t('next')}
+
+
+
+ );
+ };
+ const renderDoneButton = () => {
+ return (
+
+
+
+ {controller.isPasscodeSet() ? t('getStarted') : t('goBack')}
+
+
+
+ );
+ };
+ return (
+
+
+
+ controller.isPasscodeSet() ? controller.NEXT() : controller.BACK()
+ }
+ />
+
+ );
+};
diff --git a/screens/Home/MyVcs/AddVcModal.strings.json b/screens/Home/MyVcs/AddVcModal.strings.json
index 959db561..13a9f95a 100644
--- a/screens/Home/MyVcs/AddVcModal.strings.json
+++ b/screens/Home/MyVcs/AddVcModal.strings.json
@@ -13,4 +13,4 @@
"missingVid": "VID not available in database"
}
}
-}
\ No newline at end of file
+}
diff --git a/screens/Home/MyVcs/AddVcModal.tsx b/screens/Home/MyVcs/AddVcModal.tsx
index 4ff7268f..f67824bb 100644
--- a/screens/Home/MyVcs/AddVcModal.tsx
+++ b/screens/Home/MyVcs/AddVcModal.tsx
@@ -25,6 +25,7 @@ export const AddVcModal: React.FC = (props) => {
onDismiss={controller.DISMISS}
onInputDone={controller.INPUT_OTP}
error={controller.otpError}
+ resend={controller.RESEND_OTP}
/>
service.send(AddVcModalEvents.INPUT_OTP(otp)),
+ RESEND_OTP: () => service.send(AddVcModalEvents.RESEND_OTP()),
+
DISMISS: () => service.send(AddVcModalEvents.DISMISS()),
};
}
diff --git a/screens/Home/MyVcs/AddVcModalMachine.ts b/screens/Home/MyVcs/AddVcModalMachine.ts
index 0ec83d4c..a980ea3d 100644
--- a/screens/Home/MyVcs/AddVcModalMachine.ts
+++ b/screens/Home/MyVcs/AddVcModalMachine.ts
@@ -9,9 +9,14 @@ import {
} from 'xstate';
import { createModel } from 'xstate/lib/model';
import { BackendResponseError, request } from '../../../shared/request';
-import { VC_ITEM_STORE_KEY } from '../../../shared/constants';
+import {
+ argon2iConfigForUinVid,
+ argon2iSalt,
+ VC_ITEM_STORE_KEY,
+} from '../../../shared/constants';
import { VcIdType } from '../../../types/vc';
import i18n from '../../../i18n';
+import { hashData } from '../../../shared/commonUtil';
const model = createModel(
{
@@ -23,11 +28,14 @@ const model = createModel(
otpError: '',
transactionId: '',
requestId: '',
+ isPinned: false,
+ hashedId: '',
},
{
events: {
INPUT_ID: (id: string) => ({ id }),
INPUT_OTP: (otp: string) => ({ otp }),
+ RESEND_OTP: () => ({}),
VALIDATE_INPUT: () => ({}),
READY: (idInputRef: TextInput) => ({ idInputRef }),
DISMISS: () => ({}),
@@ -99,7 +107,7 @@ export const AddVcModalMachine =
},
],
SELECT_ID_TYPE: {
- actions: ['setIdType', 'clearId'],
+ actions: ['clearIdError', 'setIdType', 'clearId'],
},
},
},
@@ -134,7 +142,7 @@ export const AddVcModalMachine =
},
],
SELECT_ID_TYPE: {
- actions: ['setIdType', 'clearId'],
+ actions: ['clearIdError', 'setIdType', 'clearId'],
target: 'idle',
},
},
@@ -173,6 +181,29 @@ export const AddVcModalMachine =
actions: 'resetIdInputRef',
target: 'acceptingIdInput',
},
+ RESEND_OTP: {
+ target: '.resendOTP',
+ },
+ },
+ initial: 'idle',
+ states: {
+ idle: {},
+ resendOTP: {
+ invoke: {
+ src: 'requestOtp',
+ onDone: [
+ {
+ target: 'idle',
+ },
+ ],
+ onError: [
+ {
+ actions: 'setIdBackendError',
+ target: '#AddVcModal.acceptingIdInput.invalid.backend',
+ },
+ ],
+ },
+ },
},
},
requestingCredential: {
@@ -181,7 +212,7 @@ export const AddVcModalMachine =
onDone: [
{
actions: 'setRequestId',
- target: 'done',
+ target: 'calculatingHashedId',
},
],
onError: [
@@ -197,6 +228,15 @@ export const AddVcModalMachine =
],
},
},
+ calculatingHashedId: {
+ invoke: {
+ src: 'calculateHashedId',
+ onDone: {
+ actions: 'setHashedId',
+ target: 'done',
+ },
+ },
+ },
done: {
type: 'final',
data: (context) => VC_ITEM_STORE_KEY(context),
@@ -236,19 +276,31 @@ export const AddVcModalMachine =
'VID invalid': 'invalidVid',
'UIN not available in database': 'missingUin',
'VID not available in database': 'missingVid',
+ 'No message available': 'noMessageAvailable',
+ 'while generating otp error is occured':
+ 'whileGeneratingOtpErrorIsOccured',
+ 'Network request failed': 'networkRequestFailed',
'Invalid Input Parameter - individualId':
context.idType === 'UIN' ? 'invalidUin' : 'invalidVid',
+ 'VID is expired/deactivated': 'deactivatedVid',
};
return ID_ERRORS_MAP[message]
? i18n.t(`errors.backend.${ID_ERRORS_MAP[message]}`, {
ns: 'AddVcModal',
})
- : message;
+ : i18n.t(`errors.genericError`, {
+ ns: 'common',
+ });
},
}),
clearId: model.assign({ id: '' }),
+ setHashedId: model.assign({
+ hashedId: (_context, event) =>
+ (event as DoneInvokeEvent).data,
+ }),
+
clearIdError: model.assign({ idError: '' }),
setIdErrorEmpty: model.assign({
@@ -265,6 +317,7 @@ export const AddVcModalMachine =
const message = (event as ErrorPlatformEvent).data.message;
const OTP_ERRORS_MAP = {
'OTP is invalid': 'invalidOtp',
+ 'OTP has expired': 'expiredOtp',
};
return OTP_ERRORS_MAP[message]
? i18n.t(`errors.backend.${OTP_ERRORS_MAP[message]}`, {
@@ -316,6 +369,17 @@ export const AddVcModalMachine =
);
return response.response.requestId;
},
+
+ calculateHashedId: async (context) => {
+ const value = context.id;
+ const hashedid = await hashData(
+ value,
+ argon2iSalt,
+ argon2iConfigForUinVid
+ );
+ context.hashedId = hashedid;
+ return hashedid;
+ },
},
guards: {
diff --git a/screens/Home/MyVcs/AddVcModalMachine.typegen.ts b/screens/Home/MyVcs/AddVcModalMachine.typegen.ts
index 86cf20fb..7cd1289c 100644
--- a/screens/Home/MyVcs/AddVcModalMachine.typegen.ts
+++ b/screens/Home/MyVcs/AddVcModalMachine.typegen.ts
@@ -17,6 +17,10 @@ export interface Typegen0 {
type: 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
};
+ 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]': {
+ type: 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]';
+ data: unknown;
+ };
'error.platform.AddVcModal.requestingCredential:invocation[0]': {
type: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
data: unknown;
@@ -28,7 +32,9 @@ export interface Typegen0 {
};
'invokeSrcNameMap': {
requestCredential: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
- requestOtp: 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
+ requestOtp:
+ | 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
+ | 'done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]';
};
'missingImplementations': {
actions: never;
@@ -38,10 +44,11 @@ export interface Typegen0 {
};
'eventsCausingActions': {
clearId: 'SELECT_ID_TYPE';
- clearIdError: 'INPUT_ID' | 'VALIDATE_INPUT';
+ clearIdError: 'INPUT_ID' | 'SELECT_ID_TYPE' | 'VALIDATE_INPUT';
clearOtp:
| 'DISMISS'
| 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
+ | 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.init';
focusInput:
@@ -49,6 +56,7 @@ export interface Typegen0 {
| 'SELECT_ID_TYPE'
| 'VALIDATE_INPUT'
| 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
+ | 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.after(100)#AddVcModal.acceptingIdInput.focusing';
forwardToParent: 'DISMISS';
@@ -56,6 +64,7 @@ export interface Typegen0 {
setId: 'INPUT_ID';
setIdBackendError:
| 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
+ | 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]';
setIdErrorEmpty: 'VALIDATE_INPUT';
setIdErrorWrongFormat: 'VALIDATE_INPUT';
@@ -66,6 +75,7 @@ export interface Typegen0 {
setRequestId: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
setTransactionId:
| 'DISMISS'
+ | 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.init';
};
@@ -77,7 +87,7 @@ export interface Typegen0 {
};
'eventsCausingServices': {
requestCredential: 'INPUT_OTP';
- requestOtp: 'VALIDATE_INPUT';
+ requestOtp: 'RESEND_OTP' | 'VALIDATE_INPUT';
};
'matchesStates':
| 'acceptingIdInput'
@@ -90,6 +100,8 @@ export interface Typegen0 {
| 'acceptingIdInput.rendering'
| 'acceptingIdInput.requestingOtp'
| 'acceptingOtpInput'
+ | 'acceptingOtpInput.idle'
+ | 'acceptingOtpInput.resendOTP'
| 'done'
| 'requestingCredential'
| {
@@ -100,6 +112,7 @@ export interface Typegen0 {
| 'rendering'
| 'requestingOtp'
| { invalid?: 'backend' | 'empty' | 'format' };
+ acceptingOtpInput?: 'idle' | 'resendOTP';
};
'tags': never;
}
diff --git a/screens/Home/MyVcs/BindingVcWarningOverlay.tsx b/screens/Home/MyVcs/BindingVcWarningOverlay.tsx
index 4003873c..13f4a54e 100644
--- a/screens/Home/MyVcs/BindingVcWarningOverlay.tsx
+++ b/screens/Home/MyVcs/BindingVcWarningOverlay.tsx
@@ -8,7 +8,7 @@ import { Theme } from '../../../components/ui/styleUtils';
export const BindingVcWarningOverlay: React.FC = (
props
) => {
- const { t } = useTranslation('VcDetails');
+ const { t } = useTranslation('BindingVcWarningOverlay');
return (
= (
align="space-between"
crossAlign="center"
padding={'10'}
- width={Dimensions.get('screen').width * 0.8}>
-
+ width={Dimensions.get('screen').width * 0.8}
+ height={Dimensions.get('screen').height * 0}>
+
= (
-
- {t('Alert')}
-
+
+ {t('alert')}
-
- {t('BindingWarning')}
-
+
+ {t('BindingWarning')}
+
+
diff --git a/screens/Home/MyVcs/DownloadingVcModal.strings.json b/screens/Home/MyVcs/DownloadingVcModal.strings.json
index c599a2a1..acb4ac90 100644
--- a/screens/Home/MyVcs/DownloadingVcModal.strings.json
+++ b/screens/Home/MyVcs/DownloadingVcModal.strings.json
@@ -1,5 +1,5 @@
{
- "header": "Downloading your {{vcLabel}}",
- "bodyText": "This may take some time, we will notify you when your {{vcLabel}} has been downloaded and is available",
+ "header": "Downloading your Card",
+ "bodyText": "This may take some time, we will notify you when your Card has been downloaded and is available",
"backButton": "Back home"
}
\ No newline at end of file
diff --git a/screens/Home/MyVcs/DownloadingVcModal.tsx b/screens/Home/MyVcs/DownloadingVcModal.tsx
index a4bc4628..dab012bc 100644
--- a/screens/Home/MyVcs/DownloadingVcModal.tsx
+++ b/screens/Home/MyVcs/DownloadingVcModal.tsx
@@ -2,11 +2,9 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { Button, Column, Text } from '../../../components/ui';
import { Modal, ModalProps } from '../../../components/ui/Modal';
-import { useDownloadingVcModal } from './DownloadingVcModalController';
export const DownloadingVcModal: React.FC = (props) => {
const { t } = useTranslation('DownloadingVcModal');
- const controller = useDownloadingVcModal();
return (
= (props) => {
- {t('header', { vcLabel: controller.vcLabel.singular })}
-
-
- {t('bodyText', { vcLabel: controller.vcLabel.singular })}
+ {t('header')}
+ {t('bodyText')}
diff --git a/screens/Home/MyVcs/DownloadingVcModalController.ts b/screens/Home/MyVcs/DownloadingVcModalController.ts
deleted file mode 100644
index 6326bb5e..00000000
--- a/screens/Home/MyVcs/DownloadingVcModalController.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { useSelector } from '@xstate/react';
-import { useContext } from 'react';
-import { selectVcLabel } from '../../../machines/settings';
-import { GlobalContext } from '../../../shared/GlobalContext';
-
-export function useDownloadingVcModal() {
- const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
-
- return {
- vcLabel: useSelector(settingsService, selectVcLabel),
- };
-}
diff --git a/screens/Home/MyVcs/GetIdInputModal.strings.json b/screens/Home/MyVcs/GetIdInputModal.strings.json
index 08c34929..62c76fa6 100644
--- a/screens/Home/MyVcs/GetIdInputModal.strings.json
+++ b/screens/Home/MyVcs/GetIdInputModal.strings.json
@@ -1,7 +1,7 @@
{
- "header": "To retrieve your UIN or VID, enter your application {{vcLabel}} number",
+ "header": "Enter your Application ID to get your UIN",
"getUIN": "Get UIN/VID",
- "applicationId": "Application {{vcLabel}} number",
+ "applicationId": "Application ID",
"requestingOTP": "Requesting OTP...",
- "qstnMarkToolTip": "Application {{vcLabel}} Number is printed on the acknowledgment provided after enrollment"
+ "qstnMarkToolTip": "Application ID is available in the acknowledgement received after enrolment."
}
\ No newline at end of file
diff --git a/screens/Home/MyVcs/GetIdInputModal.tsx b/screens/Home/MyVcs/GetIdInputModal.tsx
index f39891ce..2cda584f 100644
--- a/screens/Home/MyVcs/GetIdInputModal.tsx
+++ b/screens/Home/MyVcs/GetIdInputModal.tsx
@@ -12,93 +12,93 @@ import { KeyboardAvoidingView, Platform } from 'react-native';
import { useTranslation } from 'react-i18next';
import { MessageOverlay } from '../../../components/MessageOverlay';
import Tooltip from '../../../lib/react-native-elements/tooltip/Tooltip';
+import { color } from 'react-native-elements/dist/helpers';
export const GetIdInputModal: React.FC = (props) => {
const { t } = useTranslation('GetIdInputModal');
const controller = useGetIdInputModal(props);
- const inputLabel = t('applicationId', {
- vcLabel: controller.vcLabel.singular,
- });
+ const inputLabel = t('enterApplicationId');
return (
-
+
-
- {t('header', { vcLabel: controller.vcLabel.singular })}
-
+
+ {t('applicationIdLabel')}
+
-
-
- {t('qstnMarkToolTip', {
- vcLabel: controller.vcLabel.singular,
- })}
-
- }
- width={Dimensions.get('screen').width * 0.8}
- height={Dimensions.get('screen').height * 0.2}
- backgroundColor={'lightgray'}
- withPointer={true}
- skipAndroidStatusBar={true}
- onOpen={controller.ACTIVATE_ICON_COLOR}
- onClose={controller.DEACTIVATE_ICON_COLOR}>
-
- {controller.isInvalid ? (
-
- ) : (
-
- )}
-
-
- }
- errorStyle={{ color: Theme.Colors.errorMessage }}
- errorMessage={controller.idError}
- onChangeText={controller.INPUT_ID}
- ref={(node) =>
- !controller.idInputRef && controller.READY(node)
- }
- />
-
+ {t('qstnMarkToolTip')}}
+ width={Dimensions.get('screen').width * 0.8}
+ height={Dimensions.get('screen').height * 0.2}
+ backgroundColor={'lightgray'}
+ withPointer={true}
+ skipAndroidStatusBar={true}
+ onOpen={controller.ACTIVATE_ICON_COLOR}
+ onClose={controller.DEACTIVATE_ICON_COLOR}>
+
+ {controller.isInvalid ? (
+
+ ) : (
+
+ )}
+
+
+ }
+ errorStyle={{ color: Theme.Colors.errorMessage }}
+ errorMessage={controller.idError}
+ onChangeText={controller.INPUT_ID}
+ ref={(node) => !controller.idInputRef && controller.READY(node)}
+ />
+
+
diff --git a/screens/Home/MyVcs/GetIdInputModalController.ts b/screens/Home/MyVcs/GetIdInputModalController.ts
index f6e4a913..9a3e188c 100644
--- a/screens/Home/MyVcs/GetIdInputModalController.ts
+++ b/screens/Home/MyVcs/GetIdInputModalController.ts
@@ -1,7 +1,4 @@
-import { useContext } from 'react';
import { useSelector } from '@xstate/react';
-import { selectVcLabel } from '../../../machines/settings';
-import { GlobalContext } from '../../../shared/GlobalContext';
import { ActorRefFrom } from 'xstate';
import { TextInput } from 'react-native';
import { ModalProps } from '../../../components/ui/Modal';
@@ -19,13 +16,9 @@ import {
} from './GetVcModalMachine';
export function useGetIdInputModal({ service }: GetIdInputModalProps) {
- const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
-
return {
id: useSelector(service, selectId),
idInputRef: useSelector(service, selectIdInputRef),
- vcLabel: useSelector(settingsService, selectVcLabel),
idError: useSelector(service, selectIdError),
otpError: useSelector(service, selectOtpError),
iconColor: useSelector(service, selectIconColor),
diff --git a/screens/Home/MyVcs/GetVcModal.tsx b/screens/Home/MyVcs/GetVcModal.tsx
index 891ab6c3..92f2761e 100644
--- a/screens/Home/MyVcs/GetVcModal.tsx
+++ b/screens/Home/MyVcs/GetVcModal.tsx
@@ -13,7 +13,7 @@ export const GetVcModal: React.FC = (props) => {
diff --git a/screens/Home/MyVcs/GetVcModalMachine.ts b/screens/Home/MyVcs/GetVcModalMachine.ts
index 1c6fcac9..76f1f52f 100644
--- a/screens/Home/MyVcs/GetVcModalMachine.ts
+++ b/screens/Home/MyVcs/GetVcModalMachine.ts
@@ -174,7 +174,8 @@ export const GetVcModalMachine =
target: 'requestingUinVid',
},
DISMISS: {
- target: '#GetVcModal.acceptingIdInput.idle',
+ actions: ['resetIdInputRef'],
+ target: '#GetVcModal.acceptingIdInput',
},
},
},
@@ -233,6 +234,9 @@ export const GetVcModalMachine =
const message = (event as ErrorPlatformEvent).data.message;
const ID_ERRORS_MAP = {
'AID is not ready': 'applicationProcessing',
+ 'No message available': 'noMessageAvailable',
+ 'Network request failed': 'networkRequestFailed',
+ 'Invalid Input Parameter- individualId': 'invalidAid',
};
return ID_ERRORS_MAP[message]
? i18n.t(`errors.backend.${ID_ERRORS_MAP[message]}`, {
@@ -258,6 +262,7 @@ export const GetVcModalMachine =
const message = (event as ErrorPlatformEvent).data.message;
const OTP_ERRORS_MAP = {
'OTP is invalid': 'invalidOtp',
+ 'OTP has expired': 'expiredOtp',
};
return OTP_ERRORS_MAP[message]
? i18n.t(`errors.backend.${OTP_ERRORS_MAP[message]}`, {
@@ -271,6 +276,12 @@ export const GetVcModalMachine =
idInputRef: (_context, event) => event.idInputRef,
}),
+ resetIdInputRef: model.assign({
+ idInputRef: () => {
+ return null;
+ },
+ }),
+
clearOtp: assign({ otp: '' }),
setIconColorActivate: assign({ iconColor: true }),
diff --git a/screens/Home/MyVcs/GetVcModalMachine.typegen.ts b/screens/Home/MyVcs/GetVcModalMachine.typegen.ts
index 6abac106..a01a7cf8 100644
--- a/screens/Home/MyVcs/GetVcModalMachine.typegen.ts
+++ b/screens/Home/MyVcs/GetVcModalMachine.typegen.ts
@@ -34,7 +34,7 @@ export interface Typegen0 {
actions: never;
delays: never;
guards: never;
- services: 'AddVcModal';
+ services: never;
};
'eventsCausingActions': {
clearIdError: 'INPUT_ID';
@@ -44,13 +44,13 @@ export interface Typegen0 {
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.init';
focusInput:
- | 'DISMISS'
| 'INPUT_ID'
| 'VALIDATE_INPUT'
| 'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.after(100)#GetVcModal.acceptingIdInput.focusing';
forwardToParent: 'DISMISS';
+ resetIdInputRef: 'DISMISS';
setIconColorActivate: 'ACTIVATE_ICON_COLOR';
setIconColorDeactivate: 'DEACTIVATE_ICON_COLOR';
setId: 'INPUT_ID';
@@ -76,7 +76,6 @@ export interface Typegen0 {
};
'eventsCausingServices': {
AddVcModal:
- | 'DISMISS'
| 'INPUT_ID'
| 'xstate.after(100)#GetVcModal.acceptingIdInput.focusing';
requestOtp: 'VALIDATE_INPUT';
diff --git a/screens/Home/MyVcs/HistoryTab.tsx b/screens/Home/MyVcs/HistoryTab.tsx
new file mode 100644
index 00000000..38b26f65
--- /dev/null
+++ b/screens/Home/MyVcs/HistoryTab.tsx
@@ -0,0 +1,66 @@
+import React from 'react';
+import { Icon, ListItem } from 'react-native-elements';
+import { useTranslation } from 'react-i18next';
+import { Modal } from '../../../components/ui/Modal';
+import { Centered, Column, Text } from '../../../components/ui';
+import { ActivityLogText } from '../../../components/ActivityLogText';
+import { ActorRefFrom } from 'xstate';
+import { vcItemMachine } from '../../../machines/vcItem';
+import { useKebabPopUp } from '../../../components/KebabPopUpController';
+import { Theme } from '../../../components/ui/styleUtils';
+import { isSameVC } from '../../../shared/constants';
+
+export const HistoryTab: React.FC = (props) => {
+ const { t } = useTranslation('HistoryTab');
+ const controller = useKebabPopUp(props);
+ return (
+
+
+
+
+ {props.label}
+
+
+
+
+
+ {controller.activities.map((activity) => {
+ const vcKeyMatch = isSameVC(activity._vcKey, props.vcKey);
+ if (vcKeyMatch) {
+ return (
+
+ );
+ }
+ })}
+ {controller.activities.length === 0 && (
+
+
+
+ {t('noHistory')}
+
+
+ )}
+
+
+
+ );
+};
+
+export interface HistoryTabProps {
+ label: string;
+ vcKey: string;
+ service: ActorRefFrom;
+}
diff --git a/screens/Home/MyVcs/IdInputModal.strings.json b/screens/Home/MyVcs/IdInputModal.strings.json
index deb78390..695af594 100644
--- a/screens/Home/MyVcs/IdInputModal.strings.json
+++ b/screens/Home/MyVcs/IdInputModal.strings.json
@@ -1,6 +1,6 @@
{
- "header": "Enter the MOSIP-provided UIN or VID of the {{vcLabel}} you wish to retrieve",
- "generateVc": "Generate {{vcLabel}}",
+ "header": "Enter your UIN/VID to download your Card",
+ "generateVc": "Generate My Card",
"enterId": "Enter your {{idType}}",
"noUIN/VID": "Don't have your UIN/VID? Get it here",
"requestingOTP": "Requesting OTP..."
diff --git a/screens/Home/MyVcs/IdInputModal.tsx b/screens/Home/MyVcs/IdInputModal.tsx
index 4563b599..0b1def7e 100644
--- a/screens/Home/MyVcs/IdInputModal.tsx
+++ b/screens/Home/MyVcs/IdInputModal.tsx
@@ -39,20 +39,26 @@ export const IdInputModal: React.FC = (props) => {
+ onShow={setIndividualID}
+ headerTitle={t('header')}
+ headerElevation={2}>
-
- {t('header', { vcLabel: controller.vcLabel.singular })}
-
-
+
+ {t('guideLabel')}
+
+
= (props) => {
- ) : null
- }
- errorStyle={{ color: Theme.Colors.errorMessage }}
+ errorStyle={Theme.TextStyles.error}
errorMessage={controller.idError}
onChangeText={controller.INPUT_ID}
ref={setIdInputRef}
/>
+
+
{!controller.id && (
-
- {t('noUIN/VID')}
-
+
+
+ {t('noUIN/VID')}
+
+
+
+ {t('getItHere')}
+
+
+
)}
diff --git a/screens/Home/MyVcs/IdInputModalController.ts b/screens/Home/MyVcs/IdInputModalController.ts
index c3422d25..c344873d 100644
--- a/screens/Home/MyVcs/IdInputModalController.ts
+++ b/screens/Home/MyVcs/IdInputModalController.ts
@@ -1,7 +1,4 @@
-import { useContext } from 'react';
import { useSelector } from '@xstate/react';
-import { selectVcLabel } from '../../../machines/settings';
-import { GlobalContext } from '../../../shared/GlobalContext';
import { ActorRefFrom } from 'xstate';
import { TextInput } from 'react-native';
import { ModalProps } from '../../../components/ui/Modal';
@@ -20,14 +17,10 @@ import {
import { VcIdType } from '../../../types/vc';
export function useIdInputModal({ service }: IdInputModalProps) {
- const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
-
return {
id: useSelector(service, selectId),
idType: useSelector(service, selectIdType),
idInputRef: useSelector(service, selectIdInputRef),
- vcLabel: useSelector(settingsService, selectVcLabel),
idError: useSelector(service, selectIdError),
otpError: useSelector(service, selectOtpError),
diff --git a/screens/Home/MyVcs/OtpVerification.tsx b/screens/Home/MyVcs/OtpVerification.tsx
deleted file mode 100644
index 89e83c33..00000000
--- a/screens/Home/MyVcs/OtpVerification.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React from 'react';
-import { useTranslation } from 'react-i18next';
-import { PinInput } from '../../../components/PinInput';
-import { Column, Text } from '../../../components/ui';
-import { ModalProps, Modal } from '../../../components/ui/Modal';
-import { Theme } from '../../../components/ui/styleUtils';
-import { Image } from 'react-native';
-import { Icon } from 'react-native-elements';
-
-export const OtpVerification: React.FC = (props) => {
- const { t } = useTranslation('OtpVerificationModal');
-
- return (
- }>
-
-
- {t('enterOtp')}
-
-
- {props.error}
-
-
-
-
-
-
- );
-};
-
-interface OtpVerificationModalProps extends ModalProps {
- onInputDone: (otp: string) => void;
- error?: string;
-}
diff --git a/screens/Home/MyVcs/OtpVerificationModal.strings.json b/screens/Home/MyVcs/OtpVerificationModal.strings.json
index ca64aba1..a378016e 100644
--- a/screens/Home/MyVcs/OtpVerificationModal.strings.json
+++ b/screens/Home/MyVcs/OtpVerificationModal.strings.json
@@ -1,3 +1,6 @@
{
- "enterOtp": "Enter the 6-digit verification code we sent you"
+ "title": "OTP Verification",
+ "otpSentMessage": "We've sent the 6 digit code to your registered mobile number!",
+ "resendTheCode": "You can resend the code in ",
+ "resendCode": "Resend Code"
}
\ No newline at end of file
diff --git a/screens/Home/MyVcs/OtpVerificationModal.tsx b/screens/Home/MyVcs/OtpVerificationModal.tsx
index 22509f8a..e2dedf32 100644
--- a/screens/Home/MyVcs/OtpVerificationModal.tsx
+++ b/screens/Home/MyVcs/OtpVerificationModal.tsx
@@ -1,22 +1,64 @@
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { Icon } from 'react-native-elements';
import { PinInput } from '../../../components/PinInput';
import { Column, Text } from '../../../components/ui';
-import { Modal, ModalProps } from '../../../components/ui/Modal';
+import { ModalProps, Modal } from '../../../components/ui/Modal';
import { Theme } from '../../../components/ui/styleUtils';
+import { Image, TouchableOpacity } from 'react-native';
export const OtpVerificationModal: React.FC = (
props
) => {
const { t } = useTranslation('OtpVerificationModal');
+ const [timer, setTimer] = useState(180); // 30 seconds
+
+ useEffect(() => {
+ if (timer === 0) return;
+
+ const intervalId = setInterval(() => {
+ setTimer(timer - 1);
+ }, 1000);
+
+ return () => clearInterval(intervalId);
+ }, [timer]);
+
+ const formatTime = (seconds) => {
+ const minutes = Math.floor(seconds / 60);
+ const Seconds = seconds % 60;
+ return `${minutes < 10 ? '0' + minutes : minutes}:${
+ Seconds < 10 ? '0' + Seconds : Seconds
+ }`;
+ };
+
return (
-
-
-
-
- {t('enterOtp')}
+ setTimer(180)}>
+
+
+
+
+
+ {t('title')}
+
+
+ {t('otpSentMessage')}
+
+
+
= (
{props.error}
+
+
+ {` ${t('resendTheCode')} : ${formatTime(timer)}`}
+
+
+ 0
+ ? null
+ : () => {
+ props.resend();
+ setTimer(180);
+ }
+ }>
+ 0 ? Theme.Colors.GrayText : Theme.Colors.AddIdBtnBg
+ }
+ margin="10 0 0 0"
+ weight="semibold">
+ {t('resendCode')}
+
+
@@ -34,4 +103,5 @@ export const OtpVerificationModal: React.FC = (
interface OtpVerificationModalProps extends ModalProps {
onInputDone: (otp: string) => void;
error?: string;
+ resend?: () => void;
}
diff --git a/screens/Home/MyVcs/RemoveVcWarningOverlay.tsx b/screens/Home/MyVcs/RemoveVcWarningOverlay.tsx
new file mode 100644
index 00000000..451b527c
--- /dev/null
+++ b/screens/Home/MyVcs/RemoveVcWarningOverlay.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { Dimensions, Image } from 'react-native';
+import { Overlay } from 'react-native-elements';
+import { Button, Column, Text, Row } from '../../../components/ui';
+import { Theme } from '../../../components/ui/styleUtils';
+
+export const RemoveVcWarningOverlay: React.FC = (
+ props
+) => {
+ const { t } = useTranslation('RemoveVcWarningOverlay');
+
+ return (
+
+
+
+
+
+ !
+
+
+
+
+ {t('alert')}
+
+
+ {t('removeWarning')}
+
+
+
+
+
+
+
+
+ );
+};
+
+interface RemoveVcWarningOverlayProps {
+ isVisible: boolean;
+ onConfirm: () => void;
+ onCancel: () => void;
+}
diff --git a/screens/Home/MyVcs/WalletBinding.tsx b/screens/Home/MyVcs/WalletBinding.tsx
new file mode 100644
index 00000000..4eb48e71
--- /dev/null
+++ b/screens/Home/MyVcs/WalletBinding.tsx
@@ -0,0 +1,102 @@
+import React from 'react';
+import { Icon, ListItem } from 'react-native-elements';
+import { Row, Text } from '../../../components/ui';
+import { Theme } from '../../../components/ui/styleUtils';
+import { useTranslation } from 'react-i18next';
+import { BindingVcWarningOverlay } from './BindingVcWarningOverlay';
+import { OtpVerificationModal } from './OtpVerificationModal';
+import { MessageOverlay } from '../../../components/MessageOverlay';
+import { useKebabPopUp } from '../../../components/KebabPopUpController';
+import { Dimensions } from 'react-native';
+import { ActorRefFrom } from 'xstate';
+import { vcItemMachine } from '../../../machines/vcItem';
+
+export const WalletBinding: React.FC = (props) => {
+ const controller = useKebabPopUp(props);
+
+ const WalletVerified: React.FC = () => {
+ return (
+
+ );
+ };
+ const { t } = useTranslation('WalletBinding');
+
+ return controller.emptyWalletBindingId ? (
+
+ {props.Icon && (
+
+ )}
+
+
+
+ {props.label}
+
+
+
+ {props.content}
+
+
+
+
+
+
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+ );
+};
+
+interface WalletBindingProps {
+ label: string;
+ content?: string;
+ Icon?: string;
+ service: ActorRefFrom;
+}
diff --git a/screens/Home/MyVcs/WalletBindingController.ts b/screens/Home/MyVcs/WalletBindingController.ts
new file mode 100644
index 00000000..70b0ec12
--- /dev/null
+++ b/screens/Home/MyVcs/WalletBindingController.ts
@@ -0,0 +1,86 @@
+import { useSelector, useInterpret } from '@xstate/react';
+import { useContext, useRef, useState } from 'react';
+import { GlobalContext } from '../../../shared/GlobalContext';
+import { selectMyVcs, VcEvents } from '../../../machines/vc';
+import {
+ createVcItemMachine,
+ isShowingBindingWarning,
+ selectAcceptingBindingOtp,
+ isWalletBindingInProgress,
+ VcItemEvents,
+ selectIsAcceptingOtpInput,
+ selectOtpError,
+ selectShowWalletBindingError,
+ selectWalletBindingError,
+} from '../../../machines/vcItem';
+import { useTranslation } from 'react-i18next';
+
+import { ActorRefFrom } from 'xstate';
+
+export function useWalletBinding(props) {
+ const { t } = useTranslation('ProfileScreen');
+ const { appService } = useContext(GlobalContext);
+
+ const machine = useRef(
+ createVcItemMachine(
+ appService.getSnapshot().context.serviceRefs,
+ props.vcKey
+ )
+ );
+
+ const bindingService = useInterpret(machine.current, { devTools: __DEV__ });
+
+ const vcService = appService.children.get('vc');
+
+ const vcKeys = useSelector(vcService, selectMyVcs);
+
+ const otpError = useSelector(bindingService, selectOtpError);
+ const [isRevoking, setRevoking] = useState(false);
+ const [isAuthenticating, setAuthenticating] = useState(false);
+ const [isViewing, setIsViewing] = useState(false);
+ const [isBindingWarning, setisBindingWarning] = useState(false);
+ const [toastVisible, setToastVisible] = useState(false);
+ const [message, setMessage] = useState('');
+ const [selectedIndex, setSelectedIndex] = useState(null);
+ const [selectedVidKeys, setSelectedVidKeys] = useState([]);
+
+ const selectVcItem = (index: number, vcKey: string) => {
+ return () => {
+ setSelectedIndex(index);
+ };
+ };
+
+ const WalletBindingInProgress = useSelector(
+ bindingService,
+ isWalletBindingInProgress
+ );
+
+ return {
+ isBindingWarning,
+ setisBindingWarning,
+ otpError,
+ message,
+ toastVisible,
+ WalletBindingInProgress,
+
+ isAcceptingOtpInput: useSelector(bindingService, selectIsAcceptingOtpInput),
+ isAcceptingBindingOtp: useSelector(
+ bindingService,
+ selectAcceptingBindingOtp
+ ),
+ isBindingError: useSelector(bindingService, selectShowWalletBindingError),
+ walletBindingError: useSelector(bindingService, selectWalletBindingError),
+
+ DISMISS: () => bindingService.send(VcItemEvents.DISMISS()),
+
+ CONFIRM: () => bindingService.send(VcItemEvents.CONFIRM()),
+
+ CANCEL: () => bindingService.send(VcItemEvents.CANCEL()),
+
+ REFRESH: () => vcService.send(VcEvents.REFRESH_MY_VCS()),
+ setAuthenticating,
+ selectVcItem,
+ setIsViewing,
+ setRevoking,
+ };
+}
diff --git a/screens/Home/MyVcsTab.strings.json b/screens/Home/MyVcsTab.strings.json
index 3ef93b5e..ffa23f54 100644
--- a/screens/Home/MyVcsTab.strings.json
+++ b/screens/Home/MyVcsTab.strings.json
@@ -1,5 +1,15 @@
{
- "addVcButton": "Add {{vcLabel}}",
- "generateVc": "Generate your {{vcLabel}}",
- "generateVcDescription": "Tap on \"Add {{vcLabel}}\" below to download your {{vcLabel}}"
-}
\ No newline at end of file
+ "addVcButton": "Add Card",
+ "generateVc": "Generate your Cards",
+ "generateVcDescription": "Tap on \"Add Card\" below to download your Card",
+ "errors": {
+ "savingFailed": {
+ "title": "Failed to save the Card",
+ "message": "Something went wrong while saving Card to the store."
+ },
+ "storageLimitReached": {
+ "title": "Insufficient Appdata",
+ "message": "You cannot add or receive cards since the Appdata is full"
+ }
+ }
+}
diff --git a/screens/Home/MyVcsTab.tsx b/screens/Home/MyVcsTab.tsx
index e4e07860..20b51d77 100644
--- a/screens/Home/MyVcsTab.tsx
+++ b/screens/Home/MyVcsTab.tsx
@@ -1,21 +1,24 @@
import React from 'react';
-import { Button, Column, Text, Centered } from '../../components/ui';
-import { Icon } from 'react-native-elements';
+import { Button, Column, Row, Text } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
-import { RefreshControl } from 'react-native';
+import { RefreshControl, Image, View } from 'react-native';
import { useMyVcsTab } from './MyVcsTabController';
import { HomeScreenTabProps } from './HomeScreen';
import { AddVcModal } from './MyVcs/AddVcModal';
import { GetVcModal } from './MyVcs/GetVcModal';
-import { DownloadingVcModal } from './MyVcs/DownloadingVcModal';
-import { OnboardingOverlay } from './OnboardingOverlay';
import { useTranslation } from 'react-i18next';
import { VcItem } from '../../components/VcItem';
import { GET_INDIVIDUAL_ID } from '../../shared/constants';
+import {
+ ErrorMessageOverlay,
+ MessageOverlay,
+} from '../../components/MessageOverlay';
+import { Icon } from 'react-native-elements';
export const MyVcsTab: React.FC = (props) => {
const { t } = useTranslation('MyVcsTab');
const controller = useMyVcsTab(props);
+ const storeErrorTranslationPath = 'errors.savingFailed';
const getId = () => {
controller.DISMISS();
@@ -26,68 +29,112 @@ export const MyVcsTab: React.FC = (props) => {
GET_INDIVIDUAL_ID('');
};
+ {
+ controller.isRequestSuccessful
+ ? setTimeout(() => {
+ controller.DISMISS();
+ }, 6000)
+ : null;
+ }
+
+ const DownloadingVcPopUp: React.FC = () => {
+ return (
+
+
+
+ {t('downloadingYourCard')}
+
+ {
+ controller.DISMISS();
+ clearIndividualId();
+ }}
+ color={Theme.Colors.whiteText}
+ size={19}
+ />
+
+
+ );
+ };
+
return (
-
+ {controller.isRequestSuccessful && }
+
{controller.vcKeys.length > 0 && (
}>
- {controller.vcKeys.map((vcKey, index) => (
-
- ))}
-
-
-
+ {controller.vcKeys.map((vcKey, index) => {
+ if (vcKey.split(':')[4] === 'true') {
+ return (
+
+ );
+ }
+ })}
+ {controller.vcKeys.map((vcKey, index) => {
+ if (vcKey.split(':')[4] === 'false') {
+ return (
+
+ );
+ }
+ })}
+
)}
{controller.vcKeys.length === 0 && (
-
-
- {t('generateVc', { vcLabel: controller.vcLabel.plural })}
+
+
+
+ {t('bringYourDigitalID')}
-
- {t('generateVcDescription', {
- vcLabel: controller.vcLabel.singular,
- })}
+
+ {t('generateVcDescription')}
-
-
-
-
+
)}
@@ -101,18 +148,43 @@ export const MyVcsTab: React.FC = (props) => {
)}
- {controller.isRequestSuccessful && (
-
- )}
+
+
+
+
+
-
+
+
+
);
diff --git a/screens/Home/MyVcsTabController.ts b/screens/Home/MyVcsTabController.ts
index 7aa41a96..ccc91c12 100644
--- a/screens/Home/MyVcsTabController.ts
+++ b/screens/Home/MyVcsTabController.ts
@@ -1,12 +1,16 @@
import { useSelector } from '@xstate/react';
import { useContext } from 'react';
import { ActorRefFrom } from 'xstate';
-import { selectVcLabel } from '../../machines/settings';
+import { selectIsTampered } from '../../machines/store';
import {
selectIsRefreshingMyVcs,
selectMyVcs,
VcEvents,
} from '../../machines/vc';
+import {
+ selectWalletBindingError,
+ selectShowWalletBindingError,
+} from '../../machines/vcItem';
import { vcItemMachine } from '../../machines/vcItem';
import { GlobalContext } from '../../shared/GlobalContext';
import { HomeScreenTabProps } from './HomeScreen';
@@ -17,13 +21,20 @@ import {
selectIsOnboarding,
selectIsRequestSuccessful,
selectGetVcModal,
+ selectIsSavingFailedInIdle,
+ selectIsMinimumStorageLimitReached,
} from './MyVcsTabMachine';
+import {
+ selectShowHardwareKeystoreNotExistsAlert,
+ SettingsEvents,
+} from '../../machines/settings';
export function useMyVcsTab(props: HomeScreenTabProps) {
const service = props.service as ActorRefFrom;
const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
const vcService = appService.children.get('vc');
+ const storeService = appService.children.get('store');
+ const settingsService = appService.children.get('settings');
return {
service,
@@ -31,15 +42,25 @@ export function useMyVcsTab(props: HomeScreenTabProps) {
GetVcModalService: useSelector(service, selectGetVcModal),
vcKeys: useSelector(vcService, selectMyVcs),
- vcLabel: useSelector(settingsService, selectVcLabel),
+ isTampered: useSelector(storeService, selectIsTampered),
isRefreshingVcs: useSelector(vcService, selectIsRefreshingMyVcs),
isRequestSuccessful: useSelector(service, selectIsRequestSuccessful),
isOnboarding: useSelector(service, selectIsOnboarding),
-
+ isSavingFailedInIdle: useSelector(service, selectIsSavingFailedInIdle),
+ walletBindingError: useSelector(service, selectWalletBindingError),
+ isBindingError: useSelector(service, selectShowWalletBindingError),
+ isMinimumStorageLimitReached: useSelector(
+ service,
+ selectIsMinimumStorageLimitReached
+ ),
+ showHardwareKeystoreNotExistsAlert: useSelector(
+ settingsService,
+ selectShowHardwareKeystoreNotExistsAlert
+ ),
DISMISS: () => service.send(MyVcsTabEvents.DISMISS()),
- ADD_VC: () => service.send(MyVcsTabEvents.ADD_VC()),
+ DOWNLOAD_ID: () => service.send(MyVcsTabEvents.ADD_VC()),
GET_VC: () => service.send(MyVcsTabEvents.GET_VC()),
@@ -50,5 +71,10 @@ export function useMyVcsTab(props: HomeScreenTabProps) {
},
ONBOARDING_DONE: () => service.send(MyVcsTabEvents.ONBOARDING_DONE()),
+
+ IS_TAMPERED: () => service.send(MyVcsTabEvents.IS_TAMPERED()),
+
+ ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS: () =>
+ settingsService.send(SettingsEvents.ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS()),
};
}
diff --git a/screens/Home/MyVcsTabMachine.ts b/screens/Home/MyVcsTabMachine.ts
index acd29a37..4532e267 100644
--- a/screens/Home/MyVcsTabMachine.ts
+++ b/screens/Home/MyVcsTabMachine.ts
@@ -17,6 +17,7 @@ import {
} from '../../shared/constants';
import { AddVcModalMachine } from './MyVcs/AddVcModalMachine';
import { GetVcModalMachine } from './MyVcs/GetVcModalMachine';
+import Storage from '../../shared/storage';
const model = createModel(
{
@@ -30,9 +31,13 @@ const model = createModel(
}),
DISMISS: () => ({}),
STORE_RESPONSE: (response?: unknown) => ({ response }),
+ STORE_ERROR: (error: Error) => ({ error }),
ADD_VC: () => ({}),
GET_VC: () => ({}),
+ STORAGE_AVAILABLE: () => ({}),
+ STORAGE_UNAVAILABLE: () => ({}),
ONBOARDING_DONE: () => ({}),
+ IS_TAMPERED: () => ({}),
},
}
);
@@ -43,6 +48,7 @@ type ViewVcEvent = EventFrom;
export const MyVcsTabMachine = model.createMachine(
{
+ /** @xstate-layout N4IgpgJg5mDOIC5QFkCeA1AxrAKgQwCMA6TACzEwGsBLAOygHlaCB7PAJwjqgGUAXPHwCusAMQ8cDAEoBRAPqyeABQYA5HjIDaABgC6iUAAcWsan2otaBkAA9EANgBMAGhCpEAFidEA7PY+O2j4ArPbajo4AjPYAvjGuaFi4hCTkVNxMrBxc9PyCIuKSsgoyymoampH6SCDGpuaW1nYIjgCcABxEwa0AzK32PU492l6tru4Ike2OXT2Rkdrac5GOPq3BcQkY2PjEllmc3KIAggAip3LoAMI61UYmZhZWNc2RrTPTSyPtPtphwR4fONEO12toiNEPO8PD0PFMej52psQIkdil9mxDvRRGoAEIMY5SU4ASVUAHE5Kc1Fo9NY6o9Gi9EG8PoFhh4fn9tACgW5EMFpl1uYEFt1Wj4QsjUcliNQIAAbMAnc6XG60mr0hrPUDNLw+LprAJvcVBJbAhA+Rz2Ig9EXrH5vdrvKXbGVEOWK0ToYkyADqqtudIeWqa-JcfJakT6vh80UR-g50R6LqSu3dCqVZJkOAD6vu9SeoZaayIgN67WCCO6flC5ui-SIf3ssfmXiWPhTaOIADdqGAAO7cLCiEk8ZDEng8QMa4OFpkIJzmwJOoiOJ32VqQysjWLxFGutN4CA5KDDiCWMDu2jdliUS-HY9YZAsCB4eXT-MM7W2fnhA2tI1WhNX4enNDpWlXADNz6ewBXsKNOzdI8T2HUdx0nD9alnRkdWZKNOnaQEKy8SIAmCRE60BSJfA3S1elhYIo13LZUxSZCh0wIhYD4Fh2COCRpHkRQVHUGk7iwgscJ-C1ohtDw23k94phCSigIhCVY2CcJIj8dZEMPY8OK4ni+OxATihkKQpGkTDNTnXCZOtWEFKhKIfmCOtBmojc2gWdp7HaW0Oz3aUDJQzjkKwHghEwTA4FgAAzIR5RHCd0KnPMJK-It5h6AiiIBeCyIoiNImCCJV0Y2MBlhcJK30lIYD4cx6DPC8rxvO8iDJMA+CfF831s7Dv2aVYILLPLKxCcVYPsMC-F8KCo36OCEJCg9Gt6lrT0wVKxwnDLxLsqTRpLCaKyrGba1K9pZLBCUdw8cjejiPdaBfOBrFCwgg0kkbEAAWkcDxzXIxbm2CSHuRg+r1tY4gyAoGh6EyTETzyYR4BnP6iwCSjglXH5-IGFZ7AGJYGr2Zg0e4X7svncjzSdfU5jBNcOVu7oPEp9NFTpkN5yjJYDVgwL-McdleQmKY-2B4Gyf8ALhg2OGuyIXsBw4-n7OkqZrUtH42mBsEvFBJcFh6G14I08V1h6ZNVaQwzWswbWTs8AF-0A4CzQjYiiE+KIVkBWDIh59iXaIfs8EeegADFeO7TAAGkwAmT8BYcrSZme73fhAusdxjMnAvKvw1yRR2wqM7jeNp7H6aznSvaiID8996WEWtbQyrWN5lnKlWWLViOdqISLMGi2L4qS+U3f+hBN31KZIbmeCnAWMZSvKmYfC8XzAqepjw+dsfYDwXt45jxUIHnosnQglfK2iaIom0LfpYr1cNy01ovh0gKJ9wpcQvtwOO19IC8zAHfec-ROiWjhN0YGQQIhS2ZFWGifxHQInkvbIBNdQFX2oDfdWfZBwuxgQ5ACy8KzP3Xm-D+zIYQeEqgxAUPRqwVh5k1baWBKHSWBnWf4NoJagn8mVTm3CtpGWjrHKACd2BJ1TunLKmdpKWjrD4aMawKzQVqo4WGcQgA */
predictableActionArguments: true,
preserveActionOrder: true,
tsTypes: {} as import('./MyVcsTabMachine.typegen').Typegen0,
@@ -64,22 +70,52 @@ export const MyVcsTabMachine = model.createMachine(
},
onboarding: {
on: {
- ADD_VC: {
- target: 'addingVc',
- actions: ['completeOnboarding'],
- },
+ ADD_VC: [
+ {
+ target: 'addVc',
+ actions: ['completeOnboarding'],
+ },
+ ],
ONBOARDING_DONE: {
target: 'idle',
actions: ['completeOnboarding'],
},
},
},
+ addVc: {
+ initial: 'checkStorage',
+ states: {
+ checkStorage: {
+ invoke: {
+ src: 'checkStorageAvailability',
+ onDone: [
+ {
+ cond: 'isMinimumStorageLimitReached',
+ target: 'storageLimitReached',
+ },
+ {
+ target: '#MyVcsTab.addingVc',
+ },
+ ],
+ },
+ },
+ storageLimitReached: {
+ on: {
+ DISMISS: '#idle',
+ },
+ },
+ },
+ },
idle: {
id: 'idle',
on: {
- ADD_VC: 'addingVc',
+ ADD_VC: 'addVc',
VIEW_VC: 'viewingVc',
GET_VC: 'gettingVc',
+ IS_TAMPERED: {
+ target: 'idle',
+ actions: ['resetIsTampered', 'refreshMyVc'],
+ },
},
},
viewingVc: {
@@ -107,6 +143,18 @@ export const MyVcsTabMachine = model.createMachine(
target: 'addVcSuccessful',
actions: ['sendVcAdded'],
},
+ STORE_ERROR: {
+ target: '#MyVcsTab.addingVc.savingFailed',
+ },
+ },
+ },
+ savingFailed: {
+ initial: 'idle',
+ states: {
+ idle: {},
+ },
+ on: {
+ DISMISS: '#idle',
},
},
addVcSuccessful: {
@@ -133,7 +181,23 @@ export const MyVcsTabMachine = model.createMachine(
},
},
{
+ services: {
+ checkStorageAvailability: () => async () => {
+ return Promise.resolve(
+ Storage.isMinimumLimitReached('minStorageRequired')
+ );
+ },
+ },
+
actions: {
+ refreshMyVc: send((_context, event) => VcEvents.REFRESH_MY_VCS(), {
+ to: (context) => context.serviceRefs.vc,
+ }),
+
+ resetIsTampered: send(() => StoreEvents.RESET_IS_TAMPERED(), {
+ to: (context) => context.serviceRefs.store,
+ }),
+
viewVcFromParent: sendParent((_context, event: ViewVcEvent) =>
model.events.VIEW_VC(event.vcItemActor)
),
@@ -170,6 +234,8 @@ export const MyVcsTabMachine = model.createMachine(
isOnboardingDone: (_context, event: StoreResponseEvent) => {
return event.response === true;
},
+
+ isMinimumStorageLimitReached: (_context, event) => Boolean(event.data),
},
}
);
@@ -198,3 +264,11 @@ export function selectIsOnboarding(state: State) {
export function selectIsRequestSuccessful(state: State) {
return state.matches('addingVc.addVcSuccessful');
}
+
+export function selectIsSavingFailedInIdle(state: State) {
+ return state.matches('addingVc.savingFailed.idle');
+}
+
+export function selectIsMinimumStorageLimitReached(state: State) {
+ return state.matches('addVc.storageLimitReached');
+}
diff --git a/screens/Home/MyVcsTabMachine.typegen.ts b/screens/Home/MyVcsTabMachine.typegen.ts
index be0484c4..513aa9ee 100644
--- a/screens/Home/MyVcsTabMachine.typegen.ts
+++ b/screens/Home/MyVcsTabMachine.typegen.ts
@@ -13,30 +13,51 @@ export interface Typegen0 {
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
+ 'done.invoke.MyVcsTab.addVc.checkStorage:invocation[0]': {
+ type: 'done.invoke.MyVcsTab.addVc.checkStorage:invocation[0]';
+ data: unknown;
+ __tip: 'See the XState TS docs to learn how to strongly type this.';
+ };
'xstate.init': { type: 'xstate.init' };
};
- 'invokeSrcNameMap': {};
+ 'invokeSrcNameMap': {
+ checkStorageAvailability: 'done.invoke.MyVcsTab.addVc.checkStorage:invocation[0]';
+ };
'missingImplementations': {
actions: never;
- services: never;
- guards: never;
delays: never;
+ guards: never;
+ services: never;
};
'eventsCausingActions': {
completeOnboarding: 'ADD_VC' | 'ONBOARDING_DONE';
getOnboardingStatus: 'xstate.init';
+ refreshMyVc: 'IS_TAMPERED';
+ resetIsTampered: 'IS_TAMPERED';
sendVcAdded: 'STORE_RESPONSE';
storeVcItem: 'done.invoke.AddVcModal';
viewVcFromParent: 'VIEW_VC';
};
- 'eventsCausingServices': {};
+ 'eventsCausingDelays': {};
'eventsCausingGuards': {
+ isMinimumStorageLimitReached: 'done.invoke.MyVcsTab.addVc.checkStorage:invocation[0]';
isOnboardingDone: 'STORE_RESPONSE';
};
- 'eventsCausingDelays': {};
+ 'eventsCausingServices': {
+ AddVcModal:
+ | 'done.invoke.GetVcModal'
+ | 'done.invoke.MyVcsTab.addVc.checkStorage:invocation[0]';
+ GetVcModal: 'GET_VC';
+ checkStorageAvailability: 'ADD_VC';
+ };
'matchesStates':
+ | 'addVc'
+ | 'addVc.checkStorage'
+ | 'addVc.storageLimitReached'
| 'addingVc'
| 'addingVc.addVcSuccessful'
+ | 'addingVc.savingFailed'
+ | 'addingVc.savingFailed.idle'
| 'addingVc.storing'
| 'addingVc.waitingForvcKey'
| 'checkingOnboardingStatus'
@@ -46,7 +67,13 @@ export interface Typegen0 {
| 'onboarding'
| 'viewingVc'
| {
- addingVc?: 'addVcSuccessful' | 'storing' | 'waitingForvcKey';
+ addVc?: 'checkStorage' | 'storageLimitReached';
+ addingVc?:
+ | 'addVcSuccessful'
+ | 'savingFailed'
+ | 'storing'
+ | 'waitingForvcKey'
+ | { savingFailed?: 'idle' };
gettingVc?: 'waitingForvcKey';
};
'tags': never;
diff --git a/screens/Home/OnboardingOverlay.strings.json b/screens/Home/OnboardingOverlay.strings.json
index ffcec886..7886ce4f 100644
--- a/screens/Home/OnboardingOverlay.strings.json
+++ b/screens/Home/OnboardingOverlay.strings.json
@@ -1,9 +1,9 @@
{
"stepOneTitle": "Welcome!",
- "stepOneText": "Keep your digital credential with you at all times. To get started, add {{vcLabel}} to your profile.",
- "stepTwoTitle": "{{vcLabel}} management",
- "stepTwoText": "Once generated, {{vcLabel}} are safely stored on your mobile and can be renamed or shared at any time.",
+ "stepOneText": "Keep your digital credential with you at all times. To get started, add Cards to your profile.",
+ "stepTwoTitle": "Card management",
+ "stepTwoText": "Once generated, Cards are safely stored on your mobile and can be renamed or shared at any time.",
"stepThreeTitle": "Easy sharing",
- "stepThreeText": "Share and receive {{vcLabel}} switfly using your phone camera to scan QR codes.",
- "stepThreeButton": "Get started and add {{vcLabel}}"
+ "stepThreeText": "Share and receive Cards switfly using your phone camera to scan QR codes.",
+ "stepThreeButton": "Get started and add Card"
}
\ No newline at end of file
diff --git a/screens/Home/OnboardingOverlay.tsx b/screens/Home/OnboardingOverlay.tsx
index 78b97396..78bdc5d8 100644
--- a/screens/Home/OnboardingOverlay.tsx
+++ b/screens/Home/OnboardingOverlay.tsx
@@ -1,43 +1,37 @@
-import React, { useRef, useContext } 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 { useSelector } from '@xstate/react';
-import { GlobalContext } from '../../shared/GlobalContext';
-import { selectVcLabel } from '../../machines/settings';
import { useTranslation } from 'react-i18next';
export const OnboardingOverlay: React.FC = (props) => {
const slider = useRef();
const { t } = useTranslation('OnboardingOverlay');
- const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
- const vcLabel = useSelector(settingsService, selectVcLabel);
const slides = [
{
key: 'one',
title: t('stepOneTitle'),
- text: t('stepOneText', { vcLabel: vcLabel.plural }),
+ text: t('stepOneText'),
},
{
key: 'two',
- title: t('stepTwoTitle', { vcLabel: vcLabel.singular }),
- text: t('stepTwoText', { vcLabel: vcLabel.plural }),
+ title: t('stepTwoTitle'),
+ text: t('stepTwoText'),
},
{
key: 'three',
title: t('stepThreeTitle'),
- text: t('stepThreeText', { vcLabel: vcLabel.plural }),
+ text: t('stepThreeText'),
footer: (
),
diff --git a/screens/Home/ReceivedVcsTab.strings.json b/screens/Home/ReceivedVcsTab.strings.json
index 05b71985..43d01d10 100644
--- a/screens/Home/ReceivedVcsTab.strings.json
+++ b/screens/Home/ReceivedVcsTab.strings.json
@@ -1,4 +1,4 @@
{
- "noReceivedVcsTitle": "No {{vcLabel}} available yet",
- "noReceivedVcsText": "Tap on Request below to receive {{vcLabel}}"
+ "noReceivedVcsTitle": "No Cards available yet",
+ "noReceivedVcsText": "Tap on Request below to receive Card"
}
\ No newline at end of file
diff --git a/screens/Home/ReceivedVcsTab.tsx b/screens/Home/ReceivedVcsTab.tsx
index c9171e5f..b4cc9fee 100644
--- a/screens/Home/ReceivedVcsTab.tsx
+++ b/screens/Home/ReceivedVcsTab.tsx
@@ -29,6 +29,7 @@ export const ReceivedVcsTab: React.FC = (props) => {
vcKey={vcKey}
margin="0 2 8 2"
onPress={controller.VIEW_VC}
+ activeTab={props.service.id}
/>
))}
{controller.vcKeys.length === 0 && (
@@ -40,14 +41,10 @@ export const ReceivedVcsTab: React.FC = (props) => {
name="sentiment-dissatisfied"
/>
- {t('noReceivedVcsTitle', {
- vcLabel: controller.vcLabel.plural,
- })}
+ {t('noReceivedVcsTitle')}
- {t('noReceivedVcsText', {
- vcLabel: controller.vcLabel.singular,
- })}
+ {t('noReceivedVcsText')}
diff --git a/screens/Home/ReceivedVcsTabController.ts b/screens/Home/ReceivedVcsTabController.ts
index d31ea5d9..f5df12fb 100644
--- a/screens/Home/ReceivedVcsTabController.ts
+++ b/screens/Home/ReceivedVcsTabController.ts
@@ -1,33 +1,70 @@
-import { useSelector } from '@xstate/react';
-import { useContext } from 'react';
+import { useSelector, useInterpret } from '@xstate/react';
+import { useContext, useRef, useState } from 'react';
import { ActorRefFrom } from 'xstate';
-import { selectVcLabel } from '../../machines/settings';
import {
+ VcEvents,
selectIsRefreshingReceivedVcs,
selectReceivedVcs,
} from '../../machines/vc';
-import { vcItemMachine } from '../../machines/vcItem';
+import { vcItemMachine } from '../../machines/vcItem';
import { GlobalContext } from '../../shared/GlobalContext';
-import { HomeScreenTabProps } from './HomeScreen';
import {
ReceivedVcsTabEvents,
ReceivedVcsTabMachine,
} from './ReceivedVcsTabMachine';
+import { MyVcsTabEvents, MyVcsTabMachine } from './MyVcsTabMachine';
+import {
+ HomeScreenEvents,
+ HomeScreenMachine,
+ selectSelectedVc,
+ selectTabRefs,
+ selectViewingVc,
+} from './HomeScreenMachine';
+
+export function useReceivedVcsTab() {
+ const [isVisible, setIsVisible] = useState(false);
-export function useReceivedVcsTab(props: HomeScreenTabProps) {
- const service = props.service as ActorRefFrom;
const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
+ const machine = useRef(
+ HomeScreenMachine.withContext({
+ ...HomeScreenMachine.context,
+ serviceRefs: appService.getSnapshot().context.serviceRefs,
+ })
+ );
+ const service = useInterpret(machine.current);
+
+ const tabRefs = useSelector(service, selectTabRefs);
+
+ const selectedVc = useSelector(service, selectSelectedVc);
+
+ const isViewingVc = useSelector(service, selectViewingVc);
+
+ const ReceivedVcsService = tabRefs.receivedVcs as ActorRefFrom<
+ typeof ReceivedVcsTabMachine
+ >;
+ const myVcservice = tabRefs.myVcs as ActorRefFrom;
+
const vcService = appService.children.get('vc');
return {
- vcLabel: useSelector(settingsService, selectVcLabel),
+ isVisible,
vcKeys: useSelector(vcService, selectReceivedVcs),
isRefreshingVcs: useSelector(vcService, selectIsRefreshingReceivedVcs),
- VIEW_VC: (vcItemActor: ActorRefFrom) =>
- service.send(ReceivedVcsTabEvents.VIEW_VC(vcItemActor)),
- REFRESH: () => service.send(ReceivedVcsTabEvents.REFRESH()),
+ TOGGLE_RECEIVED_CARDS: () => setIsVisible(!isVisible),
+
+ VIEW_VC: (vcRef: ActorRefFrom) => {
+ return myVcservice.send(MyVcsTabEvents.VIEW_VC(vcRef));
+ },
+ isViewingVc,
+ selectedVc,
+ activeTab: 1,
+ DISMISS_MODAL: () => service.send(HomeScreenEvents.DISMISS_MODAL()),
+ REVOKE: () => {
+ vcService.send(VcEvents.REFRESH_MY_VCS());
+ service.send(HomeScreenEvents.DISMISS_MODAL());
+ },
+ REFRESH: () => ReceivedVcsService.send(ReceivedVcsTabEvents.REFRESH()),
};
}
diff --git a/screens/Home/ViewVcModal.strings.json b/screens/Home/ViewVcModal.strings.json
index 188ec7d0..6824949b 100644
--- a/screens/Home/ViewVcModal.strings.json
+++ b/screens/Home/ViewVcModal.strings.json
@@ -10,8 +10,8 @@
"editTag": "Rename",
"redirecting": "Redirecting...",
"success": {
- "unlocked": "{{vcLabel}} successfully unlocked",
- "locked": "{{vcLabel}} successfully locked",
+ "unlocked": "Card successfully unlocked",
+ "locked": "Card successfully locked",
"revoked": "VID {{vid}} has been revoked. Any credential containing the same will be removed automatically from the wallet"
}
}
\ No newline at end of file
diff --git a/screens/Home/ViewVcModal.tsx b/screens/Home/ViewVcModal.tsx
index 1f87beeb..c5778d2c 100644
--- a/screens/Home/ViewVcModal.tsx
+++ b/screens/Home/ViewVcModal.tsx
@@ -10,7 +10,7 @@ import { OIDcAuthenticationModal } from '../../components/OIDcAuth';
import { useViewVcModal, ViewVcModalProps } from './ViewVcModalController';
import { useTranslation } from 'react-i18next';
import { VcDetails } from '../../components/VcDetails';
-import { OtpVerification } from './MyVcs/OtpVerification';
+import { OtpVerificationModal } from './MyVcs/OtpVerificationModal';
import { BindingVcWarningOverlay } from './MyVcs/BindingVcWarningOverlay';
export const ViewVcModal: React.FC = (props) => {
@@ -22,12 +22,12 @@ export const ViewVcModal: React.FC = (props) => {
idType: 'VID',
label: t('revoke'),
icon: 'close-circle-outline',
- onPress: () => controller.CONFIRM_REVOKE_VC(),
+ onPress: controller.CONFIRM_REVOKE_VC,
},
{
label: t('editTag'),
icon: 'pencil',
- onPress: () => controller.EDIT_TAG(),
+ onPress: controller.EDIT_TAG,
},
];
@@ -35,32 +35,16 @@ export const ViewVcModal: React.FC = (props) => {
- }>
+ headerTitle={t('title')}
+ headerElevation={2}>
-
- {controller.walletBindingError !== '' && (
-
- Error Occured : {controller.walletBindingError}
-
- )}
{controller.isEditingTag && (
@@ -68,6 +52,7 @@ export const ViewVcModal: React.FC = (props) => {
isVisible={controller.isEditingTag}
label={t('editTag')}
value={controller.vc.tag}
+ maxLength={12}
onDismiss={controller.DISMISS}
onSave={controller.SAVE_TAG}
/>
@@ -85,7 +70,7 @@ export const ViewVcModal: React.FC = (props) => {
)}
{controller.isAcceptingOtpInput && (
- = (props) => {
)}
{controller.isAcceptingBindingOtp && (
- {
if (isLockingVc) {
- showToast(
- vc.locked
- ? t('success.locked', { vcLabel: vcLabel.singular })
- : t('success.unlocked', { vcLabel: vcLabel.singular })
- );
+ showToast(vc.locked ? t('success.locked') : t('success.unlocked'));
}
if (isRevokingVc) {
showToast(t('success.revoked', { vid: vc.id }));
@@ -130,7 +123,7 @@ export function useViewVcModal({
selectIsAcceptingRevokeInput
),
storedPasscode: useSelector(authService, selectPasscode),
- isBindingOtp: useSelector(vcItemActor, selectIsRequestBindingOtp),
+ isBindingOtp: useSelector(vcItemActor, selectRequestBindingOtp),
isAcceptingBindingOtp: useSelector(vcItemActor, selectAcceptingBindingOtp),
walletBindingError: useSelector(vcItemActor, selectWalletBindingError),
isWalletBindingPending: useSelector(
@@ -139,10 +132,10 @@ export function useViewVcModal({
),
isWalletBindingInProgress: useSelector(
vcItemActor,
- isWalletBindingInProgress
+ selectWalletBindingInProgress
),
isBindingError: useSelector(vcItemActor, selectShowWalletBindingError),
- isBindingWarning: useSelector(vcItemActor, isShowingBindingWarning),
+ isBindingWarning: useSelector(vcItemActor, selectBindingWarning),
CONFIRM_REVOKE_VC: () => {
setRevoking(true);
@@ -182,4 +175,5 @@ export interface ViewVcModalProps extends ModalProps {
vcItemActor: ActorRefFrom;
onDismiss: () => void;
onRevokeDelete: () => void;
+ activeTab: Number;
}
diff --git a/screens/MainLayout.strings.json b/screens/MainLayout.strings.json
index 7fd40a57..520b6d86 100644
--- a/screens/MainLayout.strings.json
+++ b/screens/MainLayout.strings.json
@@ -2,5 +2,5 @@
"home": "Home",
"scan": "Scan",
"request": "Request",
- "profile": "Profile"
+ "settings": "Settings"
}
\ No newline at end of file
diff --git a/screens/MainLayout.tsx b/screens/MainLayout.tsx
index 28ab8042..ddbc1674 100644
--- a/screens/MainLayout.tsx
+++ b/screens/MainLayout.tsx
@@ -1,37 +1,78 @@
-import React from 'react';
+import React, { useContext } from 'react';
import {
BottomTabNavigationOptions,
createBottomTabNavigator,
} from '@react-navigation/bottom-tabs';
import { Icon } from 'react-native-elements';
-import { mainRoutes } from '../routes/main';
-import { RootRouteProps } from '../routes';
-import { LanguageSelector } from '../components/LanguageSelector';
+import { RequestRouteProps, RootRouteProps } from '../routes';
+import { mainRoutes, scan } from '../routes/main';
import { Theme } from '../components/ui/styleUtils';
import { useTranslation } from 'react-i18next';
+import { Row } from '../components/ui';
+import { Image } from 'react-native';
+import { SettingScreen } from './Settings/SettingScreen';
+import { HelpScreen } from '../components/HelpScreen';
+import { GlobalContext } from '../shared/GlobalContext';
+import { ScanEvents } from '../machines/bleShare/scan/scanMachine';
const { Navigator, Screen } = createBottomTabNavigator();
-export const MainLayout: React.FC = () => {
+export const MainLayout: React.FC = (
+ props
+) => {
const { t } = useTranslation('MainLayout');
+ const { appService } = useContext(GlobalContext);
+ const scanService = appService.children.get('scan');
const options: BottomTabNavigationOptions = {
- headerLeft: () => ,
- headerLeftContainerStyle: { paddingStart: 16 },
headerRight: () => (
- }
- />
+
+
+ }
+ navigation={undefined}
+ route={undefined}
+ />
+
+
+ }
+ navigation={props.navigation}
+ route={undefined}
+ />
+
),
- headerRightContainerStyle: { paddingEnd: 16 },
- headerTitleAlign: 'center',
- tabBarShowLabel: false,
+ headerTitleStyle: {
+ fontFamily: 'Inter_600SemiBold',
+ fontSize: 30,
+ margin: 4,
+ },
+ headerRightContainerStyle: { paddingEnd: 13 },
+ headerLeftContainerStyle: { paddingEnd: 13 },
+ tabBarShowLabel: true,
+ tabBarActiveTintColor: Theme.Colors.IconBg,
+ tabBarLabelStyle: {
+ fontSize: 12,
+ fontFamily: 'Inter_600SemiBold',
+ },
tabBarStyle: {
- height: 86,
- paddingHorizontal: 36,
+ height: 75,
+ paddingHorizontal: 10,
},
tabBarItemStyle: {
- height: 86,
+ height: 83,
+ padding: 11,
},
};
@@ -42,14 +83,21 @@ export const MainLayout: React.FC = () => {
key={route.name}
name={route.name}
component={route.component}
+ listeners={{
+ tabPress: (e) => {
+ if (route.name == scan.name) {
+ scanService.send(ScanEvents.RESET());
+ }
+ },
+ }}
options={{
...route.options,
- title: t(route.name.toLowerCase()).toUpperCase(),
+ title: t(route.name),
tabBarIcon: ({ focused }) => (
),
}}
diff --git a/screens/PasscodeScreen.tsx b/screens/PasscodeScreen.tsx
index 655996f0..6f33332f 100644
--- a/screens/PasscodeScreen.tsx
+++ b/screens/PasscodeScreen.tsx
@@ -1,30 +1,61 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
-import { Icon } from 'react-native-elements';
+import { Image } from 'react-native';
import { MAX_PIN, PasscodeVerify } from '../components/PasscodeVerify';
import { PinInput } from '../components/PinInput';
import { Column, Text } from '../components/ui';
import { Theme } from '../components/ui/styleUtils';
import { PasscodeRouteProps } from '../routes';
import { usePasscodeScreen } from './PasscodeScreenController';
+import { hashData } from '../shared/commonUtil';
+import { argon2iConfig } from '../shared/constants';
export const PasscodeScreen: React.FC = (props) => {
const { t } = useTranslation('PasscodeScreen');
const controller = usePasscodeScreen(props);
+ const setPasscode = async (passcode: string) => {
+ const data = await hashData(passcode, controller.storedSalt, argon2iConfig);
+ controller.setPasscode(data);
+ };
+
const passcodeSetup =
controller.passcode === '' ? (
- {t('header')}
-
+
+
+ {t('header')}
+
+
+ {t('enterNewPassword')}
+
+
+
+
) : (
- {t('confirmPasscode')}
+
+
+ {t('confirmPasscode')}
+
+
+ {t('reEnterPassword')}
+
+
);
@@ -34,18 +65,25 @@ export const PasscodeScreen: React.FC = (props) => {
fill
padding="32"
backgroundColor={Theme.Colors.whiteBackgroundColor}>
-
+
{props.route.params?.setup ? (
-
+
{passcodeSetup}
) : (
-
- {t('enterPasscode')}
+
+
+ {t('enterPasscode')}
+
)}
diff --git a/screens/PasscodeScreenController.ts b/screens/PasscodeScreenController.ts
index 5a656908..78ab5b54 100644
--- a/screens/PasscodeScreenController.ts
+++ b/screens/PasscodeScreenController.ts
@@ -1,6 +1,11 @@
import { useSelector } from '@xstate/react';
import { useContext, useEffect, useState } from 'react';
-import { AuthEvents, selectAuthorized, selectPasscode } from '../machines/auth';
+import {
+ AuthEvents,
+ selectAuthorized,
+ selectPasscode,
+ selectPasscodeSalt,
+} from '../machines/auth';
import { PasscodeRouteProps } from '../routes';
import { GlobalContext } from '../shared/GlobalContext';
@@ -37,5 +42,7 @@ export function usePasscodeScreen(props: PasscodeRouteProps) {
SETUP_PASSCODE: () => {
authService.send(AuthEvents.SETUP_PASSCODE(passcode));
},
+
+ storedSalt: useSelector(authService, selectPasscodeSalt),
};
}
diff --git a/screens/Profile/ProfileScreen.tsx b/screens/Profile/ProfileScreen.tsx
index d856ff2c..5068fc44 100644
--- a/screens/Profile/ProfileScreen.tsx
+++ b/screens/Profile/ProfileScreen.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { View } from 'react-native';
+import { Platform, View } from 'react-native';
import { getVersion } from 'react-native-device-info';
import { Icon, ListItem, Switch } from 'react-native-elements';
import { Column, Text } from '../../components/ui';
@@ -7,21 +7,27 @@ import { Theme } from '../../components/ui/styleUtils';
import { MainRouteProps } from '../../routes/main';
import { EditableListItem } from '../../components/EditableListItem';
import { MessageOverlay } from '../../components/MessageOverlay';
-import { Credits } from './Credits';
-import { Revoke } from './Revoke';
+import { Revoke } from '../Settings/Revoke';
import { useProfileScreen } from './ProfileScreenController';
import { useTranslation } from 'react-i18next';
import { LanguageSelector } from '../../components/LanguageSelector';
import i18next, { SUPPORTED_LANGUAGES } from '../../i18n';
import { ScrollView } from 'react-native-gesture-handler';
+import { AppMetaData } from '../Settings/AppMetaData';
+import { CREDENTIAL_REGISTRY_EDIT } from 'react-native-dotenv';
const LanguageSetting: React.FC = () => {
const { t } = useTranslation('ProfileScreen');
-
return (
+
{t('language')}
@@ -38,6 +44,7 @@ const LanguageSetting: React.FC = () => {
export const ProfileScreen: React.FC = (props) => {
const { t } = useTranslation('ProfileScreen');
+
const controller = useProfileScreen(props);
return (
@@ -54,13 +61,17 @@ export const ProfileScreen: React.FC = (props) => {
label={t('name')}
value={controller.name}
onEdit={controller.UPDATE_NAME}
- Icon="user"
+ Icon=""
+ credentialRegistryResponse={''}
/>
+ {/* Intentionally hidden using {display='none'} - Refer mosip/inji/issue#607 */}
@@ -70,7 +81,7 @@ export const ProfileScreen: React.FC = (props) => {
name="fingerprint"
type="fontawesome"
size={25}
- style={Theme.Styles.profileIconBg}
+ style={Theme.Styles.IconContainer}
color={Theme.Colors.Icon}
/>
@@ -81,15 +92,23 @@ export const ProfileScreen: React.FC = (props) => {
-
+ {/* Intentionally hidden using {display:'none'} - Refer mosip/inji/issue#607 */}
+
@@ -100,13 +119,25 @@ export const ProfileScreen: React.FC = (props) => {
-
+
+ {CREDENTIAL_REGISTRY_EDIT === 'true' && (
+
+ )}
@@ -115,14 +146,6 @@ export const ProfileScreen: React.FC = (props) => {
-
- {t('version')}: {getVersion()}
-
{controller.backendInfo.application.name !== '' ? (
settingsService.send(SettingsEvents.UPDATE_VC_LABEL(label)),
+ UPDATE_CREDENTIAL_REGISTRY: (credentialRegistry: string) =>
+ settingsService.send(
+ SettingsEvents.UPDATE_CREDENTIAL_REGISTRY(credentialRegistry)
+ ),
+
+ UPDATE_CREDENTIAL_REGISTRY_RESPONSE: (credentialRegistryResponse: string) =>
+ settingsService.send(
+ SettingsEvents.UPDATE_CREDENTIAL_REGISTRY_RESPONSE(
+ credentialRegistryResponse
+ )
+ ),
+
TOGGLE_BIOMETRIC: (enable: boolean) =>
settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(enable)),
diff --git a/screens/QrLogin/MyBindedVcs.tsx b/screens/QrLogin/MyBindedVcs.tsx
index f8ad2e2c..181f3bb9 100644
--- a/screens/QrLogin/MyBindedVcs.tsx
+++ b/screens/QrLogin/MyBindedVcs.tsx
@@ -25,7 +25,7 @@ export const MyBindedVcs: React.FC = (props) => {
{controller.vcKeys.length > 0 && (
-
+ <>
@@ -45,30 +45,30 @@ export const MyBindedVcs: React.FC = (props) => {
))}
-
-
-
-
+
+
+
+ >
)}
{controller.vcKeys.length === 0 && (
- {t('noBindedVc', { vcLabel: controller.vcLabel.plural })}
+ {t('noBindedVc')}
= (props) => {
- {t(claim[0].toUpperCase() + claim.slice(1))}
+ {t(claim[0].toUpperCase() + claim.slice(1))
+ .split('_')
+ .join(' ')}
= (props) => {
- {t(claim[0].toUpperCase() + claim.slice(1))}
+ {t(claim[0].toUpperCase() + claim.slice(1))
+ .split('_')
+ .join(' ')}
diff --git a/screens/QrLogin/QrLogin.tsx b/screens/QrLogin/QrLogin.tsx
index 738a57de..f9ae2eee 100644
--- a/screens/QrLogin/QrLogin.tsx
+++ b/screens/QrLogin/QrLogin.tsx
@@ -10,13 +10,14 @@ import { QrLoginSuccess } from './QrLoginSuccessMessage';
import { QrConsent } from './QrConsent';
import { QrLoginRef } from '../../machines/QrLoginMachine';
import { Icon } from 'react-native-elements';
+import { View } from 'react-native';
export const QrLogin: React.FC = (props) => {
const controller = useQrLogin(props);
const { t } = useTranslation('QrScreen');
return (
- = (props) => {
service={props.service}
/>
-
+
);
};
diff --git a/screens/QrLogin/QrLoginController.ts b/screens/QrLogin/QrLoginController.ts
index 733791a4..dfd4f331 100644
--- a/screens/QrLogin/QrLoginController.ts
+++ b/screens/QrLogin/QrLoginController.ts
@@ -24,7 +24,6 @@ import {
selectIsSendingAuthenticate,
selectEssentialClaims,
} from '../../machines/QrLoginMachine';
-import { selectVcLabel } from '../../machines/settings';
import { selectBindedVcs } from '../../machines/vc';
import { vcItemMachine } from '../../machines/vcItem';
import { GlobalContext } from '../../shared/GlobalContext';
@@ -33,7 +32,6 @@ import { QrLoginProps } from './QrLogin';
export function useQrLogin({ service }: QrLoginProps) {
const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
const vcService = appService.children.get('vc');
const [selectedIndex, setSelectedIndex] = useState(null);
@@ -82,7 +80,6 @@ export function useQrLogin({ service }: QrLoginProps) {
isVerifyingIdentity: useSelector(service, selectIsisVerifyingIdentity),
isInvalidIdentity: useSelector(service, selectIsInvalidIdentity),
isVerifyingSuccesful: useSelector(service, selectIsVerifyingSuccesful),
- vcLabel: useSelector(settingsService, selectVcLabel),
DISMISS: () => service.send(QrLoginEvents.DISMISS()),
SCANNING_DONE: (qrCode: string) =>
diff --git a/screens/Request/ReceiveVcScreen.strings.json b/screens/Request/ReceiveVcScreen.strings.json
index fbce0dd7..d0fe334e 100644
--- a/screens/Request/ReceiveVcScreen.strings.json
+++ b/screens/Request/ReceiveVcScreen.strings.json
@@ -1,6 +1,14 @@
{
- "header": "{{vcLabel}} details",
- "save": "Save {{vcLabel}}",
+ "header": "Card details",
+ "save": "Save Card",
"verifyAndSave": "Verify and save",
- "discard": "Discard"
-}
\ No newline at end of file
+ "reject": "Reject",
+ "discard": "Discard",
+ "goToReceivedVCTab": "View Received Cards",
+ "errors": {
+ "savingFailed": {
+ "title": "Failed to save the Card",
+ "message": "Something went wrong while saving Card to the store."
+ }
+ }
+}
diff --git a/screens/Request/ReceiveVcScreen.tsx b/screens/Request/ReceiveVcScreen.tsx
index ae53c9dd..d1f73e2c 100644
--- a/screens/Request/ReceiveVcScreen.tsx
+++ b/screens/Request/ReceiveVcScreen.tsx
@@ -7,11 +7,19 @@ import { Theme } from '../../components/ui/styleUtils';
import { VcDetails } from '../../components/VcDetails';
import { useReceiveVcScreen } from './ReceiveVcScreenController';
import { VerifyIdentityOverlay } from '../VerifyIdentityOverlay';
-import { MessageOverlay } from '../../components/MessageOverlay';
+import {
+ MessageOverlay,
+ ErrorMessageOverlay,
+} from '../../components/MessageOverlay';
+import { useOverlayVisibleAfterTimeout } from '../../shared/hooks/useOverlayVisibleAfterTimeout';
export const ReceiveVcScreen: React.FC = () => {
const { t } = useTranslation('ReceiveVcScreen');
const controller = useReceiveVcScreen();
+ const savingOverlayVisible = useOverlayVisibleAfterTimeout(
+ controller.isAccepting
+ );
+ const storeErrorTranslationPath = 'errors.savingFailed';
return (
@@ -22,32 +30,19 @@ export const ReceiveVcScreen: React.FC = () => {
- {t('header', { vcLabel: controller.vcLabel.singular })}
+ {t('header')}
-
+
- {controller.incomingVc.shouldVerifyPresence ? (
-
- ) : (
-
- )}
@@ -82,6 +77,18 @@ export const ReceiveVcScreen: React.FC = () => {
/>
+
+
+
);
};
diff --git a/screens/Request/ReceiveVcScreenController.ts b/screens/Request/ReceiveVcScreenController.ts
index f815b60f..7a11a091 100644
--- a/screens/Request/ReceiveVcScreenController.ts
+++ b/screens/Request/ReceiveVcScreenController.ts
@@ -1,27 +1,35 @@
import { useSelector } from '@xstate/react';
import { useContext } from 'react';
+import { GlobalContext } from '../../shared/GlobalContext';
import {
- RequestEvents,
selectIncomingVc,
+ selectIsAccepting,
selectIsIncomingVp,
+ selectIsReviewingInIdle,
+ selectIsSavingFailedInIdle,
+ selectSenderInfo,
+} from '../../machines/bleShare/request/selectors';
+import {
selectIsInvalidIdentity,
selectIsVerifyingIdentity,
- selectSenderInfo,
-} from '../../machines/request';
-import { selectVcLabel } from '../../machines/settings';
-import { GlobalContext } from '../../shared/GlobalContext';
+} from '../../machines/bleShare/commonSelectors';
+import { RequestEvents } from '../../machines/bleShare/request/requestMachine';
export function useReceiveVcScreen() {
const { appService } = useContext(GlobalContext);
const requestService = appService.children.get('request');
- const settingsService = appService.children.get('settings');
return {
senderInfo: useSelector(requestService, selectSenderInfo),
incomingVc: useSelector(requestService, selectIncomingVc),
- vcLabel: useSelector(settingsService, selectVcLabel),
isIncomingVp: useSelector(requestService, selectIsIncomingVp),
+ isReviewingInIdle: useSelector(requestService, selectIsReviewingInIdle),
+ isAccepting: useSelector(requestService, selectIsAccepting),
+ IsSavingFailedInIdle: useSelector(
+ requestService,
+ selectIsSavingFailedInIdle
+ ),
isVerifyingIdentity: useSelector(requestService, selectIsVerifyingIdentity),
isInvalidIdentity: useSelector(requestService, selectIsInvalidIdentity),
@@ -29,6 +37,8 @@ export function useReceiveVcScreen() {
ACCEPT_AND_VERIFY: () =>
requestService.send(RequestEvents.ACCEPT_AND_VERIFY()),
REJECT: () => requestService.send(RequestEvents.REJECT()),
+ GO_TO_RECEIVED_VC_TAB: () =>
+ requestService.send(RequestEvents.GO_TO_RECEIVED_VC_TAB()),
RETRY_VERIFICATION: () =>
requestService.send(RequestEvents.RETRY_VERIFICATION()),
CANCEL: () => requestService.send(RequestEvents.CANCEL()),
diff --git a/screens/Request/RequestLayout.tsx b/screens/Request/RequestLayout.tsx
index 6dc9229a..ad9cd3fd 100644
--- a/screens/Request/RequestLayout.tsx
+++ b/screens/Request/RequestLayout.tsx
@@ -1,15 +1,12 @@
import React from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
-import { Icon } from 'react-native-elements';
import { useTranslation } from 'react-i18next';
-
+import { HeaderBackButton } from '@react-navigation/elements';
import { RequestScreen } from './RequestScreen';
import { useRequestLayout } from './RequestLayoutController';
import { Message } from '../../components/Message';
import { ReceiveVcScreen } from './ReceiveVcScreen';
-import { LanguageSelector } from '../../components/LanguageSelector';
-import { Theme } from '../../components/ui/styleUtils';
-import { I18nManager, Platform } from 'react-native';
+import { MessageOverlay } from '../../components/MessageOverlay';
const RequestStack = createNativeStackNavigator();
@@ -21,34 +18,30 @@ export const RequestLayout: React.FC = () => {
{
+ if (controller.IsSavingFailedInViewingVc || controller.isAccepted) {
+ controller.RESET();
+ }
+ },
+ }}
screenOptions={{
headerTitleAlign: 'center',
headerShadowVisible: false,
- headerRight: () =>
- I18nManager.isRTL && Platform.OS !== 'ios' ? null : (
-
- }
- />
- ),
- headerLeft: () =>
- I18nManager.isRTL && Platform.OS !== 'ios' ? (
-
- }
- />
- ) : null,
}}>
{!controller.isDone && (
(
+ {
+ controller.RESET();
+ }}
+ />
+ ),
}}
/>
)}
@@ -56,7 +49,7 @@ export const RequestLayout: React.FC = () => {
name="RequestScreen"
component={RequestScreen}
options={{
- title: t('request').toUpperCase(),
+ title: t('receiveCard').toUpperCase(),
}}
/>
@@ -64,10 +57,7 @@ export const RequestLayout: React.FC = () => {
{controller.isAccepted && (
)}
@@ -75,10 +65,7 @@ export const RequestLayout: React.FC = () => {
{controller.isRejected && (
)}
@@ -90,6 +77,21 @@ export const RequestLayout: React.FC = () => {
onBackdropPress={controller.DISMISS}
/>
)}
+
+ {controller.isBleError && (
+
+ )}
);
};
diff --git a/screens/Request/RequestLayoutController.ts b/screens/Request/RequestLayoutController.ts
index 05a33d44..1d5c6d70 100644
--- a/screens/Request/RequestLayoutController.ts
+++ b/screens/Request/RequestLayoutController.ts
@@ -1,21 +1,27 @@
import { NavigationProp, useNavigation } from '@react-navigation/native';
import { useSelector } from '@xstate/react';
import { useContext, useEffect } from 'react';
-import {
- RequestEvents,
- selectIsAccepted,
- selectIsDisconnected,
- selectIsDone,
- selectIsRejected,
- selectIsReviewing,
- selectIsWaitingForConnection,
- selectSenderInfo,
-} from '../../machines/request';
-import { selectVcLabel } from '../../machines/settings';
+
import { MainBottomTabParamList } from '../../routes/main';
import { GlobalContext } from '../../shared/GlobalContext';
+import {
+ selectIsSavingFailedInViewingVc,
+ selectIsWaitingForConnection,
+ selectSenderInfo,
+ selectIsDone,
+} from '../../machines/bleShare/request/selectors';
+import {
+ selectIsAccepted,
+ selectIsDisconnected,
+ selectIsHandlingBleError,
+ selectIsRejected,
+ selectIsReviewing,
+ selectBleError,
+} from '../../machines/bleShare/commonSelectors';
+import { RequestEvents } from '../../machines/bleShare/request/requestMachine';
-type RequestStackParamList = {
+export type RequestStackParamList = {
+ Request: undefined;
RequestScreen: undefined;
ReceiveVcScreen: undefined;
};
@@ -26,7 +32,6 @@ type RequestLayoutNavigation = NavigationProp<
export function useRequestLayout() {
const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
const requestService = appService.children.get('request');
const navigation = useNavigation();
@@ -53,24 +58,31 @@ export function useRequestLayout() {
);
useEffect(() => {
if (isDone) {
- navigation.navigate('Home', { activeTab: 1 });
+ navigation.navigate('History');
} else if (isReviewing) {
navigation.navigate('ReceiveVcScreen');
} else if (isWaitingForConnection) {
navigation.navigate('RequestScreen');
}
- }, [isDone, isReviewing]);
+ }, [isDone, isReviewing, isWaitingForConnection]);
return {
- vcLabel: useSelector(settingsService, selectVcLabel),
senderInfo: useSelector(requestService, selectSenderInfo),
isAccepted: useSelector(requestService, selectIsAccepted),
isRejected: useSelector(requestService, selectIsRejected),
isDisconnected: useSelector(requestService, selectIsDisconnected),
+ isBleError: useSelector(requestService, selectIsHandlingBleError),
+ bleError: useSelector(requestService, selectBleError),
+
+ IsSavingFailedInViewingVc: useSelector(
+ requestService,
+ selectIsSavingFailedInViewingVc
+ ),
isReviewing,
isDone,
DISMISS: () => requestService.send(RequestEvents.DISMISS()),
+ RESET: () => requestService.send(RequestEvents.RESET()),
};
}
diff --git a/screens/Request/RequestScreen.strings.json b/screens/Request/RequestScreen.strings.json
index 8ea85705..5fd78698 100644
--- a/screens/Request/RequestScreen.strings.json
+++ b/screens/Request/RequestScreen.strings.json
@@ -1,16 +1,29 @@
{
- "bluetoothDenied": "Please enable Bluetooth to be able to request {{vcLabel}}",
- "showQrCode": "Show this QR code to request {{vcLabel}}",
- "incomingVc": "Incoming {{vcLabel}}",
+ "bluetoothDenied": "Please enable Bluetooth to be able to request Card",
+ "bluetoothStateIos": "Bluetooth is turned OFF, please turn it ON from Control center",
+ "bluetoothStateAndroid": "Bluetooth is turned OFF, please turn it ON from Quick settings menu",
+ "nearbyDevicesPermissionDenied": "Please enable Nearby Devices Permission to be able to request card",
+ "showQrCode": "Display this QR code to request resident Card",
+ "incomingVc": "Incoming Card",
"request": "Request",
+ "errors": {
+ "nearbyDevicesPermissionDenied": {
+ "message": "Nearby Devices permission is required to be able to request Card",
+ "button": "Allow Permission"
+ },
+ "storageLimitReached": {
+ "title": "Insufficient Appdata",
+ "message": "You cannot add or receive cards since the Appdata is full"
+ }
+ },
"status": {
"accepted": {
"title": "Success!",
- "message": "{{vcLabel}} has been successfully received from {{sender}}"
+ "message": "Card has been successfully received from Wallet"
},
"rejected": {
"title": "Notice",
- "message": "You discarded {{sender}}'s {{vcLabel}}"
+ "message": "You discarded Wallet's Card"
},
"disconnected": {
"title": "Disconnected",
@@ -22,14 +35,18 @@
"timeoutHint": "It's taking too long to exchange device info..."
},
"connected": {
- "message": "Connected to the device. Waiting for {{vcLabel}}...",
+ "message": "Connected to the device. Waiting for Card...",
"timeoutHint": "No data received yet. Is sending device still connected?"
},
"offline": {
"message": "Please connect to the internet to enable Online sharing mode"
+ },
+ "bleError": {
+ "title": "Failed to transfer",
+ "message": "Something went wrong while transferring Card. Please try again."
}
},
"online": "Online",
"offline": "Offline",
"gotoSettings": "Go to settings"
-}
\ No newline at end of file
+}
diff --git a/screens/Request/RequestScreen.tsx b/screens/Request/RequestScreen.tsx
index 08922512..7a4fbade 100644
--- a/screens/Request/RequestScreen.tsx
+++ b/screens/Request/RequestScreen.tsx
@@ -1,77 +1,135 @@
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import { TFunction, useTranslation } from 'react-i18next';
-import { Switch } from 'react-native-elements';
-import { I18nManager, Platform } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
-import { Centered, Button, Row, Column, Text } from '../../components/ui';
+import { Centered, Button, Column, Text } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import { useRequestScreen } from './RequestScreenController';
+import BluetoothStateManager from 'react-native-bluetooth-state-manager';
+import { Platform } from 'react-native';
+import Storage from '../../shared/storage';
+import { ErrorMessageOverlay } from '../../components/MessageOverlay';
+import {
+ NavigationProp,
+ useFocusEffect,
+ useNavigation,
+} from '@react-navigation/native';
+import { MainBottomTabParamList } from '../../routes/main';
+
+type RequestStackParamList = {
+ RequestScreen: undefined;
+ ReceiveVcScreen: undefined;
+};
+
+type RequestLayoutNavigation = NavigationProp<
+ RequestStackParamList & MainBottomTabParamList
+>;
export const RequestScreen: React.FC = () => {
const { t } = useTranslation('RequestScreen');
const controller = useRequestScreen();
const props: RequestScreenProps = { t, controller };
+ const [isBluetoothOn, setIsBluetoothOn] = useState(false);
+ const navigation = useNavigation();
+
+ useEffect(() => {
+ (async () => {
+ await BluetoothStateManager.onStateChange((state) => {
+ if (state === 'PoweredOff') {
+ setIsBluetoothOn(false);
+ } else {
+ setIsBluetoothOn(true);
+ }
+ }, true);
+ })();
+ }, [isBluetoothOn]);
return (
- {controller.isBluetoothDenied && }
+ {loadQRCode()}
+ {controller.isMinimumStorageLimitReached && (
+ {
+ navigation.navigate('Home');
+ }}
+ translationPath="RequestScreen"
+ />
+ )}
+
+ );
- {!controller.isCheckingBluetoothService &&
- !controller.isBluetoothDenied ? (
+ function loadQRCode() {
+ if (controller.isNearByDevicesPermissionDenied) {
+ return ;
+ }
+ if (
+ (controller.isBluetoothDenied || !isBluetoothOn) &&
+ controller.isReadyForBluetoothStateCheck
+ ) {
+ return ;
+ }
+ if (
+ !controller.isCheckingBluetoothService &&
+ !controller.isBluetoothDenied
+ ) {
+ return (
{controller.isWaitingForConnection && }
- ) : null}
-
+ );
+ }
+ }
+};
+
+const BluetoothPrompt: React.FC = ({ t }) => {
+ return (
+
+
+ {t(
+ Platform.OS === 'ios' ? 'bluetoothStateIos' : 'bluetoothStateAndroid'
+ )}
+
+
);
};
-const BluetoothPrompt: React.FC = ({ t, controller }) => {
+const NearByPrompt: React.FC = ({ t, controller }) => {
return (
-
-
- {t('bluetoothDenied', { vcLabel: controller.vcLabel.singular })}
-
+
+
+
+ {t('errors.nearbyDevicesPermissionDenied.message')}
+
+
-
+
);
};
const SharingQR: React.FC = ({ t, controller }) => {
return (
-
- {t('showQrCode', { vcLabel: controller.vcLabel.singular })}
-
+ {t('showQrCode')}
- {controller.connectionParams !== '' ? (
+ {controller.openId4VpUri !== '' ? (
) : null}
-
-
- {t('offline')}
-
- {t('online')}
-
);
};
diff --git a/screens/Request/RequestScreenController.ts b/screens/Request/RequestScreenController.ts
index 3c4e1969..4da295b1 100644
--- a/screens/Request/RequestScreenController.ts
+++ b/screens/Request/RequestScreenController.ts
@@ -1,40 +1,52 @@
import { useSelector } from '@xstate/react';
import { useContext, useEffect } from 'react';
import { selectIsActive, selectIsFocused } from '../../machines/app';
-import {
- RequestEvents,
- selectIsBluetoothDenied,
- selectConnectionParams,
- selectIsReviewing,
- selectSenderInfo,
- selectIsWaitingForConnection,
- selectIsExchangingDeviceInfo,
- selectIsWaitingForVc,
- selectSharingProtocol,
- selectIsExchangingDeviceInfoTimeout,
- selectIsWaitingForVcTimeout,
- selectIsCheckingBluetoothService,
- selectIsCancelling,
- selectIsOffline,
-} from '../../machines/request';
-import { selectVcLabel } from '../../machines/settings';
import { GlobalContext } from '../../shared/GlobalContext';
import BluetoothStateManager from 'react-native-bluetooth-state-manager';
import { useTranslation } from 'react-i18next';
+import {
+ selectIsCheckingBluetoothService,
+ selectIsWaitingForConnection,
+ selectIsWaitingForVc,
+ selectIsWaitingForVcTimeout,
+ selectOpenId4VpUri,
+ selectSenderInfo,
+ selectSharingProtocol,
+} from '../../machines/bleShare/request/selectors';
+import {
+ selectIsBluetoothDenied,
+ selectIsCancelling,
+ selectIsExchangingDeviceInfo,
+ selectIsExchangingDeviceInfoTimeout,
+ selectIsNearByDevicesPermissionDenied,
+ selectIsOffline,
+ selectIsReviewing,
+ selectReadyForBluetoothStateCheck,
+} from '../../machines/bleShare/commonSelectors';
+import {
+ RequestEvents,
+ selectIsMinimumStorageLimitReached,
+} from '../../machines/bleShare/request/requestMachine';
export function useRequestScreen() {
const { t } = useTranslation('RequestScreen');
const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
- const vcLabel = useSelector(settingsService, selectVcLabel);
const requestService = appService.children.get('request');
const isActive = useSelector(appService, selectIsActive);
const isFocused = useSelector(appService, selectIsFocused);
+ const isReadyForBluetoothStateCheck = useSelector(
+ requestService,
+ selectReadyForBluetoothStateCheck
+ );
const isBluetoothDenied = useSelector(
requestService,
selectIsBluetoothDenied
);
+ const isNearByDevicesPermissionDenied = useSelector(
+ requestService,
+ selectIsNearByDevicesPermissionDenied
+ );
const isWaitingForConnection = useSelector(
requestService,
selectIsWaitingForConnection
@@ -68,13 +80,9 @@ export function useRequestScreen() {
statusHint = t('status.exchangingDeviceInfo.timeoutHint');
isStatusCancellable = true;
} else if (isWaitingForVc) {
- statusMessage = t('status.connected.message', {
- vcLabel: vcLabel.singular,
- });
+ statusMessage = t('status.connected.message');
} else if (isWaitingForVcTimeout) {
- statusMessage = t('status.connected.message', {
- vcLabel: vcLabel.singular,
- });
+ statusMessage = t('status.connected.message');
statusHint = t('status.connected.timeoutHint');
isStatusCancellable = true;
}
@@ -88,7 +96,6 @@ export function useRequestScreen() {
}, [isFocused, isActive]);
return {
- vcLabel,
statusMessage,
statusHint,
sharingProtocol: useSelector(requestService, selectSharingProtocol),
@@ -99,11 +106,17 @@ export function useRequestScreen() {
isStatusCancellable,
isWaitingForVc,
isBluetoothDenied,
+ isNearByDevicesPermissionDenied,
+ isReadyForBluetoothStateCheck,
isCheckingBluetoothService: useSelector(
requestService,
selectIsCheckingBluetoothService
),
- connectionParams: useSelector(requestService, selectConnectionParams),
+ isMinimumStorageLimitReached: useSelector(
+ requestService,
+ selectIsMinimumStorageLimitReached
+ ),
+ openId4VpUri: useSelector(requestService, selectOpenId4VpUri),
senderInfo: useSelector(requestService, selectSenderInfo),
isReviewing: useSelector(requestService, selectIsReviewing),
isCancelling: useSelector(requestService, selectIsCancelling),
@@ -113,8 +126,6 @@ export function useRequestScreen() {
ACCEPT: () => requestService.send(RequestEvents.ACCEPT()),
REJECT: () => requestService.send(RequestEvents.REJECT()),
REQUEST: () => requestService.send(RequestEvents.SCREEN_FOCUS()),
- SWITCH_PROTOCOL: (value: boolean) =>
- requestService.send(RequestEvents.SWITCH_PROTOCOL(value)),
GOTO_SETTINGS: () => requestService.send(RequestEvents.GOTO_SETTINGS()),
};
}
diff --git a/screens/Scan/ScanLayout.tsx b/screens/Scan/ScanLayout.tsx
index 1502e7ab..e2b84166 100644
--- a/screens/Scan/ScanLayout.tsx
+++ b/screens/Scan/ScanLayout.tsx
@@ -1,16 +1,11 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
-import { Icon } from 'react-native-elements';
-
-import { Theme } from '../../components/ui/styleUtils';
import { SendVcScreen } from './SendVcScreen';
-import { MessageOverlay } from '../../components/MessageOverlay';
import { useScanLayout } from './ScanLayoutController';
-import { LanguageSelector } from '../../components/LanguageSelector';
import { ScanScreen } from './ScanScreen';
-import { I18nManager, Platform } from 'react-native';
-import { Message } from '../../components/Message';
+import { ProgressingModal } from '../../components/ProgressingModal';
+import { MessageOverlay } from '../../components/MessageOverlay';
const ScanStack = createNativeStackNavigator();
@@ -20,35 +15,14 @@ export const ScanLayout: React.FC = () => {
return (
-
- I18nManager.isRTL && Platform.OS !== 'ios' ? null : (
-
- }
- />
- ),
- headerLeft: () =>
- I18nManager.isRTL && Platform.OS !== 'ios' ? (
-
- }
- />
- ) : null,
- }}>
+
{!controller.isDone && (
)}
@@ -56,23 +30,26 @@ export const ScanLayout: React.FC = () => {
name="ScanScreen"
component={ScanScreen}
options={{
- title: t('MainLayout:scan').toUpperCase(),
+ headerTitleStyle: { fontSize: 30, fontFamily: 'Inter_600SemiBold' },
+ title: t('MainLayout:scan'),
}}
/>
-
{controller.isDisconnected && (
- ();
const isLocationDisabled = useSelector(scanService, selectIsLocationDisabled);
const isLocationDenied = useSelector(scanService, selectIsLocationDenied);
+ const isBleError = useSelector(scanService, selectIsHandlingBleError);
+ const bleError = useSelector(scanService, selectBleError);
const locationError = { message: '', button: '' };
@@ -86,21 +90,26 @@ export function useScanLayout() {
const isSendingVc = useSelector(scanService, selectIsSendingVc);
const isSendingVcTimeout = useSelector(scanService, selectIsSendingVcTimeout);
- const vcLabel = useSelector(settingsService, selectVcLabel);
-
const onCancel = () => scanService.send(ScanEvents.CANCEL());
let statusOverlay: Pick<
MessageOverlayProps,
- 'title' | 'message' | 'hint' | 'onCancel' | 'progress' | 'onBackdropPress'
+ | 'title'
+ | 'message'
+ | 'hint'
+ | 'onCancel'
+ | 'progress'
+ | 'onBackdropPress'
+ | 'requester'
> = null;
if (isConnecting) {
statusOverlay = {
- message: t('status.connecting'),
+ title: t('status.inProgress'),
+ message: t('status.establishingConnection'),
progress: true,
};
} else if (isConnectingTimeout) {
statusOverlay = {
- message: t('status.connecting'),
+ title: t('status.sharingInProgress'),
hint: t('status.connectingTimeout'),
onCancel,
progress: true,
@@ -114,13 +123,15 @@ export function useScanLayout() {
statusOverlay = {
message: t('status.exchangingDeviceInfo'),
hint: t('status.exchangingDeviceInfoTimeout'),
- onCancel,
+ onCancel: CANCEL,
progress: true,
};
} else if (isSent) {
statusOverlay = {
- message: t('status.sent', { vcLabel: vcLabel.singular }),
- hint: t('status.sentHint', { vcLabel: vcLabel.singular }),
+ message: t('status.sent'),
+ hint: t('status.sentHint'),
+ progress: false,
+ onCancel: CANCEL,
};
} else if (isSendingVc) {
statusOverlay = {
@@ -138,19 +149,13 @@ export function useScanLayout() {
} else if (isAccepted) {
statusOverlay = {
title: t('status.accepted.title'),
- message: t('status.accepted.message', {
- vcLabel: vcLabel.singular,
- receiver: receiverInfo.deviceName,
- }),
- onBackdropPress: DISMISS,
+ message: t('status.accepted.message'),
+ onCancel: DISMISS,
};
} else if (isRejected) {
statusOverlay = {
title: t('status.rejected.title'),
- message: t('status.rejected.message', {
- vcLabel: vcLabel.singular,
- receiver: receiverInfo.deviceName,
- }),
+ message: t('status.rejected.message'),
onBackdropPress: DISMISS,
};
} else if (isInvalid) {
@@ -163,6 +168,17 @@ export function useScanLayout() {
message: t('status.offline'),
onBackdropPress: DISMISS,
};
+ } else if (isBleError) {
+ statusOverlay = {
+ title: t('status.bleError.title'),
+ message: t('status.bleError.message'),
+ hint:
+ bleError.code &&
+ t('status.bleError.hint', {
+ code: bleError.code,
+ }),
+ onBackdropPress: DISMISS,
+ };
}
useEffect(() => {
@@ -187,24 +203,21 @@ export function useScanLayout() {
useEffect(() => {
if (isDone) {
- navigation.navigate('Home', { activeTab: 0 });
+ navigation.navigate('home', { activeTab: 0 });
} else if (isReviewing) {
navigation.navigate('SendVcScreen');
} else if (isScanning) {
navigation.navigate('ScanScreen');
} else if (isQrLoginDone) {
- navigation.navigate('Home', { activeTab: 2 });
+ navigation.navigate('History');
}
- }, [isDone, isReviewing, isScanning, isQrLoginDone]);
+ }, [isDone, isReviewing, isScanning, isQrLoginDone, isBleError]);
return {
- vcLabel,
-
isInvalid,
isDone,
isDisconnected: useSelector(scanService, selectIsDisconnected),
statusOverlay,
-
DISMISS,
};
}
diff --git a/screens/Scan/ScanScreen.strings.json b/screens/Scan/ScanScreen.strings.json
index 5c3ca0bb..91316466 100644
--- a/screens/Scan/ScanScreen.strings.json
+++ b/screens/Scan/ScanScreen.strings.json
@@ -1,7 +1,9 @@
{
"header": "Scan QR Code",
- "noShareableVcs": "No shareable {{vcLabel}} are available.",
- "sharingVc": "Sharing {{vcLabel}}",
+ "noShareableVcs": "No shareable Cards are available.",
+ "sharingVc": "Sharing Card",
+ "BluetoothStateIos": "Bluetooth is turned OFF, please turn it ON from Control center",
+ "BluetoothStateAndroid": "Bluetooth is turned OFF, please turn it ON from Quick settings menu",
"errors": {
"locationDisabled": {
"message": "Location services must be enabled for the scanning functionality",
@@ -10,6 +12,10 @@
"locationDenied": {
"message": "Location permission is required for the scanning functionality",
"button": "Allow access to location"
+ },
+ "storageLimitReached": {
+ "title": "Insufficient Appdata",
+ "message": "You cannot share cards since the Appdata is full. Clear Appdata to proceed."
}
},
"status": {
@@ -28,11 +34,15 @@
},
"accepted": {
"title": "Success!",
- "message": "Your {{vcLabel}} has been successfully shared with {{receiver}}"
+ "message": "Your Card has been successfully shared with Verifier"
},
"rejected": {
"title": "Notice",
- "message": "Your {{vcLabel}} was discarded by {{receiver}}"
+ "message": "Your Card was discarded by Verifier"
+ },
+ "bleError": {
+ "title": "Failed to transfer",
+ "message": "Something went wrong while transferring Card. Please try again."
}
}
-}
\ No newline at end of file
+}
diff --git a/screens/Scan/ScanScreen.tsx b/screens/Scan/ScanScreen.tsx
index 81b129c4..88f28e21 100644
--- a/screens/Scan/ScanScreen.tsx
+++ b/screens/Scan/ScanScreen.tsx
@@ -1,53 +1,171 @@
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { MessageOverlay } from '../../components/MessageOverlay';
+import {
+ ErrorMessageOverlay,
+ MessageOverlay,
+} from '../../components/MessageOverlay';
import { QrScanner } from '../../components/QrScanner';
import { Button, Centered, Column, Text } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import { QrLogin } from '../QrLogin/QrLogin';
import { useScanScreen } from './ScanScreenController';
+import BluetoothStateManager from 'react-native-bluetooth-state-manager';
+import { Linking, Platform } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
export const ScanScreen: React.FC = () => {
const { t } = useTranslation('ScanScreen');
const controller = useScanScreen();
+ const navigation = useNavigation();
+ const [isBluetoothOn, setIsBluetoothOn] = useState(false);
+
+ useEffect(() => {
+ (async () => {
+ await BluetoothStateManager.onStateChange((state) => {
+ if (state === 'PoweredOff') {
+ setIsBluetoothOn(false);
+ } else {
+ setIsBluetoothOn(true);
+ }
+ }, true);
+ })();
+ }, [isBluetoothOn]);
+
+ // TODO(kludge): skip running this hook on every render
+ useEffect(() => {
+ if (controller.isStartPermissionCheck && !controller.isEmpty)
+ controller.START_PERMISSION_CHECK();
+ });
+
+ const openSettings = () => {
+ Linking.openSettings();
+ };
+
+ function noShareableVcText() {
+ return (
+
+ {t('noShareableVcs')}
+
+ );
+ }
+
+ function bluetoothIsOffText() {
+ return (
+
+ {t(
+ Platform.OS === 'ios' ? 'bluetoothStateIos' : 'bluetoothStateAndroid'
+ )}
+
+ );
+ }
+
+ function allowBluetoothPermissionComponent() {
+ return (
+
+
+
+ {t('enableBluetoothMessage')}
+
+
+
+
+
+ );
+ }
+
+ function allowNearbyDevicesPermissionComponent() {
+ return (
+
+
+
+ {t('errors.nearbyDevicesPermissionDenied.message')}
+
+
+
+
+
+ );
+ }
+
+ function allowLocationComponent() {
+ return (
+
+
+
+ {controller.locationError.message}
+
+
+
+
+
+ );
+ }
+
+ function qrScannerComponent() {
+ return (
+
+
+
+ );
+ }
+
+ function loadQRScanner() {
+ if (controller.isEmpty) {
+ return noShareableVcText();
+ }
+ if (controller.isNearByDevicesPermissionDenied) {
+ return allowNearbyDevicesPermissionComponent();
+ }
+ if (
+ (controller.isBluetoothDenied || !isBluetoothOn) &&
+ controller.isReadyForBluetoothStateCheck
+ ) {
+ return bluetoothIsOffText();
+ }
+ if (controller.isLocationDisabled || controller.isLocationDenied) {
+ return allowLocationComponent();
+ }
+
+ if (controller.isBluetoothPermissionDenied) {
+ return allowBluetoothPermissionComponent();
+ }
+ if (controller.isScanning) {
+ return qrScannerComponent();
+ }
+ }
+
+ function displayStorageLimitReachedError(): React.ReactNode {
+ return (
+ !controller.isEmpty && (
+ navigation.navigate('Home')}
+ />
+ )
+ );
+ }
return (
+ backgroundColor={Theme.Colors.whiteBackgroundColor}>
- {t('header')}
-
- {controller.isLocationDisabled || controller.isLocationDenied ? (
-
-
- {controller.locationError.message}
-
-
-
- ) : null}
-
- {!controller.isEmpty ? (
- controller.isScanning && (
-
-
-
- )
- ) : (
-
- {t('noShareableVcs', { vcLabel: controller.vcLabel.plural })}
-
- )}
+ backgroundColor={Theme.Colors.whiteBackgroundColor}>
+ {loadQRScanner()}
{controller.isQrLogin && (
{
progress
/>
+ {displayStorageLimitReachedError()}
);
};
diff --git a/screens/Scan/ScanScreenController.ts b/screens/Scan/ScanScreenController.ts
index e0e8921c..e7ca9b3c 100644
--- a/screens/Scan/ScanScreenController.ts
+++ b/screens/Scan/ScanScreenController.ts
@@ -2,32 +2,60 @@ import { useSelector } from '@xstate/react';
import { useContext } from 'react';
import { useTranslation } from 'react-i18next';
+import { selectShareableVcs } from '../../machines/vc';
+import { GlobalContext } from '../../shared/GlobalContext';
import {
- ScanEvents,
- selectIsLocationDisabled,
selectIsLocationDenied,
+ selectIsLocationDisabled,
+ selectIsQrLoginStoring,
selectIsScanning,
selectIsShowQrLogin,
selectQrLoginRef,
- selectIsQrLoginStoring,
-} from '../../machines/scan';
-import { selectVcLabel } from '../../machines/settings';
-import { selectShareableVcs } from '../../machines/vc';
-import { GlobalContext } from '../../shared/GlobalContext';
+} from '../../machines/bleShare/scan/selectors';
+import {
+ selectIsBluetoothDenied,
+ selectIsNearByDevicesPermissionDenied,
+ selectReadyForBluetoothStateCheck,
+ selectIsBluetoothPermissionDenied,
+ selectIsStartPermissionCheck,
+} from '../../machines/bleShare/commonSelectors';
+import {
+ ScanEvents,
+ selectIsMinimumStorageRequiredForAuditEntryLimitReached,
+} from '../../machines/bleShare/scan/scanMachine';
export function useScanScreen() {
const { t } = useTranslation('ScanScreen');
const { appService } = useContext(GlobalContext);
const scanService = appService.children.get('scan');
- const settingsService = appService.children.get('settings');
const vcService = appService.children.get('vc');
const shareableVcs = useSelector(vcService, selectShareableVcs);
const isLocationDisabled = useSelector(scanService, selectIsLocationDisabled);
const isLocationDenied = useSelector(scanService, selectIsLocationDenied);
-
+ const isReadyForBluetoothStateCheck = useSelector(
+ scanService,
+ selectReadyForBluetoothStateCheck
+ );
+ const isStartPermissionCheck = useSelector(
+ scanService,
+ selectIsStartPermissionCheck
+ );
+ const isNearByDevicesPermissionDenied = useSelector(
+ scanService,
+ selectIsNearByDevicesPermissionDenied
+ );
+ const isBluetoothPermissionDenied = useSelector(
+ scanService,
+ selectIsBluetoothPermissionDenied
+ );
+ const isBluetoothDenied = useSelector(scanService, selectIsBluetoothDenied);
const locationError = { message: '', button: '' };
+ const isMinimumStorageRequiredForAuditEntryLimitReached = useSelector(
+ scanService,
+ selectIsMinimumStorageRequiredForAuditEntryLimitReached
+ );
if (isLocationDisabled) {
locationError.message = t('errors.locationDisabled.message');
@@ -39,16 +67,23 @@ export function useScanScreen() {
return {
locationError,
- vcLabel: useSelector(settingsService, selectVcLabel),
-
isEmpty: !shareableVcs.length,
+ isBluetoothPermissionDenied,
+ isNearByDevicesPermissionDenied,
isLocationDisabled,
isLocationDenied,
+ isBluetoothDenied,
+ isStartPermissionCheck,
+ isReadyForBluetoothStateCheck,
+ isMinimumStorageRequiredForAuditEntryLimitReached,
isScanning: useSelector(scanService, selectIsScanning),
isQrLogin: useSelector(scanService, selectIsShowQrLogin),
isQrLoginstoring: useSelector(scanService, selectIsQrLoginStoring),
isQrRef: useSelector(scanService, selectQrLoginRef),
LOCATION_REQUEST: () => scanService.send(ScanEvents.LOCATION_REQUEST()),
+ GOTO_SETTINGS: () => scanService.send(ScanEvents.GOTO_SETTINGS()),
+ START_PERMISSION_CHECK: () =>
+ scanService.send(ScanEvents.START_PERMISSION_CHECK()),
SCAN: (qrCode: string) => scanService.send(ScanEvents.SCAN(qrCode)),
};
}
diff --git a/screens/Scan/SelectVcOverlay.strings.json b/screens/Scan/SelectVcOverlay.strings.json
index e49ce941..f578e30e 100644
--- a/screens/Scan/SelectVcOverlay.strings.json
+++ b/screens/Scan/SelectVcOverlay.strings.json
@@ -1,6 +1,6 @@
{
- "header": "Share {{vcLabel}}",
- "chooseVc": "Choose the {{vcLabel}} you'd like to share with",
+ "header": "Share Card",
+ "chooseVc": "Choose the Card you'd like to share with",
"share": "Share",
"verifyAndShare": "Verify Identity & Share"
}
\ No newline at end of file
diff --git a/screens/Scan/SelectVcOverlay.tsx b/screens/Scan/SelectVcOverlay.tsx
index 1577bf0e..840931c4 100644
--- a/screens/Scan/SelectVcOverlay.tsx
+++ b/screens/Scan/SelectVcOverlay.tsx
@@ -23,11 +23,10 @@ export const SelectVcOverlay: React.FC = (props) => {
width={Dimensions.get('screen').width * 0.9}
style={{ maxHeight: Dimensions.get('screen').height * 0.9 }}>
- {t('header', { vcLabel: controller.vcLabel.singular })}
+ {t('header')}
- {t('chooseVc', { vcLabel: controller.vcLabel.singular })}{' '}
- {props.receiverName}
+ {t('chooseVc')} {props.receiverName}
{props.vcKeys.map((vcKey, index) => (
diff --git a/screens/Scan/SelectVcOverlayController.ts b/screens/Scan/SelectVcOverlayController.ts
index 5726ba5f..ba509400 100644
--- a/screens/Scan/SelectVcOverlayController.ts
+++ b/screens/Scan/SelectVcOverlayController.ts
@@ -1,9 +1,6 @@
-import { useSelector } from '@xstate/react';
-import { useContext, useState } from 'react';
+import { useState } from 'react';
import { ActorRefFrom } from 'xstate';
-import { selectVcLabel } from '../../machines/settings';
import { vcItemMachine } from '../../machines/vcItem';
-import { GlobalContext } from '../../shared/GlobalContext';
import { VC } from '../../types/vc';
export function useSelectVcOverlay(props: SelectVcOverlayProps) {
@@ -11,13 +8,9 @@ export function useSelectVcOverlay(props: SelectVcOverlayProps) {
const [selectedVcRef, setSelectedVcRef] =
useState>(null);
- const { appService } = useContext(GlobalContext);
- const settingsService = appService.children.get('settings');
-
return {
selectVcItem,
selectedIndex,
- vcLabel: useSelector(settingsService, selectVcLabel),
onSelect: () => {
const { serviceRefs, ...vc } = selectedVcRef.getSnapshot().context;
diff --git a/screens/Scan/SendVcScreen.strings.json b/screens/Scan/SendVcScreen.strings.json
index 408909f0..cb8461c7 100644
--- a/screens/Scan/SendVcScreen.strings.json
+++ b/screens/Scan/SendVcScreen.strings.json
@@ -1,7 +1,7 @@
{
"reasonForSharing": "Reason for sharing (optional)",
- "acceptRequest": "Accept request and choose {{vcLabel}}",
+ "acceptRequest": "Share",
"acceptRequestAndVerify": "Accept request and verify",
"reject": "Reject",
"consentToPhotoVerification": "I give consent to have my photo taken for authentication"
-}
\ No newline at end of file
+}
diff --git a/screens/Scan/SendVcScreen.tsx b/screens/Scan/SendVcScreen.tsx
index 4a00edfb..44684c3c 100644
--- a/screens/Scan/SendVcScreen.tsx
+++ b/screens/Scan/SendVcScreen.tsx
@@ -1,85 +1,105 @@
-import React from 'react';
-import { CheckBox, Input } from 'react-native-elements';
+import React, { useContext, useEffect, useRef } from 'react';
+import { Input } from 'react-native-elements';
import { useTranslation } from 'react-i18next';
-
-import { DeviceInfoList } from '../../components/DeviceInfoList';
-import { Button, Column, Row } from '../../components/ui';
+import { Button, Column, Row, Text } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import { MessageOverlay } from '../../components/MessageOverlay';
import { useSendVcScreen } from './SendVcScreenController';
import { VerifyIdentityOverlay } from '../VerifyIdentityOverlay';
import { VcItem } from '../../components/VcItem';
-import { SingleVcItem } from '../../components/SingleVcItem';
-import { I18nManager } from 'react-native';
+import { I18nManager, BackHandler } from 'react-native';
+import { useInterpret } from '@xstate/react';
+import { createVcItemMachine } from '../../machines/vcItem';
+import { GlobalContext } from '../../shared/GlobalContext';
+import { useFocusEffect } from '@react-navigation/native';
export const SendVcScreen: React.FC = () => {
const { t } = useTranslation('SendVcScreen');
+ const { appService } = useContext(GlobalContext);
const controller = useSendVcScreen();
+ let service;
+
+ if (controller.vcKeys?.length > 0) {
+ const firstVCMachine = useRef(
+ createVcItemMachine(
+ appService.getSnapshot().context.serviceRefs,
+ controller.vcKeys[0]
+ )
+ );
+
+ service = useInterpret(firstVCMachine.current);
+ }
+
+ useEffect(() => {
+ if (service) {
+ controller.SELECT_VC_ITEM(0)(service);
+ }
+ }, []);
+
+ useFocusEffect(
+ React.useCallback(() => {
+ const onBackPress = () => true;
+
+ const disableBackHandler = BackHandler.addEventListener(
+ 'hardwareBackPress',
+ onBackPress
+ );
+
+ return () => disableBackHandler.remove();
+ }, [])
+ );
const reasonLabel = t('reasonForSharing');
return (
-
-
-
-
+
+
-
- {controller.vcKeys.length === 1 && (
-
- )}
-
- {controller.vcKeys.length > 1 &&
- controller.vcKeys.map((vcKey, index) => (
-
- ))}
-
+
+ {t('pleaseSelectAnId')}
+
-
+
+ {controller.vcKeys.map((vcKey, index) => (
+
+ ))}
{!controller.selectedVc.shouldVerifyPresence && (
diff --git a/screens/Scan/SendVcScreenController.ts b/screens/Scan/SendVcScreenController.ts
index 2704626b..68ce79e8 100644
--- a/screens/Scan/SendVcScreenController.ts
+++ b/screens/Scan/SendVcScreenController.ts
@@ -1,26 +1,26 @@
import { useSelector } from '@xstate/react';
import { useContext, useState } from 'react';
import { ActorRefFrom } from 'xstate';
-import {
- ScanEvents,
- selectReason,
- selectReceiverInfo,
- selectIsSelectingVc,
- selectVcName,
- selectIsVerifyingIdentity,
- selectIsInvalidIdentity,
- selectSelectedVc,
- selectIsCancelling,
-} from '../../machines/scan';
-import { selectVcLabel } from '../../machines/settings';
import { selectShareableVcs } from '../../machines/vc';
import { vcItemMachine } from '../../machines/vcItem';
import { GlobalContext } from '../../shared/GlobalContext';
+import {
+ selectIsSelectingVc,
+ selectReason,
+ selectReceiverInfo,
+ selectSelectedVc,
+ selectVcName,
+} from '../../machines/bleShare/scan/selectors';
+import {
+ selectIsCancelling,
+ selectIsInvalidIdentity,
+ selectIsVerifyingIdentity,
+} from '../../machines/bleShare/commonSelectors';
+import { ScanEvents } from '../../machines/bleShare/scan/scanMachine';
export function useSendVcScreen() {
const { appService } = useContext(GlobalContext);
const scanService = appService.children.get('scan');
- const settingsService = appService.children.get('settings');
const vcService = appService.children.get('vc');
const CANCEL = () => scanService.send(ScanEvents.CANCEL());
@@ -41,7 +41,6 @@ export function useSendVcScreen() {
receiverInfo: useSelector(scanService, selectReceiverInfo),
reason: useSelector(scanService, selectReason),
vcName: useSelector(scanService, selectVcName),
- vcLabel: useSelector(settingsService, selectVcLabel),
vcKeys: useSelector(vcService, selectShareableVcs),
selectedVc: useSelector(scanService, selectSelectedVc),
diff --git a/screens/Scan/SuccessfullySharedModal.tsx b/screens/Scan/SuccessfullySharedModal.tsx
new file mode 100644
index 00000000..f32e4ec1
--- /dev/null
+++ b/screens/Scan/SuccessfullySharedModal.tsx
@@ -0,0 +1,54 @@
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Theme } from '../../components/ui/styleUtils';
+import { Modal } from '../../components/ui/Modal';
+import { Image } from 'react-native';
+import { Column, Text } from '../../components/ui';
+import { DeviceInfoList } from '../../components/DeviceInfoList';
+import { Button } from '../../components/ui';
+import { useScanLayout } from './ScanLayoutController';
+import { useSendVcScreen } from './SendVcScreenController';
+
+export const SharingSuccessModal: React.FC = (
+ props
+) => {
+ const { t } = useTranslation('ScanScreen');
+ const controller = useScanLayout();
+ const controller1 = useSendVcScreen();
+
+ return (
+
+
+
+
+
+ {t('ScanScreen:status.accepted.title')}
+
+
+ {t('ScanScreen:status.accepted.message')}
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+interface SharingSuccessModalProps {
+ isVisible: boolean;
+}
diff --git a/screens/Settings/AboutInji.tsx b/screens/Settings/AboutInji.tsx
new file mode 100644
index 00000000..f41b44f9
--- /dev/null
+++ b/screens/Settings/AboutInji.tsx
@@ -0,0 +1,129 @@
+import React, { useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Linking, Pressable, TouchableOpacity } from 'react-native';
+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 getAllConfigurations from '../../shared/commonprops/commonProps';
+import { getVersion } from 'react-native-device-info';
+import { CopyButton } from '../../components/CopyButton';
+
+export const AboutInji: React.FC = ({ appId }) => {
+ const { t } = useTranslation('AboutInji');
+
+ const [showAboutInji, setShowAboutInji] = useState(false);
+ const [aboutInjiUrl, setAboutInjiUrl] = useState('');
+
+ useEffect(() => {
+ getAllConfigurations().then((response) => {
+ setAboutInjiUrl(response.aboutInjiUrl);
+ });
+ }, []);
+
+ const dependencies = require('../../package-lock.json').dependencies;
+ let packageVersion, packageCommitId;
+
+ Object.keys(dependencies).forEach((dependencyName) => {
+ const dependencyData = dependencies[dependencyName];
+
+ if (dependencyName == 'react-native-tuvali') {
+ packageVersion = dependencyData.from
+ ? dependencyData.from.split('#')[1]
+ : 'unknown';
+ if (packageVersion != 'unknown') {
+ packageCommitId = dependencyData.version.split('#')[1].substring(0, 7);
+ }
+ }
+ });
+
+ return (
+
+ {
+ setShowAboutInji(!showAboutInji);
+ }}>
+
+
+
+
+
+ {t('aboutInji')}
+
+
+
+
+
+ }
+ onDismiss={() => {
+ setShowAboutInji(!showAboutInji);
+ }}>
+
+
+ {t('appID')} : {appId}
+
+
+
+
+
+
+ {t('aboutDetailes')}
+
+
+
+ {t('forMoreDetailes')}
+
+ {
+ aboutInjiUrl && Linking.openURL(aboutInjiUrl);
+ }}>
+
+ {t('clickHere')}
+
+
+
+
+
+
+
+ {t('version')}: {getVersion()}
+
+ {packageVersion != 'unknown' && (
+
+ {t('tuvaliVersion')}: {packageVersion + '-' + packageCommitId}
+
+ )}
+
+
+
+
+ );
+};
+
+interface AboutInjiProps {
+ isVisible?: boolean;
+ appId?: string;
+}
diff --git a/screens/Settings/AppMetaData.strings.json b/screens/Settings/AppMetaData.strings.json
new file mode 100644
index 00000000..0fa00728
--- /dev/null
+++ b/screens/Settings/AppMetaData.strings.json
@@ -0,0 +1,5 @@
+{
+ "header": "About Inji",
+ "version": "Version",
+ "useBle": "Powered by BLE"
+}
diff --git a/screens/Settings/AppMetaData.tsx b/screens/Settings/AppMetaData.tsx
new file mode 100644
index 00000000..15bcf82b
--- /dev/null
+++ b/screens/Settings/AppMetaData.tsx
@@ -0,0 +1,116 @@
+import React, { useState } from 'react';
+import Markdown from 'react-native-simple-markdown';
+import { useTranslation } from 'react-i18next';
+import { I18nManager, SafeAreaView, View } from 'react-native';
+import { Divider, Icon, ListItem, Overlay } from 'react-native-elements';
+
+import { Button, Text, Row } from '../../components/ui';
+import { Theme } from '../../components/ui/styleUtils';
+import appMetaData from '../../AppMetaData.md';
+import { getVersion } from 'react-native-device-info';
+
+export const AppMetaData: React.FC = (props) => {
+ const { t } = useTranslation('AppMetaData');
+ const [isViewing, setIsViewing] = useState(false);
+
+ const dependencies = require('../../package-lock.json').dependencies;
+ let packageVersion, packageCommitId;
+
+ Object.keys(dependencies).forEach((dependencyName) => {
+ const dependencyData = dependencies[dependencyName];
+
+ if (dependencyName == 'react-native-tuvali') {
+ packageVersion = dependencyData.from
+ ? dependencyData.from.split('#')[1]
+ : 'unknown';
+ if (packageVersion != 'unknown') {
+ packageCommitId = dependencyData.version.split('#')[1].substring(0, 7);
+ }
+ }
+ });
+
+ const markdownStyles = {
+ text: {
+ fontSize: 18,
+ },
+ view: {
+ flex: 1,
+ },
+ };
+
+ return (
+ setIsViewing(true)}>
+
+
+
+ {props.label}
+
+
+ setIsViewing(false)}>
+
+
+
+
+
+ }
+ title=""
+ onPress={() => setIsViewing(false)}
+ />
+
+
+ {t('header').toUpperCase()}
+
+
+
+
+ {appMetaData}
+
+
+ {t('version')}: {getVersion()}
+
+ {packageVersion != 'unknown' && (
+
+ {t('Tuvali-version')}:{' '}
+ {packageVersion + '-' + packageCommitId}
+
+ )}
+
+
+
+
+
+
+ );
+};
+
+interface AppMetaDataProps {
+ label: string;
+ color?: string;
+}
diff --git a/screens/Profile/Credits.strings.json b/screens/Settings/Credits.strings.json
similarity index 100%
rename from screens/Profile/Credits.strings.json
rename to screens/Settings/Credits.strings.json
diff --git a/screens/Profile/Credits.tsx b/screens/Settings/Credits.tsx
similarity index 84%
rename from screens/Profile/Credits.tsx
rename to screens/Settings/Credits.tsx
index 08c96410..a668c2f3 100644
--- a/screens/Profile/Credits.tsx
+++ b/screens/Settings/Credits.tsx
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import Markdown from 'react-native-simple-markdown';
import { useTranslation } from 'react-i18next';
-import { I18nManager, Image, SafeAreaView, View } from 'react-native';
+import { Image, SafeAreaView, View } from 'react-native';
import { Divider, Icon, ListItem, Overlay } from 'react-native-elements';
import { Button, Text, Row, Column } from '../../components/ui';
@@ -50,15 +50,21 @@ export const Credits: React.FC = (props) => {
- {props.label}
+
+ {props.label}
+
+
= (props) => {
- }
+ icon={}
title=""
onPress={() => setIsViewing(false)}
/>
diff --git a/screens/Settings/ReceivedCards.tsx b/screens/Settings/ReceivedCards.tsx
new file mode 100644
index 00000000..cc21627e
--- /dev/null
+++ b/screens/Settings/ReceivedCards.tsx
@@ -0,0 +1,88 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { RefreshControl } from 'react-native';
+import { Pressable } from 'react-native';
+import { Centered, Column, Text } from '../../components/ui';
+import { Icon } from 'react-native-elements';
+import { Theme } from '../../components/ui/styleUtils';
+import { Image } from 'react-native';
+import { Modal } from '../../components/ui/Modal';
+import { useReceivedVcsTab } from '../Home/ReceivedVcsTabController';
+import { VcItem } from '../../components/VcItem';
+import { ViewVcModal } from '../Home/ViewVcModal';
+
+export const ReceivedCards: React.FC = () => {
+ const { t } = useTranslation('ReceivedVcsTab');
+ const controller = useReceivedVcsTab();
+
+ return (
+
+
+
+
+
+ {t('receivedCards')}
+
+
+
+
+ }
+ headerTitle={t('header')}
+ headerElevation={2}
+ onDismiss={controller.TOGGLE_RECEIVED_CARDS}>
+
+ }>
+ {controller.vcKeys.map((vcKey) => (
+
+ ))}
+ {controller.vcKeys.length === 0 && (
+
+
+
+
+ {t('noReceivedVcsTitle')}
+
+
+ {t('noReceivedVcsText')}
+
+
+
+ )}
+
+ {controller.selectedVc && (
+ {
+ controller.REVOKE();
+ }}
+ activeTab={controller.activeTab}
+ />
+ )}
+
+
+ );
+};
diff --git a/screens/Profile/Revoke.tsx b/screens/Settings/Revoke.tsx
similarity index 95%
rename from screens/Profile/Revoke.tsx
rename to screens/Settings/Revoke.tsx
index 3a2891b8..6213ba68 100644
--- a/screens/Profile/Revoke.tsx
+++ b/screens/Settings/Revoke.tsx
@@ -15,22 +15,25 @@ import { OIDcAuthenticationOverlay } from '../../components/OIDcAuthModal';
import { useTranslation } from 'react-i18next';
import { useRevoke } from './RevokeController';
+// Intentionally hidden using {display:'none'} - Refer mosip/inji/issue#607
export const Revoke: React.FC = (props) => {
const controller = useRevoke();
const { t } = useTranslation('ProfileScreen');
return (
- controller.setAuthenticating(true)}>
+ controller.setAuthenticating(true)}
+ style={{ display: 'none' }}>
- {props.label}
+ {props.label}
{
+ const { t } = useTranslation('SettingScreen');
+
+ return (
+
+
+
+
+ {t('language')}
+
+
+
+
+ }
+ />
+ );
+};
+
+export const SettingScreen: React.FC<
+ SettingProps & RootRouteProps & RequestRouteProps
+> = (props) => {
+ const { t } = useTranslation('SettingScreen');
+ const controller = useSettingsScreen(props);
+
+ return (
+
+
+ {props.triggerComponent}
+
+ }
+ headerTitle={t('header')}
+ headerElevation={2}
+ onDismiss={controller.TOGGLE_SETTINGS}>
+
+
+
+ {t('injiAsVerifierApp')}
+
+
+
+
+
+
+ {t('receiveCard')}
+
+
+
+
+
+
+
+ {t('basicSettings')}
+
+
+
+
+
+
+
+
+
+
+
+
+ {t('bioUnlock')}
+
+
+
+
+
+
+
+
+ {CREDENTIAL_REGISTRY_EDIT === 'true' && (
+
+ )}
+
+ controller.INJI_TOUR_GUIDE()}>
+
+
+
+
+ {t('injiTourGuide')}
+
+
+
+
+
+
+
+
+
+
+ {t('logout')}
+
+
+
+
+ {controller.backendInfo.application.name !== '' ? (
+
+
+ {controller.backendInfo.application.name}:{' '}
+ {controller.backendInfo.application.version}
+
+
+ MOSIP: {controller.backendInfo.config['mosip.host']}
+
+
+ ) : null}
+
+
+
+
+ );
+};
+
+interface SettingProps {
+ triggerComponent: React.ReactElement;
+}
diff --git a/screens/Settings/SettingScreenController.ts b/screens/Settings/SettingScreenController.ts
new file mode 100644
index 00000000..392ca715
--- /dev/null
+++ b/screens/Settings/SettingScreenController.ts
@@ -0,0 +1,172 @@
+import { useMachine, useSelector } from '@xstate/react';
+import { useContext, useEffect, useState } from 'react';
+import * as LocalAuthentication from 'expo-local-authentication';
+import { selectBackendInfo } from '../../machines/app';
+import {
+ AuthEvents,
+ selectBiometrics,
+ selectCanUseBiometrics,
+} from '../../machines/auth';
+import {
+ selectBiometricUnlockEnabled,
+ selectName,
+ selectCredentialRegistryResponse,
+ selectVcLabel,
+ selectCredentialRegistry,
+ SettingsEvents,
+ selectAppId,
+ selectIsResetInjiProps,
+} from '../../machines/settings';
+
+import {
+ biometricsMachine,
+ selectError,
+ selectIsSuccess,
+ selectUnenrolledNotice,
+} from '../../machines/biometrics';
+import { GlobalContext } from '../../shared/GlobalContext';
+import { useTranslation } from 'react-i18next';
+import { Platform } from 'react-native';
+import { RequestRouteProps, RootRouteProps } from '../../routes';
+
+export function useSettingsScreen(props: RootRouteProps & RequestRouteProps) {
+ const { appService } = useContext(GlobalContext);
+ const authService = appService.children.get('auth');
+ const settingsService = appService.children.get('settings');
+
+ const [isVisible, setIsVisible] = useState(false);
+
+ const [alertMsg, setHasAlertMsg] = useState('');
+ const authBiometrics = useSelector(authService, selectBiometrics);
+ const [biometricState, biometricSend, bioService] =
+ useMachine(biometricsMachine);
+
+ const isSuccessBio: boolean = useSelector(bioService, selectIsSuccess);
+ const errorMsgBio: string = useSelector(bioService, selectError);
+ const unEnrolledNoticeBio: string = useSelector(
+ bioService,
+ selectUnenrolledNotice
+ );
+ const { t } = useTranslation('AuthScreen');
+
+ useEffect(() => {
+ setTimeout(async () => {
+ const hasEnrolledBiometrics = await LocalAuthentication.isEnrolledAsync();
+ if (!hasEnrolledBiometrics) {
+ authService.send(AuthEvents.SETUP_BIOMETRICS(''));
+ settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(false));
+ }
+ }, 0);
+
+ // if biometic state is success then lets send auth service BIOMETRICS
+ if (isSuccessBio) {
+ authService.send(AuthEvents.SETUP_BIOMETRICS('true'));
+ settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(true));
+
+ // handle biometric failure unknown error
+ } else {
+ const error: string = errorMsgBio ?? unEnrolledNoticeBio ?? '';
+ if (error != '') {
+ setHasAlertMsg(t(error));
+ }
+ }
+ }, [isSuccessBio, errorMsgBio, unEnrolledNoticeBio]);
+
+ const useBiometrics = (value: boolean) => {
+ if (value) {
+ // But check if we already enrolled biometrics
+ if (authBiometrics) {
+ authService.send(AuthEvents.SETUP_BIOMETRICS('true'));
+ settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(true));
+
+ // but if device does not have any enrolled biometrics
+ } else if (biometricState.matches({ failure: 'unenrolled' })) {
+ biometricSend({ type: 'RETRY_AUTHENTICATE' });
+
+ // otherwise lets do a biometric auth
+ } else {
+ biometricSend({ type: 'AUTHENTICATE' });
+ }
+ } else {
+ authService.send(AuthEvents.SETUP_BIOMETRICS(''));
+ settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(false));
+ }
+ };
+
+ const hideAlert = () => {
+ setHasAlertMsg('');
+ };
+
+ return {
+ isVisible,
+ alertMsg,
+ hideAlert,
+ appId: useSelector(settingsService, selectAppId),
+ backendInfo: useSelector(appService, selectBackendInfo),
+ name: useSelector(settingsService, selectName),
+ vcLabel: useSelector(settingsService, selectVcLabel),
+ credentialRegistry: useSelector(settingsService, selectCredentialRegistry),
+ credentialRegistryResponse: useSelector(
+ settingsService,
+ selectCredentialRegistryResponse
+ ),
+ isBiometricUnlockEnabled: useSelector(
+ settingsService,
+ selectBiometricUnlockEnabled
+ ),
+ isResetInjiProps: useSelector(settingsService, selectIsResetInjiProps),
+ canUseBiometrics: useSelector(authService, selectCanUseBiometrics),
+ useBiometrics,
+
+ UPDATE_NAME: (name: string) =>
+ settingsService.send(SettingsEvents.UPDATE_NAME(name)),
+
+ TOGGLE_SETTINGS: () => setIsVisible(!isVisible),
+
+ UPDATE_VC_LABEL: (label: string) =>
+ settingsService.send(SettingsEvents.UPDATE_VC_LABEL(label)),
+
+ UPDATE_CREDENTIAL_REGISTRY: (credentialRegistry: string) =>
+ settingsService.send(
+ SettingsEvents.UPDATE_CREDENTIAL_REGISTRY(credentialRegistry)
+ ),
+
+ UPDATE_CREDENTIAL_REGISTRY_RESPONSE: (credentialRegistryResponse: string) =>
+ settingsService.send(
+ SettingsEvents.UPDATE_CREDENTIAL_REGISTRY_RESPONSE(
+ credentialRegistryResponse
+ )
+ ),
+
+ RECEIVE_CARD: () => {
+ props.navigation.navigate('Request');
+ setIsVisible(false);
+ },
+
+ INJI_TOUR_GUIDE: () => {
+ settingsService.send(SettingsEvents.INJI_TOUR_GUIDE()),
+ props.navigation.navigate('IntroSliders'),
+ setIsVisible(false);
+ },
+
+ TOGGLE_BIOMETRIC: (enable: boolean) =>
+ settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(enable)),
+
+ LOGOUT: () => {
+ setIsVisible(false);
+ const navigate = () => {
+ authService.send(AuthEvents.LOGOUT());
+ };
+
+ if (Platform.OS === 'ios') {
+ setTimeout(() => navigate(), 0);
+ } else {
+ navigate();
+ }
+ },
+
+ CANCEL: () => {
+ settingsService.send(SettingsEvents.CANCEL());
+ },
+ };
+}
diff --git a/screens/SetupLanguageScreen.tsx b/screens/SetupLanguageScreen.tsx
new file mode 100644
index 00000000..2e9dcf27
--- /dev/null
+++ b/screens/SetupLanguageScreen.tsx
@@ -0,0 +1,81 @@
+import React from 'react';
+import i18n, { SUPPORTED_LANGUAGES } from '../i18n';
+import { I18nManager, Dimensions } from 'react-native';
+import Storage from '../shared/storage';
+import { useTranslation } from 'react-i18next';
+import i18next from 'i18next';
+import RNRestart from 'react-native-restart';
+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';
+
+export const SetupLanguageScreen: React.FC = (props) => {
+ const { t } = useTranslation('SetupLanguage');
+ const controller = useWelcomeScreen(props);
+ const languages = Object.entries(SUPPORTED_LANGUAGES).map(
+ ([value, label]) => ({ label, value })
+ );
+
+ const changeLanguage = async (language: string) => {
+ if (language !== i18n.language) {
+ await i18n.changeLanguage(language).then(async () => {
+ await Storage.setItem('language', i18n.language);
+ const isRTL = i18next.dir(language) === 'rtl' ? true : false;
+ if (isRTL !== I18nManager.isRTL) {
+ try {
+ I18nManager.forceRTL(isRTL);
+ setTimeout(() => {
+ RNRestart.Restart();
+ }, 150);
+ } catch (e) {
+ console.log('error', e);
+ }
+ }
+ });
+ }
+ };
+
+ return (
+
+
+
+
+ {t('header')}
+
+
+ {t('description')}
+
+
+
+
+
+ {
+ controller.SELECT(), controller.unlockPage;
+ }}
+ />
+
+ );
+};
diff --git a/screens/VerifyIdentityOverlay.strings.json b/screens/VerifyIdentityOverlay.strings.json
index 62c87ba9..80b8101c 100644
--- a/screens/VerifyIdentityOverlay.strings.json
+++ b/screens/VerifyIdentityOverlay.strings.json
@@ -5,8 +5,8 @@
"errors": {
"invalidIdentity": {
"title": "Unable to verify identity",
- "message": "An error occurred and we couldn't scan your portrait. Try again, make sure your face is visible, devoid of any accessories.",
- "messageNoRetry": "An error occurred and we couldn't scan your portrait."
+ "message": "Face not recognised. Please try again.",
+ "messageNoRetry": "Face not recognised."
}
}
}
\ No newline at end of file
diff --git a/screens/VerifyIdentityOverlay.tsx b/screens/VerifyIdentityOverlay.tsx
index 59152119..7d78cc03 100644
--- a/screens/VerifyIdentityOverlay.tsx
+++ b/screens/VerifyIdentityOverlay.tsx
@@ -7,10 +7,12 @@ import { Theme } from '../components/ui/styleUtils';
import { VC } from '../types/vc';
import { Modal } from '../components/ui/Modal';
import { t } from 'i18next';
+import { useTranslation } from 'react-i18next';
export const VerifyIdentityOverlay: React.FC = (
props
) => {
+ const { t } = useTranslation('VerifyIdentityOverlay');
return (
= (props) => {
const { t } = useTranslation('WelcomeScreen');
const controller = useWelcomeScreen(props);
-
return (
-
+
- {t('title')}
-
+
{
+ if (passcode) {
+ return false;
+ } else {
+ return true;
+ }
+ };
+
const biometrics = useSelector(authService, selectBiometrics);
- const isBiometricUnlockEnabled = useSelector(settingsService, selectBiometricUnlockEnabled);
+ const isLanguagesetup = useSelector(authService, selectLanguagesetup);
+ const isBiometricUnlockEnabled = useSelector(
+ settingsService,
+ selectBiometricUnlockEnabled
+ );
return {
isSettingUp,
-
+ isLanguagesetup,
+ isPasscodeSet,
+ NEXT: () => {
+ authService.send(AuthEvents.NEXT()), props.navigation.navigate('Auth');
+ },
+ SELECT: () => {
+ authService.send(AuthEvents.SELECT()),
+ props.navigation.navigate('IntroSliders');
+ },
+ BACK: () => {
+ settingsService.send(SettingsEvents.BACK()),
+ props.navigation.navigate('Main');
+ },
unlockPage: () => {
// prioritize biometrics
if (!isSettingUp && isBiometricUnlockEnabled && biometrics !== '') {
diff --git a/shared/GlobalContext.ts b/shared/GlobalContext.ts
index 020cd63e..d93dca3a 100644
--- a/shared/GlobalContext.ts
+++ b/shared/GlobalContext.ts
@@ -3,13 +3,12 @@ import { ActorRefFrom, InterpreterFrom } from 'xstate';
import { activityLogMachine } from '../machines/activityLog';
import { appMachine } from '../machines/app';
import { authMachine } from '../machines/auth';
-import { requestMachine } from '../machines/request';
-import { scanMachine } from '../machines/scan';
+import { requestMachine } from '../machines/bleShare/request/requestMachine';
+import { scanMachine } from '../machines/bleShare/scan/scanMachine';
import { settingsMachine } from '../machines/settings';
import { storeMachine } from '../machines/store';
import { vcMachine } from '../machines/vc';
import { revokeVidsMachine } from '../machines/revoke';
-import { qrLoginMachine } from '../machines/QrLoginMachine';
export const GlobalContext = createContext({} as GlobalServices);
diff --git a/shared/commonUtil.ts b/shared/commonUtil.ts
new file mode 100644
index 00000000..3c3f3068
--- /dev/null
+++ b/shared/commonUtil.ts
@@ -0,0 +1,18 @@
+import argon2 from 'react-native-argon2';
+
+export const hashData = async (
+ data: string,
+ salt: string,
+ config: Argon2iConfig
+): Promise => {
+ const result = await argon2(data, salt, config);
+ return result.rawHash as string;
+};
+
+export interface Argon2iConfig {
+ iterations: number;
+ memory: number;
+ parallelism: number;
+ hashLength: number;
+ mode: string;
+}
diff --git a/shared/commonprops/commonProps.ts b/shared/commonprops/commonProps.ts
index 6d2e3b6e..fa312b64 100644
--- a/shared/commonprops/commonProps.ts
+++ b/shared/commonprops/commonProps.ts
@@ -1,19 +1,22 @@
import { request } from '../request';
-import AsyncStorage from '@react-native-async-storage/async-storage';
+import Storage from '../storage';
+import { init } from 'mosip-inji-face-sdk';
+import { changeCrendetialRegistry } from '../constants';
-const COMMON_PROPS_KEY: string =
+export const COMMON_PROPS_KEY: string =
'CommonPropsKey-' + '6964d04a-9268-11ed-a1eb-0242ac120002';
-export default async function getAllConfigurations() {
+export default async function getAllConfigurations(host = undefined) {
try {
- var response = await AsyncStorage.getItem(COMMON_PROPS_KEY);
+ host && changeCrendetialRegistry(host);
+ const response = await Storage.getItem(COMMON_PROPS_KEY);
if (response) {
return JSON.parse(response);
} else {
const resp = await request('GET', '/residentmobileapp/allProperties');
const injiProps = resp.response;
const injiPropsString = JSON.stringify(injiProps);
- await AsyncStorage.setItem(COMMON_PROPS_KEY, injiPropsString);
+ await Storage.setItem(COMMON_PROPS_KEY, injiPropsString);
return injiProps;
}
} catch (error) {
@@ -22,6 +25,26 @@ export default async function getAllConfigurations() {
}
}
+export async function downloadModel() {
+ try {
+ var injiProp = await getAllConfigurations();
+ const maxRetryStr = injiProp.modelDownloadMaxRetry;
+ const maxRetry = parseInt(maxRetryStr);
+ const resp: string = injiProp != null ? injiProp.faceSdkModelUrl : null;
+ if (resp != null) {
+ for (let counter = 0; counter < maxRetry; counter++) {
+ var result = await init(resp, false);
+ console.log('model download result is = ' + result);
+ if (result) {
+ break;
+ }
+ }
+ }
+ } catch (error) {
+ console.log(error);
+ }
+}
+
export interface DownloadProps {
maxDownloadLimit: number;
downloadInterval: number;
diff --git a/shared/constants.ts b/shared/constants.ts
index 32ea2d52..f60f8ddc 100644
--- a/shared/constants.ts
+++ b/shared/constants.ts
@@ -1,10 +1,14 @@
+import { Platform } from 'react-native';
import { VC } from '../types/vc';
import {
MIMOTO_HOST,
GOOGLE_NEARBY_MESSAGES_API_KEY,
} from 'react-native-dotenv';
+import { Argon2iConfig } from './commonUtil';
-export const HOST = MIMOTO_HOST;
+export let HOST = MIMOTO_HOST;
+
+export const changeCrendetialRegistry = (host) => (HOST = host);
export const MY_VCS_STORE_KEY = 'myVCs';
@@ -13,7 +17,21 @@ export const RECEIVED_VCS_STORE_KEY = 'receivedVCs';
export const MY_LOGIN_STORE_KEY = 'myLogins';
export const VC_ITEM_STORE_KEY = (vc: Partial) =>
- `vc:${vc.idType}:${vc.id}:${vc.requestId}`;
+ `vc:${vc.idType}:${vc.hashedId}:${vc.requestId}:${vc.isPinned}:${vc.id}`;
+
+export const VC_ITEM_STORE_KEY_AFTER_DOWNLOAD = (vc: Partial) =>
+ `vc:${vc.idType}:${vc.hashedId}:${vc.requestId}:${vc.isPinned}`;
+
+//Regex expression to evaluate if the key is for a VC
+export const VC_ITEM_STORE_KEY_REGEX =
+ '^vc:(UIN|VID):[a-z0-9]+:[a-z0-9-]+:[true|false]+(:[0-9-]+)?$';
+
+//To compare the vckey with requestId, when the vc is pinned
+export const isSameVC = (vcKey: string, pinnedVcKey: string) => {
+ const requestId = vcKey.split(':')[3];
+ const pinnedRequestId = pinnedVcKey.split(':')[3];
+ return requestId === pinnedRequestId;
+};
export let individualId = '';
@@ -31,3 +49,37 @@ export const GNM_API_KEY = GOOGLE_NEARBY_MESSAGES_API_KEY;
// https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Message#MAX_CONTENT_SIZE_BYTES
export const GNM_MESSAGE_LIMIT = 102400 - 6400; // allowance for metadata
+
+export const APP_ID_LENGTH = 12;
+
+// Numbers and Upper case Alphabets without confusing characters like 0, 1, 2, I, O, Z
+// prettier-ignore
+export const APP_ID_DICTIONARY = [
+ '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L',
+ 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+];
+
+export function isIOS(): boolean {
+ return Platform.OS === 'ios';
+}
+
+// Configuration for argon2i hashing algorithm
+export const argon2iConfig: Argon2iConfig = {
+ iterations: 5,
+ memory: 16 * 1024,
+ parallelism: 2,
+ hashLength: 20,
+ mode: 'argon2i',
+};
+
+export const argon2iConfigForUinVid: Argon2iConfig = {
+ iterations: 5,
+ memory: 16 * 1024,
+ parallelism: 2,
+ hashLength: 5,
+ mode: 'argon2i',
+};
+
+export const argon2iSalt =
+ '1234567891011121314151617181920212223242526272829303132333435363';
diff --git a/shared/cryptoutil/cryptoUtil.ts b/shared/cryptoutil/cryptoUtil.ts
index 54d750f0..d17073e3 100644
--- a/shared/cryptoutil/cryptoUtil.ts
+++ b/shared/cryptoutil/cryptoUtil.ts
@@ -1,6 +1,18 @@
import { KeyPair, RSA } from 'react-native-rsa-native';
import forge from 'node-forge';
import getAllConfigurations from '../commonprops/commonProps';
+import { isIOS } from '../constants';
+import SecureKeystore from 'react-native-secure-keystore';
+import Storage from '../storage';
+import CryptoJS from 'crypto-js';
+
+// 5min
+export const AUTH_TIMEOUT = 5 * 60;
+export const ENCRYPTION_ID = 'c7c22a6c-9759-4605-ac88-46f4041d863d';
+export const HMAC_ALIAS = '860cc320-4248-11ee-be56-0242ac120002';
+//This key is used to request biometric at app open to reset auth timeout which is used by encryption key
+export const DUMMY_KEY_FOR_BIOMETRIC_ALIAS =
+ '9a6cfc0e-4248-11ee-be56-0242ac120002';
export function generateKeys(): Promise {
return Promise.resolve(RSA.generateKeys(4096));
@@ -9,55 +21,85 @@ export function generateKeys(): Promise {
export async function getJwt(
privateKey: string,
individualId: string,
- keyId: string,
thumbprint: string
) {
- var token: string = null;
try {
var iat = Math.floor(new Date().getTime() / 1000);
var exp = Math.floor(new Date().getTime() / 1000) + 18000;
var config = await getAllConfigurations();
- const key = forge.pki.privateKeyFromPem(privateKey);
- const md = forge.md.sha256.create();
const header = {
'alg': 'RS256',
//'kid': keyId,
'x5t#S256': thumbprint,
};
- var myJSON =
- '{"iss": "' +
- config.issuer +
- '", "aud": "' +
- config.audience +
- '", "sub": "' +
- individualId +
- '", "iat": ' +
- iat +
- ', "exp": ' +
- exp +
- '}';
- var payload = JSON.parse(myJSON);
+
+ const payloadJSON = JSON.stringify({
+ iss: config.issuer,
+ sub: individualId,
+ aud: config.audience,
+ iat: iat,
+ exp: exp,
+ });
+
+ var payload = JSON.parse(payloadJSON);
const strHeader = JSON.stringify(header);
const strPayload = JSON.stringify(payload);
const header64 = encodeB64(strHeader);
const payload64 = encodeB64(strPayload);
const preHash = header64 + '.' + payload64;
- md.update(preHash, 'utf8');
- const signature = key.sign(md);
- const signature64 = encodeB64(signature);
- var token: string = header64 + '.' + payload64 + '.' + signature64;
- return token;
+
+ const signature64 = await createSignature(
+ privateKey,
+ preHash,
+ individualId
+ );
+
+ return header64 + '.' + payload64 + '.' + signature64;
} catch (e) {
console.log(e);
throw e;
}
}
+async function createSignature(
+ privateKey: string,
+ preHash: string,
+ individualId: string
+) {
+ let signature64;
+
+ if (!isCustomSecureKeystore()) {
+ const key = forge.pki.privateKeyFromPem(privateKey);
+ const md = forge.md.sha256.create();
+ md.update(preHash, 'utf8');
+
+ const signature = key.sign(md);
+ return encodeB64(signature);
+ } else {
+ try {
+ signature64 = await SecureKeystore.sign(individualId, preHash);
+ } catch (e) {
+ console.error('Error in creating signature:', e);
+ throw e;
+ }
+
+ return replaceCharactersInB64(signature64);
+ }
+}
+
+function replaceCharactersInB64(encodedB64) {
+ return encodedB64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
+}
+
function encodeB64(str: string) {
const encodedB64 = forge.util.encode64(str);
- return encodedB64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
+ return replaceCharactersInB64(encodedB64);
+}
+
+export function isCustomSecureKeystore() {
+ return !isIOS() ? SecureKeystore.deviceSupportsHardware() : false;
}
export interface WalletBindingResponse {
@@ -66,3 +108,43 @@ export interface WalletBindingResponse {
thumbprint: string;
expireDateTime: string;
}
+
+export async function clear() {
+ try {
+ console.log('clearing entire storage');
+ if (isCustomSecureKeystore()) {
+ SecureKeystore.clearKeys();
+ }
+ await Storage.clear();
+ } catch (e) {
+ console.error('error clear:', e);
+ throw e;
+ }
+}
+
+export async function encryptJson(
+ encryptionKey: string,
+ data: string
+): Promise {
+ if (!isCustomSecureKeystore()) {
+ return CryptoJS.AES.encrypt(data, encryptionKey).toString();
+ }
+ return await SecureKeystore.encryptData(ENCRYPTION_ID, data);
+}
+
+export async function decryptJson(
+ encryptionKey: string,
+ encryptedData: string
+): Promise {
+ try {
+ if (!isCustomSecureKeystore()) {
+ return CryptoJS.AES.decrypt(encryptedData, encryptionKey).toString(
+ CryptoJS.enc.Utf8
+ );
+ }
+ return await SecureKeystore.decryptData(ENCRYPTION_ID, encryptedData);
+ } catch (e) {
+ console.error('error decryptJson:', e);
+ throw e;
+ }
+}
diff --git a/shared/hooks/useFont.ts b/shared/hooks/useFont.ts
index 9dd7cd2b..898ea849 100644
--- a/shared/hooks/useFont.ts
+++ b/shared/hooks/useFont.ts
@@ -1,15 +1,15 @@
import {
- Poppins_400Regular,
- Poppins_600SemiBold,
- Poppins_700Bold,
+ Inter_400Regular,
+ Inter_600SemiBold,
+ Inter_700Bold,
useFonts,
-} from '@expo-google-fonts/poppins';
+} from '@expo-google-fonts/inter';
export function useFont() {
const [hasFontsLoaded] = useFonts({
- Poppins_400Regular,
- Poppins_600SemiBold,
- Poppins_700Bold,
+ Inter_400Regular,
+ Inter_600SemiBold,
+ Inter_700Bold,
});
return hasFontsLoaded;
diff --git a/shared/hooks/useOverlayVisibleAfterTimeout.ts b/shared/hooks/useOverlayVisibleAfterTimeout.ts
new file mode 100644
index 00000000..887cd25a
--- /dev/null
+++ b/shared/hooks/useOverlayVisibleAfterTimeout.ts
@@ -0,0 +1,23 @@
+import { useEffect, useState } from 'react';
+
+export const useOverlayVisibleAfterTimeout = (
+ visibleStart = false,
+ ms = 1000
+) => {
+ const [visible, setVisible] = useState(false);
+ const [savingTimeout, setSavingTimeout] = useState(null);
+
+ useEffect(() => {
+ if (visibleStart) {
+ const timeoutID = setTimeout(() => {
+ setVisible(true);
+ }, ms);
+ setSavingTimeout(timeoutID);
+ } else {
+ clearTimeout(savingTimeout);
+ setVisible(false);
+ }
+ }, [visibleStart]);
+
+ return visible;
+};
diff --git a/shared/location.ts b/shared/location.ts
index 7e1f60a3..fb3b8090 100644
--- a/shared/location.ts
+++ b/shared/location.ts
@@ -1,19 +1,45 @@
-import LocationEnabler from 'react-native-location-enabler';
+import RNLocation from 'react-native-location';
-const LOCATION_CONFIG = {
- priority: LocationEnabler.PRIORITIES.BALANCED_POWER_ACCURACY,
- alwaysShow: false,
- needBle: true,
-};
+// Initialize RNLocation
+RNLocation.configure({
+ distanceFilter: 5.0, // Example configuration, adjust as needed
+});
-export function checkLocation(onEnabled: () => void, onDisabled: () => void) {
- const subscription = LocationEnabler.addListener(({ locationEnabled }) => {
- locationEnabled ? onEnabled() : onDisabled();
- });
- LocationEnabler.checkSettings(LOCATION_CONFIG);
- return subscription;
+export function checkLocationPermissionStatus(
+ onEnabled: () => void,
+ onDisabled: () => void
+) {
+ RNLocation.checkPermission({
+ android: {
+ detail: 'fine',
+ },
+ })
+ .then((granted) => {
+ if (granted) {
+ return onEnabled();
+ } else {
+ return onDisabled();
+ }
+ })
+ .catch((err) => console.log('Error getting location:', err));
}
-export function requestLocation() {
- return LocationEnabler.requestResolutionSettings(LOCATION_CONFIG);
+export async function requestLocationPermission(
+ onEnabled: () => void,
+ onDisabled: () => void
+) {
+ try {
+ const granted = await RNLocation.requestPermission({
+ android: {
+ detail: 'fine',
+ },
+ });
+ if (granted) {
+ return onEnabled();
+ } else {
+ return onDisabled();
+ }
+ } catch (error) {
+ console.log(error);
+ }
}
diff --git a/shared/openIdBLE/verifierEventHandler.ts b/shared/openIdBLE/verifierEventHandler.ts
new file mode 100644
index 00000000..4a3171df
--- /dev/null
+++ b/shared/openIdBLE/verifierEventHandler.ts
@@ -0,0 +1,9 @@
+import tuvali from 'react-native-tuvali';
+import { VerifierDataEvent } from 'react-native-tuvali/src/types/events';
+
+const { verifier } = tuvali;
+export function subscribe(callback: (event: VerifierDataEvent) => void) {
+ return verifier.handleDataEvents((e) => {
+ callback(e);
+ });
+}
diff --git a/shared/openIdBLE/walletEventHandler.ts b/shared/openIdBLE/walletEventHandler.ts
new file mode 100644
index 00000000..f05cdc7e
--- /dev/null
+++ b/shared/openIdBLE/walletEventHandler.ts
@@ -0,0 +1,10 @@
+import tuvali from 'react-native-tuvali';
+import { WalletDataEvent } from 'react-native-tuvali/src/types/events';
+
+const { wallet } = tuvali;
+
+export function subscribe(callback: (event: WalletDataEvent) => void) {
+ return wallet.handleDataEvents((e) => {
+ callback(e);
+ });
+}
diff --git a/shared/request.ts b/shared/request.ts
index db0a4d10..48a5fe50 100644
--- a/shared/request.ts
+++ b/shared/request.ts
@@ -8,27 +8,59 @@ export class BackendResponseError extends Error {
}
}
+export class AppId {
+ private static value: string;
+
+ public static getValue(): string {
+ return AppId.value;
+ }
+
+ public static setValue(value: string) {
+ this.value = value;
+ }
+}
+
export async function request(
method: 'GET' | 'POST' | 'PATCH',
path: `/${string}`,
body?: Record
) {
+ const headers = {
+ 'Content-Type': 'application/json',
+ };
+ if (path.includes('residentmobileapp')) headers['X-AppId'] = AppId.getValue();
+
const response = await fetch(HOST + path, {
method,
- headers: {
- 'Content-Type': 'application/json',
- },
+ headers,
body: JSON.stringify(body),
});
const jsonResponse = await response.json();
if (response.status >= 400) {
- throw new Error(jsonResponse.message || jsonResponse.error);
+ let backendUrl = HOST + path;
+ let errorMessage = jsonResponse.message || jsonResponse.error;
+ console.error(
+ 'The backend API ' +
+ backendUrl +
+ ' returned error code 400 with message --> ' +
+ errorMessage
+ );
+ throw new Error(errorMessage);
}
if (jsonResponse.errors && jsonResponse.errors.length) {
+ let backendUrl = HOST + path;
const { errorCode, errorMessage } = jsonResponse.errors.shift();
+ console.error(
+ 'The backend API ' +
+ backendUrl +
+ ' returned error response --> error code is : ' +
+ errorCode +
+ ' error message is : ' +
+ errorMessage
+ );
throw new BackendResponseError(errorCode, errorMessage);
}
diff --git a/shared/smartshare.ts b/shared/smartshare.ts
deleted file mode 100644
index 32c861d5..00000000
--- a/shared/smartshare.ts
+++ /dev/null
@@ -1,165 +0,0 @@
-// TODO: fix export from smartshare library
-// import {
-// IdpassSmartshare,
-// GoogleNearbyMessages,
-// } from '@idpass/smartshare-react-native';
-import Smartshare from '@idpass/smartshare-react-native';
-import { ConnectionParams } from '@idpass/smartshare-react-native/lib/typescript/IdpassSmartshare';
-import { getDeviceNameSync } from 'react-native-device-info';
-const { IdpassSmartshare, GoogleNearbyMessages } = Smartshare;
-
-import { DeviceInfo } from '../components/DeviceInfoList';
-import { VC } from '../types/vc';
-
-export async function onlineSubscribe(
- eventType: T,
- callback: (data: SmartshareEventData) => void,
- disconectCallback?: (data: SmartshareEventData) => void,
- config?: { keepAlive?: boolean; pairId?: string }
-) {
- return GoogleNearbyMessages.subscribe(
- (foundMessage) => {
- if (__DEV__) {
- console.log(
- `[${getDeviceNameSync()}] MESSAGE_FOUND`,
- foundMessage.slice(0, 100)
- );
- }
- const response = SmartshareEvent.fromString(foundMessage);
- if (response.pairId !== config?.pairId) {
- return;
- } else if (response.type === 'disconnect') {
- GoogleNearbyMessages.unsubscribe();
- disconectCallback(response.data);
- } else if (response.type === eventType) {
- !config?.keepAlive && GoogleNearbyMessages.unsubscribe();
- callback(response.data);
- }
- },
- (lostMessage) => {
- if (__DEV__) {
- console.log(
- `[${getDeviceNameSync()}] MESSAGE_LOST`,
- lostMessage.slice(0, 100)
- );
- }
- }
- ).catch((error: Error) => {
- if (error.message.includes('existing callback is already subscribed')) {
- console.log(
- `${getDeviceNameSync()} Existing callback found for ${eventType}. Unsubscribing then retrying...`
- );
- return onlineSubscribe(eventType, callback, disconectCallback, config);
- }
- });
-}
-
-export async function onlineSend(event: SmartshareEvents, pairId: string) {
- return GoogleNearbyMessages.publish(
- new SmartshareEvent(event.type, event.data, pairId).toString()
- );
-}
-
-export function offlineSubscribe(
- eventType: T,
- callback: (data: SmartshareEventData) => void
-) {
- return IdpassSmartshare.handleNearbyEvents(({ type, data }) => {
- if (type !== 'msg') return;
-
- const response = SmartshareEvent.fromString(data);
- if (response.type === eventType) {
- callback(response.data);
- }
- });
-}
-
-export function offlineSend(event: SmartshareEvents, callback: () => void) {
- IdpassSmartshare.send(
- new SmartshareEvent(event.type, event.data).toString(),
- callback
- );
-}
-
-class SmartshareEvent {
- constructor(
- public type: T | string,
- public data: SmartshareEventData,
- public pairId = ''
- ) {}
-
- static fromString(json: string) {
- const [pairId, type, data] = json.split('\n');
- return new SmartshareEvent(
- type,
- data ? JSON.parse(data) : undefined,
- pairId
- );
- }
-
- toString() {
- const message =
- this.data != null
- ? this.type + '\n' + JSON.stringify(this.data)
- : this.type;
- return [this.pairId, message].join('\n');
- }
-}
-
-export interface PairingEvent {
- type: 'pairing';
- data: ConnectionParams;
-}
-
-export interface PairingResponseEvent {
- type: 'pairing:response';
- data: string;
-}
-
-export interface ExchangeReceiverInfoEvent {
- type: 'exchange-receiver-info';
- data: DeviceInfo;
-}
-
-export interface ExchangeSenderInfoEvent {
- type: 'exchange-sender-info';
- data: DeviceInfo;
-}
-
-export interface VcChunk {
- total: number;
- chunk: number;
- rawData: string;
-}
-export interface SendVcEvent {
- type: 'send-vc';
- data: {
- isChunked: boolean;
- vc?: VC;
- vcChunk?: VcChunk;
- };
-}
-
-export type SendVcStatus = 'ACCEPTED' | 'REJECTED' | 'RECEIVED';
-export interface SendVcResponseEvent {
- type: 'send-vc:response';
- data: SendVcStatus | number;
-}
-
-export interface DisconnectEvent {
- type: 'disconnect';
- data: string;
-}
-
-type SmartshareEventType = SmartshareEvents['type'];
-
-type SmartshareEventData = Extract['data'];
-
-type SmartshareEvents =
- | PairingEvent
- | PairingResponseEvent
- | ExchangeReceiverInfoEvent
- | ExchangeSenderInfoEvent
- | SendVcEvent
- | SendVcResponseEvent
- | DisconnectEvent;
diff --git a/shared/storage.ts b/shared/storage.ts
new file mode 100644
index 00000000..e1727773
--- /dev/null
+++ b/shared/storage.ts
@@ -0,0 +1,191 @@
+import { MMKVLoader } from 'react-native-mmkv-storage';
+import { VC_ITEM_STORE_KEY_REGEX } from './constants';
+import CryptoJS from 'crypto-js';
+import {
+ DocumentDirectoryPath,
+ exists,
+ mkdir,
+ readFile,
+ stat,
+ unlink,
+ writeFile,
+} from 'react-native-fs';
+import getAllConfigurations from './commonprops/commonProps';
+import { Platform } from 'react-native';
+import {
+ getFreeDiskStorageOldSync,
+ getFreeDiskStorageSync,
+} from 'react-native-device-info';
+import SecureKeystore from 'react-native-secure-keystore';
+import {
+ decryptJson,
+ encryptJson,
+ HMAC_ALIAS,
+ isCustomSecureKeystore,
+} from './cryptoutil/cryptoUtil';
+
+const MMKV = new MMKVLoader().initialize();
+const vcKeyRegExp = new RegExp(VC_ITEM_STORE_KEY_REGEX);
+const vcDirectoryPath = `${DocumentDirectoryPath}/inji/VC`;
+
+async function generateHmac(
+ encryptionKey: string,
+ data: string
+): Promise {
+ if (!isCustomSecureKeystore()) {
+ return CryptoJS.HmacSHA256(encryptionKey, data).toString();
+ }
+ return await SecureKeystore.generateHmacSha(HMAC_ALIAS, data);
+}
+
+class Storage {
+ static isVCStorageInitialised = async (): Promise => {
+ try {
+ const res = await stat(vcDirectoryPath);
+ return res.isDirectory();
+ } catch (_) {
+ return false;
+ }
+ };
+
+ static setItem = async (
+ key: string,
+ data: string,
+ encryptionKey?: string
+ ) => {
+ try {
+ const isSavingVC = vcKeyRegExp.exec(key);
+ if (isSavingVC) {
+ await this.storeVcHmac(encryptionKey, data, key);
+ return await this.storeVC(key, data);
+ }
+
+ await MMKV.setItem(key, data);
+ } catch (error) {
+ console.log('Error Occurred while saving in Storage.', error);
+ throw error;
+ }
+ };
+
+ static getItem = async (key: string, encryptionKey?: string) => {
+ try {
+ const isSavingVC = vcKeyRegExp.exec(key);
+
+ if (isSavingVC) {
+ const data = await this.readVCFromFile(key);
+ const isCorrupted = await this.isCorruptedVC(key, encryptionKey, data);
+
+ return isCorrupted ? null : data;
+ }
+
+ return await MMKV.getItem(key);
+ } catch (error) {
+ console.log('Error Occurred while retriving from Storage.', error);
+ throw error;
+ }
+ };
+
+ private static async isCorruptedVC(
+ key: string,
+ encryptionKey: string,
+ data: string
+ ) {
+ const storedHMACofCurrentVC = await this.readHmacForVC(key, encryptionKey);
+ const HMACofVC = await generateHmac(encryptionKey, data);
+ return HMACofVC !== storedHMACofCurrentVC;
+ }
+
+ private static async readHmacForVC(key: string, encryptionKey: string) {
+ const encryptedHMACofCurrentVC = await MMKV.getItem(getVCKeyName(key));
+ return decryptJson(encryptionKey, encryptedHMACofCurrentVC);
+ }
+
+ private static async readVCFromFile(key: string) {
+ const path = getFilePath(key);
+ return await readFile(path, 'utf8');
+ }
+
+ private static async storeVC(key: string, data: string) {
+ await mkdir(vcDirectoryPath);
+ const path = getFilePath(key);
+ return await writeFile(path, data, 'utf8');
+ }
+
+ private static async storeVcHmac(
+ encryptionKey: string,
+ data: string,
+ key: string
+ ) {
+ const HMACofVC = await generateHmac(encryptionKey, data);
+ const encryptedHMACofVC = await encryptJson(encryptionKey, HMACofVC);
+ await MMKV.setItem(getVCKeyName(key), encryptedHMACofVC);
+ }
+
+ static removeItem = async (key: string) => {
+ if (vcKeyRegExp.exec(key)) {
+ const path = getFilePath(key);
+ return await unlink(path);
+ }
+ MMKV.removeItem(key);
+ };
+
+ static clear = async () => {
+ try {
+ (await exists(`${vcDirectoryPath}`)) &&
+ (await unlink(`${vcDirectoryPath}`));
+ MMKV.clearStore();
+ } catch (e) {
+ console.log('Error Occurred while Clearing Storage.', e);
+ }
+ };
+
+ static isMinimumLimitReached = async (limitInMB: string) => {
+ const configurations = await getAllConfigurations();
+ if (!configurations[limitInMB]) return false;
+
+ const minimumStorageLimitInBytes = configurations[limitInMB] * 1000 * 1000;
+
+ const freeDiskStorageInBytes =
+ Platform.OS === 'android' && Platform.Version < 29
+ ? getFreeDiskStorageOldSync()
+ : getFreeDiskStorageSync();
+
+ console.log('minimumStorageLimitInBytes ', minimumStorageLimitInBytes);
+ console.log('freeDiskStorageInBytes ', freeDiskStorageInBytes);
+
+ return freeDiskStorageInBytes <= minimumStorageLimitInBytes;
+ };
+}
+/**
+ * The VC file name will not have the pinned / unpinned state, we will splice the state as this will change.
+ * replace ':' with '_' in the key to get the file name as ':' are not allowed in filenames
+ * eg: "vc:UIN:6732935275:e7426576-112f-466a-961a-1ed9635db628" is changed to "vc_UIN_6732935275_e7426576-112f-466a-961a-1ed9635db628"
+ */
+const getFileName = (key: string) => {
+ return key.split(':').splice(0, 4).join('_');
+};
+
+/**
+ * iOS: /var/mobile/Containers/Data/Application/196A05AD-6B11-403D-BA2D-6DC1F30075E1/Documents/inji/VC/
+ * android: /data/user/0/io.mosip.residentapp/files/inji/VC/
+ * These paths are coming from DocumentDirectoryPath in react-native-fs.
+ */
+const getFilePath = (key: string) => {
+ const fileName = getFileName(key);
+ return `${vcDirectoryPath}/${fileName}.txt`;
+};
+
+/**
+ * The VC key will not have the pinned / unpinned state, we will splice the state as this will change.
+ * eg: "vc:UIN:6732935275:e7426576-112f-466a-961a-1ed9635db628:true" is changed to "vc:UIN:6732935275:e7426576-112f-466a-961a-1ed9635db628"
+ */
+const getVCKeyName = (key: string) => {
+ return key.split(':').splice(0, 4).join(':');
+};
+
+// To print the MMKV data cal this function in getItem
+const getMMKVData = async () => {
+ const mmkvData = await MMKV.indexer.getKeys();
+};
+
+export default Storage;
diff --git a/types/react-native-dotenv/index.d.ts b/types/react-native-dotenv/index.d.ts
index 34d77fd6..1396640f 100644
--- a/types/react-native-dotenv/index.d.ts
+++ b/types/react-native-dotenv/index.d.ts
@@ -8,4 +8,19 @@ declare module 'react-native-dotenv' {
* API key to use Google Nearby Messages API
*/
export const GOOGLE_NEARBY_MESSAGES_API_KEY: string;
+
+ /**
+ * Flag for Toggling Purple Theme and Default Theme
+ */
+ export const APPLICATION_THEME: string;
+
+ /**
+ * Flag for Toggling environment url
+ */
+ export const CREDENTIAL_REGISTRY_EDIT: string;
+
+ /**
+ * LANGUAGE for the unsupported device languages
+ */
+ export const APPLICATION_LANGUAGE: string;
}
diff --git a/types/vc.ts b/types/vc.ts
index 2798aa33..cd75da17 100644
--- a/types/vc.ts
+++ b/types/vc.ts
@@ -15,6 +15,9 @@ export interface VC {
reason?: VCSharingReason[];
shouldVerifyPresence?: boolean;
walletBindingResponse?: WalletBindingResponse;
+ credentialRegistry: string;
+ isPinned?: boolean;
+ hashedId: string;
}
export interface VCSharingReason {