feat(INJI-94): [Vijay] Environment Agnostics Basic Implementation

Issue Link: https://mosip.atlassian.net/browse/INJI-94
This commit is contained in:
Vijay
2023-06-07 12:10:14 +05:30
parent f9ffcedb82
commit 1a3e39b6ef
25 changed files with 277 additions and 51 deletions

5
.env
View File

@@ -1,10 +1,13 @@
# after making changes to the env file, ensure to start the bundler (or the project) with a --reset-cache # 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 # eg . npm build android:newlogic --reset-cache
MIMOTO_HOST=https://api.qa-1201-b2.mosip.net MIMOTO_HOST=https://api.qatriple.mosip.net
#MIMOTO_HOST=http://mock.mimoto.newlogic.dev #MIMOTO_HOST=http://mock.mimoto.newlogic.dev
GOOGLE_NEARBY_MESSAGES_API_KEY= GOOGLE_NEARBY_MESSAGES_API_KEY=
#Application Theme can be ( orange | purple ) #Application Theme can be ( orange | purple )
APPLICATION_THEME=orange APPLICATION_THEME=orange
#environment can be changed if it is toggled
CREDENTIAL_REGISTRY_EDIT=false
USE_BLE_SHARE=true USE_BLE_SHARE=true

View File

@@ -78,6 +78,7 @@ jobs:
MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }} MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }}
FIREBASE_SECRET: ${{ secrets.GPG_SECRET }} FIREBASE_SECRET: ${{ secrets.GPG_SECRET }}
APPLICATION_THEME: ${{ github.event.inputs.theme }} APPLICATION_THEME: ${{ github.event.inputs.theme }}
CREDENTIAL_REGISTRY_EDIT: ${{ github.event.inputs.registry_edit }}
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v3.1.1 uses: actions/upload-artifact@v3.1.1
with: with:

View File

@@ -72,6 +72,7 @@ jobs:
SLACK_URL: '${{ secrets.SLACK_WEBHOOK_DEVOPS }}' SLACK_URL: '${{ secrets.SLACK_WEBHOOK_DEVOPS }}'
MATCH_PASSWORD: '${{ secrets.INJI_IOS_MATCH_PASSWORD }}' MATCH_PASSWORD: '${{ secrets.INJI_IOS_MATCH_PASSWORD }}'
APPLICATION_THEME: ${{ github.event.inputs.theme }} APPLICATION_THEME: ${{ github.event.inputs.theme }}
CREDENTIAL_REGISTRY_EDIT: ${{ github.event.inputs.registry_edit }}
MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }} MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }}
TESTFLIGHT_INTERNAL_TESTERS_GROUP: ${{ github.event.inputs.internal-testers }} TESTFLIGHT_INTERNAL_TESTERS_GROUP: ${{ github.event.inputs.internal-testers }}
TESTFLIGHT_BETA_APP_DESCRIPTION: ${{ github.event.inputs.buildDescription }} TESTFLIGHT_BETA_APP_DESCRIPTION: ${{ github.event.inputs.buildDescription }}

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Dimensions, I18nManager } from 'react-native'; import { Dimensions, I18nManager } from 'react-native';
import { Icon, ListItem, Overlay, Input } from 'react-native-elements'; import { Icon, ListItem, Overlay, Input } from 'react-native-elements';
import { Text, Column, Row, Button } from './ui'; import { Text, Column, Row, Button } from './ui';
@@ -9,6 +9,13 @@ export const EditableListItem: React.FC<EditableListItemProps> = (props) => {
const { t } = useTranslation('common'); const { t } = useTranslation('common');
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [newValue, setNewValue] = useState(props.value); const [newValue, setNewValue] = useState(props.value);
const [overlayOpened, setOverlayOpened] = useState(true);
useEffect(() => {
if (props.credentialRegistryError === 'success') {
closePopup();
}
}, [props.credentialRegistryError]);
return ( return (
<ListItem <ListItem
@@ -26,8 +33,9 @@ export const EditableListItem: React.FC<EditableListItemProps> = (props) => {
<ListItem.Title> <ListItem.Title>
<Text color={Theme.Colors.profileLabel}>{props.label}</Text> <Text color={Theme.Colors.profileLabel}>{props.label}</Text>
</ListItem.Title> </ListItem.Title>
<Text color={Theme.Colors.profileValue}>{props.value}</Text>
</ListItem.Content> </ListItem.Content>
<Text color={Theme.Colors.profileValue}>{props.value}</Text>
<Overlay <Overlay
overlayStyle={{ padding: 24, elevation: 6 }} overlayStyle={{ padding: 24, elevation: 6 }}
isVisible={isEditing} isVisible={isEditing}
@@ -43,6 +51,14 @@ export const EditableListItem: React.FC<EditableListItemProps> = (props) => {
textAlign: I18nManager.isRTL ? 'right' : 'left', textAlign: I18nManager.isRTL ? 'right' : 'left',
}} }}
/> />
{props.credentialRegistryError === 'error' && (
<Text style={Theme.Styles.warningText}>
please try again after sometime...
</Text>
)}
{props.credentialRegistryError === 'success' &&
overlayOpened &&
closePopup()}
<Row> <Row>
<Button fill type="clear" title={t('cancel')} onPress={dismiss} /> <Button fill type="clear" title={t('cancel')} onPress={dismiss} />
<Button fill title={t('save')} onPress={edit} /> <Button fill title={t('save')} onPress={edit} />
@@ -54,12 +70,20 @@ export const EditableListItem: React.FC<EditableListItemProps> = (props) => {
function edit() { function edit() {
props.onEdit(newValue); props.onEdit(newValue);
setIsEditing(false); if (props.credentialRegistryError === undefined) {
setIsEditing(false);
}
} }
function dismiss() { function dismiss() {
setNewValue(props.value); setNewValue(props.value);
setIsEditing(false); setIsEditing(false);
props.credentialRegistryError = '';
}
function closePopup() {
setIsEditing(false);
setOverlayOpened(false);
} }
}; };
@@ -69,4 +93,5 @@ interface EditableListItemProps {
Icon: string; Icon: string;
onEdit: (newValue: string) => void; onEdit: (newValue: string) => void;
display?: 'none' | 'flex'; display?: 'none' | 'flex';
credentialRegistryError: string;
} }

View File

@@ -11,6 +11,7 @@ import { TextItem } from './ui/TextItem';
import { VcItemTags } from './VcItemTags'; import { VcItemTags } from './VcItemTags';
import VerifiedIcon from './VerifiedIcon'; import VerifiedIcon from './VerifiedIcon';
import { getLocalizedField } from '../i18n'; import { getLocalizedField } from '../i18n';
import { CREDENTIAL_REGISTRY_EDIT } from 'react-native-dotenv';
export const VcDetails: React.FC<VcDetailsProps> = (props) => { export const VcDetails: React.FC<VcDetailsProps> = (props) => {
const { t, i18n } = useTranslation('VcDetails'); const { t, i18n } = useTranslation('VcDetails');
@@ -236,6 +237,22 @@ export const VcDetails: React.FC<VcDetailsProps> = (props) => {
</Text> </Text>
</Row> </Row>
</Column> </Column>
{CREDENTIAL_REGISTRY_EDIT === 'true' && (
<Column fill style={Theme.Styles.labelPart}>
<Text
weight="bold"
size="smaller"
color={Theme.Colors.DetailsLabel}>
{t('credentialRegistry')}
</Text>
<Text
weight="semibold"
size="smaller"
color={Theme.Colors.Details}>
{props.vc?.credentialRegistry}
</Text>
</Column>
)}
</Column> </Column>
</Row> </Row>
<VcItemTags tag={props.vc?.tag} /> <VcItemTags tag={props.vc?.tag} />

View File

@@ -302,6 +302,10 @@ export const DefaultTheme = {
placeholder: { placeholder: {
fontFamily: 'Poppins_400Regular', fontFamily: 'Poppins_400Regular',
}, },
warningText: {
color: Colors.Red,
fontSize: 18,
},
}), }),
PinInputStyle: StyleSheet.create({ PinInputStyle: StyleSheet.create({
input: { input: {

View File

@@ -253,6 +253,10 @@ export const PurpleTheme = {
placeholder: { placeholder: {
fontFamily: 'Poppins_400Regular', fontFamily: 'Poppins_400Regular',
}, },
warningText: {
color: Colors.Red,
fontSize: 18,
},
}), }),
PinInputStyle: StyleSheet.create({ PinInputStyle: StyleSheet.create({
input: { input: {

View File

@@ -62,6 +62,7 @@
"no": "رقم", "no": "رقم",
"Alert": "انذار", "Alert": "انذار",
"ok": "تمام", "ok": "تمام",
"credentialRegistry": "سجل الاعتماد",
"errors": { "errors": {
"savingFailed": { "savingFailed": {
"title": "فشل حفظ {{vcLabelSingular}}", "title": "فشل حفظ {{vcLabelSingular}}",
@@ -226,6 +227,7 @@
"name": "اسم", "name": "اسم",
"vcLabel": "تسمية VC", "vcLabel": "تسمية VC",
"language": "اللغة", "language": "اللغة",
"credentialRegistry": "سجل الاعتماد",
"bioUnlock": "افتح مع القياسات الحيوية", "bioUnlock": "افتح مع القياسات الحيوية",
"authFactorUnlock": "إلغاء تأمين عامل المصادقة", "authFactorUnlock": "إلغاء تأمين عامل المصادقة",
"AppMetaData": "حول إنجي", "AppMetaData": "حول إنجي",

View File

@@ -62,6 +62,7 @@
"no": "No", "no": "No",
"Alert": "Alert", "Alert": "Alert",
"ok": "Okay", "ok": "Okay",
"credentialRegistry": "Credential Registry",
"errors": { "errors": {
"savingFailed": { "savingFailed": {
"title": "Failed to save the {{vcLabelSingular}}", "title": "Failed to save the {{vcLabelSingular}}",
@@ -226,6 +227,7 @@
"name": "Name", "name": "Name",
"vcLabel": "VC Label", "vcLabel": "VC Label",
"language": "Language", "language": "Language",
"credentialRegistry": "Credential Registry",
"bioUnlock": "Unlock with biometrics", "bioUnlock": "Unlock with biometrics",
"authFactorUnlock": "Unlock auth factor", "authFactorUnlock": "Unlock auth factor",
"AppMetaData": "About Inji", "AppMetaData": "About Inji",

View File

@@ -62,6 +62,7 @@
"no": "Hindi", "no": "Hindi",
"Alert": "Alerto", "Alert": "Alerto",
"ok": "Sige", "ok": "Sige",
"credentialRegistry": "Registry ng Mga Kredensyal",
"errors": { "errors": {
"savingFailed": { "savingFailed": {
"title": "Nabigong i-save ang {{vcLabelSingular}}", "title": "Nabigong i-save ang {{vcLabelSingular}}",
@@ -226,6 +227,7 @@
"name": "Pangalan", "name": "Pangalan",
"vcLabel": "Panawag sa VC", "vcLabel": "Panawag sa VC",
"language": "Wika", "language": "Wika",
"credentialRegistry": "Registry ng Mga Kredensyal",
"bioUnlock": "I-unlock gamit ang biometrics", "bioUnlock": "I-unlock gamit ang biometrics",
"authFactorUnlock": "Pagbukas ng auth factor", "authFactorUnlock": "Pagbukas ng auth factor",
"AppMetaData": "Tungkol kay Inji", "AppMetaData": "Tungkol kay Inji",

View File

@@ -62,6 +62,7 @@
"no": "नहीं", "no": "नहीं",
"Alert": "चेतावनी", "Alert": "चेतावनी",
"ok": "ठीक", "ok": "ठीक",
"credentialRegistry": "साख रजिस्ट्री",
"errors": { "errors": {
"savingFailed": { "savingFailed": {
"title": "{{vcLabelSingular}} सहेजने में विफल", "title": "{{vcLabelSingular}} सहेजने में विफल",
@@ -228,6 +229,7 @@
"name": "नाम", "name": "नाम",
"vcLabel": "वीसी लेबल", "vcLabel": "वीसी लेबल",
"language": "भाषा", "language": "भाषा",
"credentialRegistry": "साख रजिस्ट्री",
"bioUnlock": "बायोमेट्रिक्स से अनलॉक करें", "bioUnlock": "बायोमेट्रिक्स से अनलॉक करें",
"authFactorUnlock": "अनलॉक ऑथ फैक्टर", "authFactorUnlock": "अनलॉक ऑथ फैक्टर",
"AppMetaData": "इंजी के बारे में", "AppMetaData": "इंजी के बारे में",

View File

@@ -62,6 +62,7 @@
"no": "ಸಂ", "no": "ಸಂ",
"Alert": "ಎಚ್ಚರಿಕೆ", "Alert": "ಎಚ್ಚರಿಕೆ",
"ok": "ಸರಿ", "ok": "ಸರಿ",
"credentialRegistry": "ರುಜುವಾತುಗಳ ನೋಂದಣಿ",
"errors": { "errors": {
"savingFailed": { "savingFailed": {
"title": "{{vcLabelSingular}} ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ", "title": "{{vcLabelSingular}} ಉಳಿಸಲು ವಿಫಲವಾಗಿದೆ",
@@ -226,6 +227,7 @@
"name": "ಹೆಸರು", "name": "ಹೆಸರು",
"vcLabel": "VC ಲೇಬಲ್", "vcLabel": "VC ಲೇಬಲ್",
"language": "ಭಾಷೆ", "language": "ಭಾಷೆ",
"credentialRegistry": "ರುಜುವಾತುಗಳ ನೋಂದಣಿ",
"bioUnlock": "ಬಯೋಮೆಟ್ರಿಕ್‌ಗಳೊಂದಿಗೆ ಅನ್‌ಲಾಕ್ ಮಾಡಿ", "bioUnlock": "ಬಯೋಮೆಟ್ರಿಕ್‌ಗಳೊಂದಿಗೆ ಅನ್‌ಲಾಕ್ ಮಾಡಿ",
"authFactorUnlock": "ಅನ್ಲಾಕ್ ದೃಢೀಕರಣ ಅಂಶ", "authFactorUnlock": "ಅನ್ಲಾಕ್ ದೃಢೀಕರಣ ಅಂಶ",
"AppMetaData": "ಇಂಜಿ ಬಗ್ಗೆ", "AppMetaData": "ಇಂಜಿ ಬಗ್ಗೆ",

View File

@@ -62,6 +62,7 @@
"no": "இல்லை", "no": "இல்லை",
"Alert": "எச்சரிக்கை", "Alert": "எச்சரிக்கை",
"ok": "சரி", "ok": "சரி",
"credentialRegistry": "நற்சான்றிதழ்கள் பதிவு",
"errors": { "errors": {
"savingFailed": { "savingFailed": {
"title": "{{vcLabelSingular}}ஐ சேமிப்பதில் தோல்வி", "title": "{{vcLabelSingular}}ஐ சேமிப்பதில் தோல்வி",
@@ -226,6 +227,7 @@
"name": "பெயர்", "name": "பெயர்",
"vcLabel": "VC லேபிள்", "vcLabel": "VC லேபிள்",
"language": "மொழி", "language": "மொழி",
"credentialRegistry": "நற்சான்றிதழ்கள் பதிவு",
"bioUnlock": "பயோமெட்ரிக்ஸ் மூலம் திறக்கவும்", "bioUnlock": "பயோமெட்ரிக்ஸ் மூலம் திறக்கவும்",
"authFactorUnlock": "அங்கீகார காரணியைத் திற", "authFactorUnlock": "அங்கீகார காரணியைத் திற",
"AppMetaData": "இன்ஜி பற்றி", "AppMetaData": "இன்ஜி பற்றி",

View File

@@ -9,7 +9,7 @@ import { EventFrom, spawn, StateFrom, send, assign, AnyState } from 'xstate';
import { createModel } from 'xstate/lib/model'; import { createModel } from 'xstate/lib/model';
import { authMachine, createAuthMachine } from './auth'; import { authMachine, createAuthMachine } from './auth';
import { createSettingsMachine, settingsMachine } from './settings'; import { createSettingsMachine, settingsMachine } from './settings';
import { storeMachine } from './store'; import { StoreEvents, storeMachine } from './store';
import { createVcMachine, vcMachine } from './vc'; import { createVcMachine, vcMachine } from './vc';
import { createActivityLogMachine, activityLogMachine } from './activityLog'; import { createActivityLogMachine, activityLogMachine } from './activityLog';
import { createRequestMachine, requestMachine } from './request'; import { createRequestMachine, requestMachine } from './request';
@@ -22,6 +22,11 @@ import { pure, respond } from 'xstate/lib/actions';
import { AppServices } from '../shared/GlobalContext'; import { AppServices } from '../shared/GlobalContext';
import { request } from '../shared/request'; import { request } from '../shared/request';
import { isBLEEnabled } from '../lib/smartshare'; import { isBLEEnabled } from '../lib/smartshare';
import {
changeCrendetialRegistry,
SETTINGS_STORE_KEY,
} from '../shared/constants';
import { MIMOTO_HOST } from 'react-native-dotenv';
const model = createModel( const model = createModel(
{ {
@@ -39,6 +44,7 @@ const model = createModel(
READY: (data?: unknown) => ({ data }), READY: (data?: unknown) => ({ data }),
APP_INFO_RECEIVED: (info: AppInfo) => ({ info }), APP_INFO_RECEIVED: (info: AppInfo) => ({ info }),
BACKEND_INFO_RECEIVED: (info: BackendInfo) => ({ info }), BACKEND_INFO_RECEIVED: (info: BackendInfo) => ({ info }),
STORE_RESPONSE: (response: unknown) => ({ response }),
}, },
} }
); );
@@ -67,7 +73,16 @@ export const appMachine = model.createMachine(
services: { services: {
entry: ['spawnServiceActors', 'logServiceEvents'], entry: ['spawnServiceActors', 'logServiceEvents'],
on: { on: {
READY: 'info', READY: 'credentialRegistry',
},
},
credentialRegistry: {
entry: ['loadCredentialRegistryHostFromStorage'],
on: {
STORE_RESPONSE: {
actions: ['loadCredentialRegistryInConstants'],
target: 'info',
},
}, },
}, },
info: { info: {
@@ -239,6 +254,21 @@ export const appMachine = model.createMachine(
setBackendInfo: model.assign({ setBackendInfo: model.assign({
backendInfo: (_, event) => event.info, 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: { services: {

View File

@@ -19,6 +19,8 @@ export interface Typegen0 {
}; };
'eventsCausingActions': { 'eventsCausingActions': {
forwardToServices: 'ACTIVE' | 'INACTIVE' | 'OFFLINE' | 'ONLINE'; forwardToServices: 'ACTIVE' | 'INACTIVE' | 'OFFLINE' | 'ONLINE';
loadCredentialRegistryHostFromStorage: 'READY';
loadCredentialRegistryInConstants: 'STORE_RESPONSE';
logServiceEvents: 'READY'; logServiceEvents: 'READY';
logStoreEvents: 'xstate.init'; logStoreEvents: 'xstate.init';
requestDeviceInfo: 'REQUEST_DEVICE_INFO'; requestDeviceInfo: 'REQUEST_DEVICE_INFO';
@@ -32,11 +34,12 @@ export interface Typegen0 {
'eventsCausingServices': { 'eventsCausingServices': {
checkFocusState: 'BACKEND_INFO_RECEIVED'; checkFocusState: 'BACKEND_INFO_RECEIVED';
checkNetworkState: 'BACKEND_INFO_RECEIVED'; checkNetworkState: 'BACKEND_INFO_RECEIVED';
getAppInfo: 'READY'; getAppInfo: 'STORE_RESPONSE';
getBackendInfo: 'APP_INFO_RECEIVED'; getBackendInfo: 'APP_INFO_RECEIVED';
}; };
'matchesStates': 'matchesStates':
| 'init' | 'init'
| 'init.credentialRegistry'
| 'init.devinfo' | 'init.devinfo'
| 'init.info' | 'init.info'
| 'init.services' | 'init.services'
@@ -51,7 +54,7 @@ export interface Typegen0 {
| 'ready.network.offline' | 'ready.network.offline'
| 'ready.network.online' | 'ready.network.online'
| { | {
init?: 'devinfo' | 'info' | 'services' | 'store'; init?: 'credentialRegistry' | 'devinfo' | 'info' | 'services' | 'store';
ready?: ready?:
| 'focus' | 'focus'
| 'network' | 'network'

View File

@@ -1,9 +1,13 @@
import { ContextFrom, EventFrom, send, StateFrom } from 'xstate'; import { ContextFrom, EventFrom, send, StateFrom } from 'xstate';
import { createModel } from 'xstate/lib/model'; import { createModel } from 'xstate/lib/model';
import { AppServices } from '../shared/GlobalContext'; import { AppServices } from '../shared/GlobalContext';
import { SETTINGS_STORE_KEY } from '../shared/constants'; import { HOST, SETTINGS_STORE_KEY } from '../shared/constants';
import { VCLabel } from '../types/vc'; import { VCLabel } from '../types/vc';
import { StoreEvents } from './store'; import { StoreEvents } from './store';
import getAllConfigurations, {
COMMON_PROPS_KEY,
} from '../shared/commonprops/commonProps';
import Storage from '../shared/storage';
const model = createModel( const model = createModel(
{ {
@@ -14,6 +18,8 @@ const model = createModel(
plural: 'Cards', plural: 'Cards',
} as VCLabel, } as VCLabel,
isBiometricUnlockEnabled: false, isBiometricUnlockEnabled: false,
credentialRegistry: HOST,
credentialRegistryError: '',
}, },
{ {
events: { events: {
@@ -22,6 +28,12 @@ const model = createModel(
TOGGLE_BIOMETRIC_UNLOCK: (enable: boolean) => ({ enable }), TOGGLE_BIOMETRIC_UNLOCK: (enable: boolean) => ({ enable }),
STORE_RESPONSE: (response: unknown) => ({ response }), STORE_RESPONSE: (response: unknown) => ({ response }),
CHANGE_LANGUAGE: (language: string) => ({ language }), CHANGE_LANGUAGE: (language: string) => ({ language }),
UPDATE_CREDENTIAL_REGISTRY: (credentialRegistry: string) => ({
credentialRegistry,
}),
UPDATE_CREDENTIAL_REGISTRY_ERROR: (credentialRegistryError: string) => ({
credentialRegistryError,
}),
}, },
} }
); );
@@ -66,6 +78,26 @@ export const settingsMachine = model.createMachine(
UPDATE_VC_LABEL: { UPDATE_VC_LABEL: {
actions: ['updateVcLabel', 'storeContext'], actions: ['updateVcLabel', 'storeContext'],
}, },
UPDATE_CREDENTIAL_REGISTRY: {
actions: ['resetCredentialRegistry'],
target: 'resetInjiProps',
},
},
},
resetInjiProps: {
invoke: {
src: 'resetInjiProps',
onDone: {
actions: [
'updateCredentialRegistrySuccess',
'updateCredentialRegistry',
],
target: 'idle',
},
onError: {
actions: ['updateCredentialRegistryError'],
target: 'idle',
},
}, },
}, },
}, },
@@ -102,13 +134,41 @@ export const settingsMachine = model.createMachine(
plural: event.label + 's', plural: event.label + 's',
}), }),
}), }),
updateCredentialRegistry: model.assign({
credentialRegistry: (_context, event) => event.data.warningDomainName,
}),
updateCredentialRegistryError: model.assign({
credentialRegistryError: () => 'error',
}),
updateCredentialRegistrySuccess: model.assign({
credentialRegistryError: () => 'success',
}),
resetCredentialRegistry: model.assign({
credentialRegistryError: () => {
console.log('resetCredentialRegistry : called');
return '';
},
}),
toggleBiometricUnlock: model.assign({ toggleBiometricUnlock: model.assign({
isBiometricUnlockEnabled: (_, event) => event.enable, 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: { guards: {
hasData: (_, event) => event.response != null, hasData: (_, event) => event.response != null,
@@ -133,6 +193,13 @@ export function selectVcLabel(state: State) {
return state.context.vcLabel; return state.context.vcLabel;
} }
export function selectCredentialRegistry(state: State) {
return state.context.credentialRegistry;
}
export function selectCredentialRegistryError(state: State) {
return state.context.credentialRegistryError;
}
export function selectBiometricUnlockEnabled(state: State) { export function selectBiometricUnlockEnabled(state: State) {
return state.context.isBiometricUnlockEnabled; return state.context.isBiometricUnlockEnabled;
} }

View File

@@ -1,38 +1,51 @@
// This file was automatically generated. Edits will be overwritten
// This file was automatically generated. Edits will be overwritten export interface Typegen0 {
'@@xstate/typegen': true;
export interface Typegen0 { 'internalEvents': {
'@@xstate/typegen': true; 'done.invoke.settings.resetInjiProps:invocation[0]': {
internalEvents: { type: 'done.invoke.settings.resetInjiProps:invocation[0]';
"xstate.init": { type: "xstate.init" }; data: unknown;
}; __tip: 'See the XState TS docs to learn how to strongly type this.';
invokeSrcNameMap: { };
'error.platform.settings.resetInjiProps:invocation[0]': {
}; type: 'error.platform.settings.resetInjiProps:invocation[0]';
missingImplementations: { data: unknown;
actions: never; };
delays: never; 'xstate.init': { type: 'xstate.init' };
guards: never; };
services: never; 'invokeSrcNameMap': {
}; resetInjiProps: 'done.invoke.settings.resetInjiProps:invocation[0]';
eventsCausingActions: { };
"requestStoredContext": "xstate.init"; 'missingImplementations': {
"setContext": "STORE_RESPONSE"; actions: never;
"storeContext": "STORE_RESPONSE" | "TOGGLE_BIOMETRIC_UNLOCK" | "UPDATE_NAME" | "UPDATE_VC_LABEL"; delays: never;
"toggleBiometricUnlock": "TOGGLE_BIOMETRIC_UNLOCK"; guards: never;
"updateName": "UPDATE_NAME"; services: never;
"updateVcLabel": "UPDATE_VC_LABEL"; };
}; 'eventsCausingActions': {
eventsCausingDelays: { requestStoredContext: 'xstate.init';
resetCredentialRegistry: 'UPDATE_CREDENTIAL_REGISTRY';
}; setContext: 'STORE_RESPONSE';
eventsCausingGuards: { storeContext:
"hasData": "STORE_RESPONSE"; | 'STORE_RESPONSE'
}; | 'TOGGLE_BIOMETRIC_UNLOCK'
eventsCausingServices: { | 'UPDATE_NAME'
| 'UPDATE_VC_LABEL';
}; toggleBiometricUnlock: 'TOGGLE_BIOMETRIC_UNLOCK';
matchesStates: "idle" | "init" | "storingDefaults"; updateCredentialRegistry: 'done.invoke.settings.resetInjiProps:invocation[0]';
tags: never; updateCredentialRegistryError: 'error.platform.settings.resetInjiProps:invocation[0]';
} updateCredentialRegistrySuccess: 'done.invoke.settings.resetInjiProps:invocation[0]';
updateName: 'UPDATE_NAME';
updateVcLabel: 'UPDATE_VC_LABEL';
};
'eventsCausingDelays': {};
'eventsCausingGuards': {
hasData: 'STORE_RESPONSE';
};
'eventsCausingServices': {
resetInjiProps: 'UPDATE_CREDENTIAL_REGISTRY';
};
'matchesStates': 'idle' | 'init' | 'resetInjiProps' | 'storingDefaults';
'tags': never;
}

View File

@@ -1,6 +1,6 @@
import { assign, ErrorPlatformEvent, EventFrom, send, StateFrom } from 'xstate'; import { assign, ErrorPlatformEvent, EventFrom, send, StateFrom } from 'xstate';
import { createModel } from 'xstate/lib/model'; 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 } from '../shared/constants';
import { AppServices } from '../shared/GlobalContext'; import { AppServices } from '../shared/GlobalContext';
import { CredentialDownloadResponse, request } from '../shared/request'; import { CredentialDownloadResponse, request } from '../shared/request';
import { import {
@@ -647,6 +647,7 @@ export const vcItemMachine =
storeContext: send( storeContext: send(
(context) => { (context) => {
const { serviceRefs, ...data } = context; const { serviceRefs, ...data } = context;
data.credentialRegistry = HOST;
return StoreEvents.SET(VC_ITEM_STORE_KEY(context), data); return StoreEvents.SET(VC_ITEM_STORE_KEY(context), data);
}, },
{ {

View File

@@ -14,6 +14,7 @@ import { LanguageSelector } from '../../components/LanguageSelector';
import i18next, { SUPPORTED_LANGUAGES } from '../../i18n'; import i18next, { SUPPORTED_LANGUAGES } from '../../i18n';
import { ScrollView } from 'react-native-gesture-handler'; import { ScrollView } from 'react-native-gesture-handler';
import { AppMetaData } from './AppMetaData'; import { AppMetaData } from './AppMetaData';
import { CREDENTIAL_REGISTRY_EDIT } from 'react-native-dotenv';
const LanguageSetting: React.FC = () => { const LanguageSetting: React.FC = () => {
const { t } = useTranslation('ProfileScreen'); const { t } = useTranslation('ProfileScreen');
@@ -120,6 +121,15 @@ export const ProfileScreen: React.FC<MainRouteProps> = (props) => {
label={t('AppMetaData')} label={t('AppMetaData')}
color={Theme.Colors.profileLabel} color={Theme.Colors.profileLabel}
/> />
{CREDENTIAL_REGISTRY_EDIT === 'true' && (
<EditableListItem
label={t('credentialRegistry')}
value={controller.credentialRegistry}
credentialRegistryError={controller.credentialRegistryError}
onEdit={controller.UPDATE_CREDENTIAL_REGISTRY}
Icon="star"
/>
)}
<ListItem bottomDivider onPress={controller.LOGOUT}> <ListItem bottomDivider onPress={controller.LOGOUT}>
<Icon <Icon
name="logout" name="logout"

View File

@@ -10,7 +10,9 @@ import {
import { import {
selectBiometricUnlockEnabled, selectBiometricUnlockEnabled,
selectName, selectName,
selectCredentialRegistryError,
selectVcLabel, selectVcLabel,
selectCredentialRegistry,
SettingsEvents, SettingsEvents,
} from '../../machines/settings'; } from '../../machines/settings';
@@ -96,6 +98,11 @@ export function useProfileScreen({ navigation }: MainRouteProps) {
backendInfo: useSelector(appService, selectBackendInfo), backendInfo: useSelector(appService, selectBackendInfo),
name: useSelector(settingsService, selectName), name: useSelector(settingsService, selectName),
vcLabel: useSelector(settingsService, selectVcLabel), vcLabel: useSelector(settingsService, selectVcLabel),
credentialRegistry: useSelector(settingsService, selectCredentialRegistry),
credentialRegistryError: useSelector(
settingsService,
selectCredentialRegistryError
),
isBiometricUnlockEnabled: useSelector( isBiometricUnlockEnabled: useSelector(
settingsService, settingsService,
selectBiometricUnlockEnabled selectBiometricUnlockEnabled
@@ -109,6 +116,16 @@ export function useProfileScreen({ navigation }: MainRouteProps) {
UPDATE_VC_LABEL: (label: string) => UPDATE_VC_LABEL: (label: string) =>
settingsService.send(SettingsEvents.UPDATE_VC_LABEL(label)), settingsService.send(SettingsEvents.UPDATE_VC_LABEL(label)),
UPDATE_CREDENTIAL_REGISTRY: (credentialRegistry: string) =>
settingsService.send(
SettingsEvents.UPDATE_CREDENTIAL_REGISTRY(credentialRegistry)
),
UPDATE_CREDENTIAL_REGISTRY_ERROR: (credentialRegistryError: string) =>
settingsService.send(
SettingsEvents.UPDATE_CREDENTIAL_REGISTRY_ERROR(credentialRegistryError)
),
TOGGLE_BIOMETRIC: (enable: boolean) => TOGGLE_BIOMETRIC: (enable: boolean) =>
settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(enable)), settingsService.send(SettingsEvents.TOGGLE_BIOMETRIC_UNLOCK(enable)),

View File

@@ -1,12 +1,14 @@
import { request } from '../request'; import { request } from '../request';
import Storage from '../storage'; import Storage from '../storage';
import { init } from 'mosip-inji-face-sdk'; 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'; 'CommonPropsKey-' + '6964d04a-9268-11ed-a1eb-0242ac120002';
export default async function getAllConfigurations() { export default async function getAllConfigurations(host = undefined) {
try { try {
host && changeCrendetialRegistry(host);
var response = await Storage.getItem(COMMON_PROPS_KEY); var response = await Storage.getItem(COMMON_PROPS_KEY);
if (response) { if (response) {
return JSON.parse(response); return JSON.parse(response);

View File

@@ -4,7 +4,9 @@ import {
GOOGLE_NEARBY_MESSAGES_API_KEY, GOOGLE_NEARBY_MESSAGES_API_KEY,
} from 'react-native-dotenv'; } from 'react-native-dotenv';
export const HOST = MIMOTO_HOST; export let HOST = MIMOTO_HOST;
export const changeCrendetialRegistry = (host) => (HOST = host);
export const MY_VCS_STORE_KEY = 'myVCs'; export const MY_VCS_STORE_KEY = 'myVCs';

View File

@@ -36,6 +36,14 @@ class Storage {
} }
}; };
static removeItem = async (key: string) => {
if (vcKeyRegExp.exec(key)) {
const path = getFilePath(key);
return await unlink(path);
}
MMKV.removeItem(key);
};
static clear = async () => { static clear = async () => {
try { try {
(await exists(`${vcDirectoryPath}`)) && (await exists(`${vcDirectoryPath}`)) &&

View File

@@ -18,4 +18,9 @@ declare module 'react-native-dotenv' {
* Flag for Toggling Purple Theme and Default Theme * Flag for Toggling Purple Theme and Default Theme
*/ */
export const APPLICATION_THEME: string; export const APPLICATION_THEME: string;
/**
* Flag for Toggling environment url
*/
export const CREDENTIAL_REGISTRY_EDIT: string;
} }

View File

@@ -15,6 +15,7 @@ export interface VC {
reason?: VCSharingReason[]; reason?: VCSharingReason[];
shouldVerifyPresence?: boolean; shouldVerifyPresence?: boolean;
walletBindingResponse?: WalletBindingResponse; walletBindingResponse?: WalletBindingResponse;
credentialRegistry: string;
} }
export interface VCSharingReason { export interface VCSharingReason {