From 3e2c6f2886f15c5f933f19ea32ad7d94a3eed6ce Mon Sep 17 00:00:00 2001 From: Reuben Mangubat Date: Thu, 19 May 2022 18:13:01 +0800 Subject: [PATCH 01/11] Add intent link for launching via 3rd party ODK Collect --- android/app/src/main/AndroidManifest.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 88adffa08f..5d4dd97926 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,7 +30,7 @@ - + @@ -41,6 +41,10 @@ + + + + From 1fdd924050cca49ac79fac03d8ec93eb82525bc1 Mon Sep 17 00:00:00 2001 From: Paolo Miguel de Leon Date: Wed, 25 May 2022 18:13:23 +0800 Subject: [PATCH 02/11] chore: cleanup unused code --- shared/ModelEvents.ts | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 shared/ModelEvents.ts diff --git a/shared/ModelEvents.ts b/shared/ModelEvents.ts deleted file mode 100644 index 8ac0695f6b..0000000000 --- a/shared/ModelEvents.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ActorRefFrom } from 'xstate'; -import { vcItemMachine } from '../machines/vcItem'; - -export const VcTabEvents = { - VIEW_VC: (vcItemActor: ActorRefFrom) => ({ - vcItemActor, - }), - REFRESH: () => ({}), -}; - -export const StoreEvents = { - STORE_RESPONSE: (response: unknown) => ({ response }), - STORE_ERROR: (error: Error) => ({ error }), -}; - -export const ModalEvents = { - DISMISS: () => ({}), -}; - -export const GenericEvents = { - ERROR: (error: Error) => ({ error }), -}; From 977842ee8f088a8527cf4ccddc9bc14d15a45b68 Mon Sep 17 00:00:00 2001 From: Paolo Miguel de Leon Date: Wed, 25 May 2022 18:25:06 +0800 Subject: [PATCH 03/11] feat: add intent for sharing VC data with ODK --- .../io/mosip/residentapp/MainApplication.java | 3 +- .../io/mosip/residentapp/ODKIntentModule.java | 51 +++++++++++++++++++ .../mosip/residentapp/ODKIntentPackage.java | 27 ++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 android/app/src/main/java/io/mosip/residentapp/ODKIntentModule.java create mode 100644 android/app/src/main/java/io/mosip/residentapp/ODKIntentPackage.java diff --git a/android/app/src/main/java/io/mosip/residentapp/MainApplication.java b/android/app/src/main/java/io/mosip/residentapp/MainApplication.java index 80c0d4bf5c..1125ff03d9 100644 --- a/android/app/src/main/java/io/mosip/residentapp/MainApplication.java +++ b/android/app/src/main/java/io/mosip/residentapp/MainApplication.java @@ -18,7 +18,6 @@ import expo.modules.ReactNativeHostWrapper; import timber.log.Timber; -import com.facebook.react.bridge.JSIModulePackage; import com.google.firebase.analytics.FirebaseAnalytics; import com.google.firebase.crashlytics.FirebaseCrashlytics; @@ -39,7 +38,7 @@ protected List getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); // Packages that cannot be autolinked yet can be added manually here, for example: - // packages.add(new MyReactNativePackage()); + packages.add(new ODKIntentPackage()); return packages; } diff --git a/android/app/src/main/java/io/mosip/residentapp/ODKIntentModule.java b/android/app/src/main/java/io/mosip/residentapp/ODKIntentModule.java new file mode 100644 index 0000000000..fe1df27131 --- /dev/null +++ b/android/app/src/main/java/io/mosip/residentapp/ODKIntentModule.java @@ -0,0 +1,51 @@ +package io.mosip.residentapp; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; + +public class ODKIntentModule extends ReactContextBaseJavaModule { + + @Override + public String getName() { + return "ODKIntentModule"; + } + + ODKIntentModule(ReactApplicationContext context) { + super(context); + } + + @ReactMethod + public void isRequestIntent(Promise promise) { + Activity activity = getCurrentActivity(); + Intent intent = activity.getIntent(); + + String action = intent.getAction(); + if (action == "io.mosip.residentapp.odk.REQUEST") { + promise.resolve(true); + } else { + promise.resolve(false); + } + } + + @ReactMethod + public void sendBundleResult(ReadableMap vcData) { + Activity activity = getCurrentActivity(); + + Intent result = new Intent(); + Bundle vcBundle = new Bundle(Arguments.toBundle(vcData)); + for (String key : vcBundle.keySet()) { + result.putExtra(key, vcBundle.getString(key)); + } + + activity.setResult(Activity.RESULT_OK, result); + activity.finish(); + } +} diff --git a/android/app/src/main/java/io/mosip/residentapp/ODKIntentPackage.java b/android/app/src/main/java/io/mosip/residentapp/ODKIntentPackage.java new file mode 100644 index 0000000000..ba4d42dd3f --- /dev/null +++ b/android/app/src/main/java/io/mosip/residentapp/ODKIntentPackage.java @@ -0,0 +1,27 @@ +package io.mosip.residentapp; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ODKIntentPackage implements ReactPackage { + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + + modules.add(new ODKIntentModule(reactContext)); + + return modules; + } +} From 584aaa8f85d92ffbd1344e4e8bb034bfc4a678ac Mon Sep 17 00:00:00 2001 From: Paolo Miguel de Leon Date: Wed, 25 May 2022 18:37:31 +0800 Subject: [PATCH 04/11] feat: integrate ODK intent with app --- .../ODKIntentModule.ts | 22 +++++++++++++++++++ machines/request.ts | 19 +++++++++++++++- machines/request.typegen.ts | 1 + screens/MainLayout.tsx | 16 ++++++++++---- 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 lib/react-native-odk-intent/ODKIntentModule.ts diff --git a/lib/react-native-odk-intent/ODKIntentModule.ts b/lib/react-native-odk-intent/ODKIntentModule.ts new file mode 100644 index 0000000000..4afcd4e008 --- /dev/null +++ b/lib/react-native-odk-intent/ODKIntentModule.ts @@ -0,0 +1,22 @@ +import { NativeModules } from 'react-native'; +const { ODKIntentModule } = NativeModules; + +export enum ODKIntentVcField { + UIN = 'uin', + FullName = 'full_name', + DateOfBirth = 'date_of_birth', + Email = 'email', + Phone = 'phone', + Biometrics = 'biometrics', + Issuer = 'issuer', + IssuanceDate = 'issuance_date', +} + +export type ODKIntentVcData = Record; + +interface ODKIntentInterface { + isRequestIntent: () => Promise; + sendBundleResult: (vcData: ODKIntentVcData) => void; +} + +export default ODKIntentModule as ODKIntentInterface; diff --git a/machines/request.ts b/machines/request.ts index 8ac7eb4573..84822d36e6 100644 --- a/machines/request.ts +++ b/machines/request.ts @@ -1,5 +1,6 @@ import SmartShare from '@idpass/smartshare-react-native'; import BluetoothStateManager from 'react-native-bluetooth-state-manager'; +import ODKIntentModule from '../lib/react-native-odk-intent/ODKIntentModule'; import { EmitterSubscription } from 'react-native'; import { assign, EventFrom, send, sendParent, StateFrom } from 'xstate'; import { createModel } from 'xstate/lib/model'; @@ -198,7 +199,7 @@ export const requestMachine = model.createMachine( }, accepted: { id: 'accepted', - entry: ['sendVcReceived', 'logReceived'], + entry: ['sendVcReceived', 'logReceived', 'sendVcDataToOdk'], invoke: { src: 'sendVcResponse', data: { @@ -349,6 +350,22 @@ export const requestMachine = model.createMachine( }, { to: (context) => context.serviceRefs.vc } ), + + sendVcDataToOdk: (context) => { + const { verifiableCredential } = context.incomingVc; + const { credentialSubject: subject } = verifiableCredential; + + ODKIntentModule.sendBundleResult({ + biometrics: subject.biometrics, + date_of_birth: subject.dateOfBirth, + email: subject.email, + full_name: subject.fullName, + issuance_date: verifiableCredential.issuanceDate, + issuer: verifiableCredential.issuer, + phone: subject.phone, + uin: subject.UIN, + }); + }, }, services: { diff --git a/machines/request.typegen.ts b/machines/request.typegen.ts index a02984fe64..c20f941a2a 100644 --- a/machines/request.typegen.ts +++ b/machines/request.typegen.ts @@ -23,6 +23,7 @@ export interface Typegen0 { storeVc: 'STORE_RESPONSE'; sendVcReceived: 'STORE_RESPONSE'; logReceived: 'STORE_RESPONSE'; + sendVcDataToOdk: 'STORE_RESPONSE'; }; 'internalEvents': { 'xstate.after(CLEAR_DELAY)#clearingConnection': { diff --git a/screens/MainLayout.tsx b/screens/MainLayout.tsx index bcfaca4895..6132d84851 100644 --- a/screens/MainLayout.tsx +++ b/screens/MainLayout.tsx @@ -1,18 +1,18 @@ -import React from 'react'; +import React, { useEffect } 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 { MainRouteProps, mainRoutes } from '../routes/main'; import { LanguageSelector } from '../components/LanguageSelector'; import { Colors } from '../components/ui/styleUtils'; import { useTranslation } from 'react-i18next'; +import ODKIntentModule from '../lib/react-native-odk-intent/ODKIntentModule'; const { Navigator, Screen } = createBottomTabNavigator(); -export const MainLayout: React.FC = () => { +export const MainLayout: React.FC = (props) => { const { t } = useTranslation('MainLayout'); const options: BottomTabNavigationOptions = { @@ -29,6 +29,14 @@ export const MainLayout: React.FC = () => { tabBarStyle: { height: 86, paddingHorizontal: 36 }, }; + useEffect(() => { + ODKIntentModule.isRequestIntent().then((result) => { + if (result) { + props.navigation.navigate('Request'); + } + }); + }, []); + return ( {mainRoutes.map((route) => ( From e8dc325932b929d7d40e8fd38162aca5c8965b50 Mon Sep 17 00:00:00 2001 From: Paolo Miguel de Leon Date: Fri, 27 May 2022 19:17:30 +0800 Subject: [PATCH 05/11] refactor: move intent check to app init --- machines/app.ts | 33 +++++++++++++++++++-- machines/app.typegen.ts | 15 ++++++++-- machines/request.ts | 59 +++++++++++++++++++++++++++++-------- machines/request.typegen.ts | 11 ++++--- routes/index.ts | 2 +- screens/MainLayout.tsx | 18 ++++++----- 6 files changed, 108 insertions(+), 30 deletions(-) diff --git a/machines/app.ts b/machines/app.ts index 15817d2778..3bc9d6e5a3 100644 --- a/machines/app.ts +++ b/machines/app.ts @@ -16,11 +16,13 @@ import { createRequestMachine, requestMachine } from './request'; import { createScanMachine, scanMachine } from './scan'; import { pure, respond } from 'xstate/lib/actions'; import { AppServices } from '../shared/GlobalContext'; +import ODKIntentModule from '../lib/react-native-odk-intent/ODKIntentModule'; const model = createModel( { info: {} as AppInfo, serviceRefs: {} as AppServices, + isRequestIntent: false, }, { events: { @@ -41,13 +43,25 @@ export const appMachine = model.createMachine( schema: { context: model.initialContext, events: {} as EventFrom, + services: {} as { + checkIntent: { data: boolean }; + }, }, id: 'app', initial: 'init', states: { init: { - initial: 'store', + initial: 'intent', states: { + intent: { + invoke: { + src: 'checkIntent', + onDone: { + target: 'store', + actions: 'setIntent', + }, + }, + }, store: { entry: ['spawnStoreActor', 'logStoreEvents'], on: { @@ -126,6 +140,10 @@ export const appMachine = model.createMachine( }, { actions: { + setIntent: assign({ + isRequestIntent: (_context, event) => event.data, + }), + forwardToServices: pure((context, event) => Object.values(context.serviceRefs).map((serviceRef) => send({ ...event, type: `APP_${event.type}` }, { to: serviceRef }) @@ -176,7 +194,10 @@ export const appMachine = model.createMachine( scanMachine.id ); serviceRefs.request = spawn( - createRequestMachine(serviceRefs), + createRequestMachine({ + serviceRefs, + isRequestIntent: context.isRequestIntent, + }), requestMachine.id ); return serviceRefs; @@ -200,6 +221,10 @@ export const appMachine = model.createMachine( }, services: { + checkIntent: () => { + return ODKIntentModule.isRequestIntent(); + }, + getAppInfo: () => async (callback) => { const appInfo = { deviceId: getDeviceId(), @@ -263,6 +288,10 @@ export function selectAppInfo(state: State) { return state.context.info; } +export function selectIsRequestIntent(state: State) { + return state.context.isRequestIntent; // TODO: change to state 'ready.intent.request' +} + export function selectIsReady(state: State) { return state.matches('ready'); } diff --git a/machines/app.typegen.ts b/machines/app.typegen.ts index 1f0b0536db..3ea208ea3c 100644 --- a/machines/app.typegen.ts +++ b/machines/app.typegen.ts @@ -3,18 +3,25 @@ export interface Typegen0 { '@@xstate/typegen': true; 'eventsCausingActions': { + setIntent: 'done.invoke.app.init.intent:invocation[0]'; setAppInfo: 'APP_INFO_RECEIVED'; requestDeviceInfo: 'REQUEST_DEVICE_INFO'; - spawnStoreActor: 'xstate.init'; - logStoreEvents: 'xstate.init'; + spawnStoreActor: 'done.invoke.app.init.intent:invocation[0]'; + logStoreEvents: 'done.invoke.app.init.intent:invocation[0]'; spawnServiceActors: 'READY'; logServiceEvents: 'READY'; forwardToServices: 'ACTIVE' | 'INACTIVE' | 'ONLINE' | 'OFFLINE'; }; 'internalEvents': { + 'done.invoke.app.init.intent:invocation[0]': { + type: 'done.invoke.app.init.intent:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; 'xstate.init': { type: 'xstate.init' }; }; 'invokeSrcNameMap': { + checkIntent: 'done.invoke.app.init.intent:invocation[0]'; getAppInfo: 'done.invoke.app.init.info:invocation[0]'; checkFocusState: 'done.invoke.app.ready.focus:invocation[0]'; checkNetworkState: 'done.invoke.app.ready.network:invocation[0]'; @@ -26,6 +33,7 @@ export interface Typegen0 { delays: never; }; 'eventsCausingServices': { + checkIntent: 'xstate.init'; getAppInfo: 'READY'; checkFocusState: 'xstate.init'; checkNetworkState: 'xstate.init'; @@ -34,6 +42,7 @@ export interface Typegen0 { 'eventsCausingDelays': {}; 'matchesStates': | 'init' + | 'init.intent' | 'init.store' | 'init.services' | 'init.info' @@ -47,7 +56,7 @@ export interface Typegen0 { | 'ready.network.online' | 'ready.network.offline' | { - init?: 'store' | 'services' | 'info'; + init?: 'intent' | 'store' | 'services' | 'info'; ready?: | 'focus' | 'network' diff --git a/machines/request.ts b/machines/request.ts index 84822d36e6..fe221fe5de 100644 --- a/machines/request.ts +++ b/machines/request.ts @@ -2,7 +2,14 @@ import SmartShare from '@idpass/smartshare-react-native'; import BluetoothStateManager from 'react-native-bluetooth-state-manager'; import ODKIntentModule from '../lib/react-native-odk-intent/ODKIntentModule'; import { EmitterSubscription } from 'react-native'; -import { assign, EventFrom, send, sendParent, StateFrom } from 'xstate'; +import { + assign, + ContextFrom, + EventFrom, + send, + sendParent, + StateFrom, +} from 'xstate'; import { createModel } from 'xstate/lib/model'; import { DeviceInfo } from '../components/DeviceInfoList'; import { Message } from '../shared/Message'; @@ -22,6 +29,7 @@ const model = createModel( incomingVc: {} as VC, connectionParams: '', loggers: [] as EmitterSubscription[], + isRequestIntent: false, }, { events: { @@ -177,29 +185,50 @@ export const requestMachine = model.createMachine( STORE_RESPONSE: 'mergingIncomingVc', }, }, - mergingIncomingVc: { - entry: ['mergeIncomingVc'], - on: { - STORE_RESPONSE: '#accepted', - }, - }, prependingReceivedVc: { entry: ['prependReceivedVc'], on: { STORE_RESPONSE: 'storingVc', }, }, + mergingIncomingVc: { + entry: ['mergeIncomingVc'], + on: { + STORE_RESPONSE: [ + { + cond: 'isRequestIntent', + target: '#acceptedIntentShare', + }, + { + target: '#accepted', + }, + ], + }, + }, storingVc: { entry: ['storeVc'], on: { - STORE_RESPONSE: '#accepted', + STORE_RESPONSE: [ + { + cond: 'isRequestIntent', + target: '#acceptedIntentShare', + }, + { + target: '#accepted', + }, + ], }, }, }, }, + acceptedIntentShare: { + id: 'acceptedIntentShare', + entry: ['sendVcReceived', 'logReceived', 'sendVcDataIntent'], + always: 'navigatingToHome', + }, accepted: { id: 'accepted', - entry: ['sendVcReceived', 'logReceived', 'sendVcDataToOdk'], + entry: ['sendVcReceived', 'logReceived'], invoke: { src: 'sendVcResponse', data: { @@ -351,7 +380,7 @@ export const requestMachine = model.createMachine( { to: (context) => context.serviceRefs.vc } ), - sendVcDataToOdk: (context) => { + sendVcDataIntent: (context) => { const { verifiableCredential } = context.incomingVc; const { credentialSubject: subject } = verifiableCredential; @@ -450,6 +479,10 @@ export const requestMachine = model.createMachine( const vcKey = VC_ITEM_STORE_KEY(context.incomingVc); return receivedVcs.includes(vcKey); }, + + isRequestIntent: (context) => { + return context.isRequestIntent; + }, }, delays: { @@ -458,10 +491,12 @@ export const requestMachine = model.createMachine( } ); -export function createRequestMachine(serviceRefs: AppServices) { +export function createRequestMachine( + context?: Partial> +) { return requestMachine.withContext({ ...requestMachine.context, - serviceRefs, + ...(context || {}), }); } diff --git a/machines/request.typegen.ts b/machines/request.typegen.ts index c20f941a2a..414ac5c757 100644 --- a/machines/request.typegen.ts +++ b/machines/request.typegen.ts @@ -18,12 +18,12 @@ export interface Typegen0 { requestReceiverInfo: 'CONNECTED'; requestReceivedVcs: 'xstate.init'; requestExistingVc: 'VC_RESPONSE'; - mergeIncomingVc: 'STORE_RESPONSE'; prependReceivedVc: 'VC_RESPONSE'; + mergeIncomingVc: 'STORE_RESPONSE'; storeVc: 'STORE_RESPONSE'; sendVcReceived: 'STORE_RESPONSE'; logReceived: 'STORE_RESPONSE'; - sendVcDataToOdk: 'STORE_RESPONSE'; + sendVcDataIntent: 'STORE_RESPONSE'; }; 'internalEvents': { 'xstate.after(CLEAR_DELAY)#clearingConnection': { @@ -58,6 +58,7 @@ export interface Typegen0 { }; 'eventsCausingGuards': { hasExistingVc: 'VC_RESPONSE'; + isRequestIntent: 'STORE_RESPONSE'; }; 'eventsCausingDelays': { CLEAR_DELAY: 'xstate.init'; @@ -79,9 +80,10 @@ export interface Typegen0 { | 'reviewing.accepting' | 'reviewing.accepting.requestingReceivedVcs' | 'reviewing.accepting.requestingExistingVc' - | 'reviewing.accepting.mergingIncomingVc' | 'reviewing.accepting.prependingReceivedVc' + | 'reviewing.accepting.mergingIncomingVc' | 'reviewing.accepting.storingVc' + | 'reviewing.acceptedIntentShare' | 'reviewing.accepted' | 'reviewing.rejected' | 'reviewing.navigatingToHome' @@ -91,6 +93,7 @@ export interface Typegen0 { reviewing?: | 'idle' | 'accepting' + | 'acceptedIntentShare' | 'accepted' | 'rejected' | 'navigatingToHome' @@ -98,8 +101,8 @@ export interface Typegen0 { accepting?: | 'requestingReceivedVcs' | 'requestingExistingVc' - | 'mergingIncomingVc' | 'prependingReceivedVc' + | 'mergingIncomingVc' | 'storingVc'; }; }; diff --git a/routes/index.ts b/routes/index.ts index c103fabe4f..d146cb6e4b 100644 --- a/routes/index.ts +++ b/routes/index.ts @@ -66,7 +66,7 @@ export type RootStackParamList = { export interface Screen { name: string; - component: React.FC; + component: React.FC; options?: NativeStackNavigationOptions; } diff --git a/screens/MainLayout.tsx b/screens/MainLayout.tsx index 6132d84851..eb7dcf5447 100644 --- a/screens/MainLayout.tsx +++ b/screens/MainLayout.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useContext, useEffect } from 'react'; import { BottomTabNavigationOptions, createBottomTabNavigator, @@ -8,12 +8,16 @@ import { MainRouteProps, mainRoutes } from '../routes/main'; import { LanguageSelector } from '../components/LanguageSelector'; import { Colors } from '../components/ui/styleUtils'; import { useTranslation } from 'react-i18next'; -import ODKIntentModule from '../lib/react-native-odk-intent/ODKIntentModule'; +import { GlobalContext } from '../shared/GlobalContext'; +import { useSelector } from '@xstate/react'; +import { selectIsRequestIntent } from '../machines/app'; const { Navigator, Screen } = createBottomTabNavigator(); export const MainLayout: React.FC = (props) => { const { t } = useTranslation('MainLayout'); + const { appService } = useContext(GlobalContext); + const isRequestIntent = useSelector(appService, selectIsRequestIntent); const options: BottomTabNavigationOptions = { headerLeft: () => , @@ -30,12 +34,10 @@ export const MainLayout: React.FC = (props) => { }; useEffect(() => { - ODKIntentModule.isRequestIntent().then((result) => { - if (result) { - props.navigation.navigate('Request'); - } - }); - }, []); + if (isRequestIntent) { + props.navigation.navigate('Request'); + } + }, [isRequestIntent]); return ( From ee7e096af633d9855c9d9442d24d22cf9d5ad086 Mon Sep 17 00:00:00 2001 From: ckm007 Date: Fri, 15 Dec 2023 12:08:26 +0000 Subject: [PATCH 06/11] [DSD-3960] inji 0.10.0 release changes --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 401bb699b3..3fb04f542c 100644 --- a/README.md +++ b/README.md @@ -192,3 +192,4 @@ To learn more about React Native, take a look at the following resources: - [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**. - [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts. - [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native. + From d50a12c20eeb8480c3ba170a2e53ddc8008c8a8f Mon Sep 17 00:00:00 2001 From: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com> Date: Tue, 16 Jan 2024 18:25:17 +0530 Subject: [PATCH 07/11] [INJI-720] add a workflow to upload to actions without using secrets (#1171) Signed-off-by: adityankannan-tw Co-authored-by: adityankannan-tw --- .github/workflows/android-custom-build.yml | 56 ++++++++++++++++++++++ .github/workflows/push-triggers.yml | 6 +-- android/fastlane/Fastfile | 4 +- 3 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/android-custom-build.yml diff --git a/.github/workflows/android-custom-build.yml b/.github/workflows/android-custom-build.yml new file mode 100644 index 0000000000..cd5df3e256 --- /dev/null +++ b/.github/workflows/android-custom-build.yml @@ -0,0 +1,56 @@ +name: Android Custom Build +run-name: ${{ inputs.buildName }} + +on: + workflow_dispatch: + inputs: + buildName: + description: 'Run name' + required: true + default: 'Edit this name' + type: string + mimotoBackendServiceUrl: + description: 'Mimoto backend service URL' + required: true + default: 'https://api.sandbox.mosip.net' + type: string + esignetBackendServiceUrl: + description: 'Esignet backend service URL' + required: true + default: 'https://api.sandbox.mosip.net' + type: string + allow_env_edit: + description: 'Edit ENV' + required: true + default: 'true' + type: choice + options: + - false + - true + theme: + description: 'Application Theme' + required: true + default: 'orange' + type: choice + options: + - orange + - purple + +jobs: + build-android: + uses: mosip/kattu/.github/workflows/android-build.yml@master + with: + NODE_VERSION: "16.x" + MIMOTO_HOST: ${{ inputs.mimotoBackendServiceUrl }} + ESIGNET_HOST: ${{ inputs.esignetBackendServiceUrl }} + APPLICATION_THEME: ${{ inputs.theme }} + ALLOW_ENV_EDIT: ${{ inputs.allow_env_edit }} + KEYSTORE_ALIAS: androidbuildkey + KEYSTORE_PASSWORD: 'password' + SERVICE_LOCATION: '.' + ANDROID_SERVICE_LOCATION: 'android' + BUILD_SCRIPT_LOCATION: 'scripts' + SCRIPT_NAME: './android-build.sh' + UPLOAD_TO_ACTIONS: 'true' + ANDROID_ARTIFACT_NAME: ${{ inputs.buildName }} + ANDROID_ARTIFACT_PATH: "android/app/build/outputs/apk/residentapp/release/Inji_universal.apk" \ No newline at end of file diff --git a/.github/workflows/push-triggers.yml b/.github/workflows/push-triggers.yml index 9e7170b843..d1a8fe46f4 100644 --- a/.github/workflows/push-triggers.yml +++ b/.github/workflows/push-triggers.yml @@ -22,13 +22,13 @@ jobs: uses: mosip/kattu/.github/workflows/android-build.yml@master with: NODE_VERSION: "16.x" - DEBUG_KEYSTORE_ALIAS: androiddebugkey + KEYSTORE_ALIAS: androidbuildkey + KEYSTORE_PASSWORD: 'password' SERVICE_LOCATION: '.' ANDROID_SERVICE_LOCATION: 'android' BUILD_SCRIPT_LOCATION: 'scripts' SCRIPT_NAME: './android-build.sh' - secrets: - DEBUG_KEYSTORE_PASSWORD: '${{ secrets.INJI_ANDROID_DEBUG_STOREPASS }}' + UPLOAD_TO_ACTIONS: 'false' build-ios: uses: mosip/kattu/.github/workflows/ios-build.yml@master diff --git a/android/fastlane/Fastfile b/android/fastlane/Fastfile index aa859df525..ba7c0351a3 100644 --- a/android/fastlane/Fastfile +++ b/android/fastlane/Fastfile @@ -4,9 +4,7 @@ MIMOTO_HOST = ENV["MIMOTO_HOST"] ESIGNET_HOST = ENV["ESIGNET_HOST"] APPLICATION_THEME = ENV["APPLICATION_THEME"] RELEASE_KEYSTORE_ALIAS = ENV["RELEASE_KEYSTORE_ALIAS"] -DEBUG_KEYSTORE_ALIAS = ENV["DEBUG_KEYSTORE_ALIAS"] RELEASE_KEYSTORE_PASSWORD = ENV["RELEASE_KEYSTORE_PASSWORD"] -DEBUG_KEYSTORE_PASSWORD = ENV["DEBUG_KEYSTORE_PASSWORD"] PLAY_CONSOLE_RELEASE_DESCRIPTION = ENV["BUILD_DESCRIPTION"] SLACK_URL = ENV["SLACK_WEBHOOK_URL"] CREDENTIAL_REGISTRY_EDIT = ENV["CREDENTIAL_REGISTRY_EDIT"] @@ -46,7 +44,7 @@ end desc "Verify Build for Android" lane :android_build do - gradle(task: "assemble#{APP_FLAVOR}Debug") + gradle(task: "assembleResidentappRelease") end desc "Deploy an Internal testing version to the Google Play" From 4bbe377ed7d482b996bd980f09c0ccf330173232 Mon Sep 17 00:00:00 2001 From: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:34:33 +0530 Subject: [PATCH 08/11] [INJI-700] add workflow for ui automation (#1181) Signed-off-by: adityankannan-tw Co-authored-by: adityankannan-tw --- .github/workflows/ui-automation.yml | 190 ++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 .github/workflows/ui-automation.yml diff --git a/.github/workflows/ui-automation.yml b/.github/workflows/ui-automation.yml new file mode 100644 index 0000000000..c3cd2b9154 --- /dev/null +++ b/.github/workflows/ui-automation.yml @@ -0,0 +1,190 @@ +name: UI - Automation +run-name: ${{ inputs.runName }} + +on: + workflow_dispatch: + inputs: + runName: + description: 'Run name' + required: true + default: 'Device-pool/Test-name/Env' + type: string + buildFor: + description: 'Build' + required: true + default: 'Both[Android and IOS]' + type: choice + options: + - Both[Android and IOS] + - Android + - IOS + testType: + description: 'Sanity/Regression' + required: true + default: 'sanity' + type: choice + options: + - sanity + - regression + backendServiceUrl: + description: 'Mimoto and Esignet backend service URL' + required: true + default: 'https://api.sandbox.mosip.net' + type: string + +jobs: + android-ui-automation: + if: ${{ github.event.inputs.buildFor == 'Both[Android and IOS]' || github.event.inputs.buildFor == 'Android'}} + name: Trigger android run + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3.1.0 + - uses: actions/setup-node@v3 + with: + node-version: '18.x' + + - name: Cache npm dependencies + uses: actions/cache@v3.3.1 + with: + path: '~/.npm' + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Install npm dependencies + run: | + npm ci + + - name: Generate Android 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: Create Android Build + run: | + npx jetify + cd android + ./gradlew :app:assembleResidentappRelease + env: + MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }} + ESIGNET_HOST: ${{ github.event.inputs.backendServiceUrl }} + APPLICATION_THEME: 'orange' + CREDENTIAL_REGISTRY_EDIT: 'false' + RELEASE_KEYSTORE_ALIAS: 'androidreleasekey' + RELEASE_KEYSTORE_PASSWORD: "${{ secrets.INJI_ANDROID_RELEASE_STOREPASS }}" + + - name: Configure AWS CLI + run: | + aws configure set aws_access_key_id ${{ secrets.AWS_DEVICE_FARM_ACCESS_KEY }} + aws configure set aws_secret_access_key ${{ secrets.AWS_DEVICE_FARM_SECRET_KEY }} + aws configure set region us-west-2 + + - name: Android - Automation + id: android-run + run: | + cd injitest/scripts/ui_automation + RUN_ARN=$(./automation_trigger.sh "Android" "$RUN_NAME" "$TEST_TYPE") + echo "The Run ARN is $RUN_ARN" + env: + RUN_NAME: ${{ github.event.inputs.runName }} + TEST_TYPE: ${{ github.event.inputs.testType }} + + # - name: Artifacts download + # id: artifact-download + # run: | + # cd injitest/scripts/ui_automation + # ./download_artifacts.sh "${{ steps.android-run.outputs.run_arn }}" "Android" + + # - name: Upload Artifact to Actions + # uses: actions/upload-artifact@v3.1.1 + # with: + # name: Automation Artifacts + # path: injitest/scripts/ui_automation/artifacts/ + # retention-days: 5 + + # - name: Update slack channel + # if: always() + # uses: 8398a7/action-slack@v3 + # with: + # status: ${{ job.status }} + # fields: repo,message,author,commit,workflow,job + # env: + # SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_INJI_TEAM }} + + ios-ui-automation: + if: ${{ github.event.inputs.buildFor == 'Both[Android and IOS]' || github.event.inputs.buildFor == 'IOS'}} + name: Trigger ios run + runs-on: macos-13 + + steps: + - uses: actions/checkout@v3.1.0 + - uses: actions/setup-node@v3 + with: + node-version: '18.x' + + - name: Cache npm dependencies + uses: actions/cache@v3.3.1 + with: + path: '~/.npm' + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Install npm dependencies + run: | + npm ci + + - name: Create iOS Build + run: | + cd ios + pod install && pod install + fastlane ios_ui_automation_build + env: + MIMOTO_HOST: ${{ github.event.inputs.backendServiceUrl }} + ESIGNET_HOST: ${{ github.event.inputs.backendServiceUrl }} + APPLICATION_THEME: 'orange' + APP_FLAVOR: 'residentapp' + CREDENTIAL_REGISTRY_EDIT: 'false' + INJI_IOS_TEMP_KEYCHAIN_PASSWORD: '${{ secrets.INJI_IOS_TEMP_KEYCHAIN_PASSWORD }}' + INJI_IOS_TEMP_KEYCHAIN_USER: '${{ secrets.INJI_IOS_TEMP_KEYCHAIN_USER }}' + GIT_AUTHORIZATION: '${{ secrets.GIT_AUTHORIZATION }}' + + - name: Configure AWS CLI + run: | + aws configure set aws_access_key_id ${{ secrets.AWS_DEVICE_FARM_ACCESS_KEY }} + aws configure set aws_secret_access_key ${{ secrets.AWS_DEVICE_FARM_SECRET_KEY }} + aws configure set region us-west-2 + + - name: IOS - Automation + run: | + cd injitest/scripts/ui_automation + RUN_ARN=$(./automation_trigger.sh "IOS" "$RUN_NAME" "$TEST_TYPE") + echo "The Run ARN is $RUN_ARN" + env: + RUN_NAME: ${{ github.event.inputs.runName }} + TEST_TYPE: ${{ github.event.inputs.testType }} + + # - name: Artifacts download + # id: artifact-download + # run: | + # cd injitest/scripts/ui_automation + # ./download_artifacts.sh "${{ steps.android-run.outputs.run_arn }}" "Android" + + # - name: Upload Artifact to Actions + # uses: actions/upload-artifact@v3.1.1 + # with: + # name: Automation Artifacts + # path: injitest/scripts/ui_automation/artifacts/ + # retention-days: 5 + + # - name: Update slack channel + # if: always() + # uses: 8398a7/action-slack@v3 + # with: + # status: ${{ job.status }} + # fields: repo,message,author,commit,workflow,job + # env: + # SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_INJI_TEAM }} From 8b65cf4982f4f97dfbf05e5719abfb01af0b05b3 Mon Sep 17 00:00:00 2001 From: Paolo Miguel de Leon Date: Tue, 30 Jan 2024 14:42:27 +0800 Subject: [PATCH 09/11] feat: migrate ODK integration to new request machine --- machines/app.ts | 2 +- machines/bleShare/request/requestMachine.ts | 40 +- .../request/requestMachine.typegen.ts | 276 +++------ machines/request.ts | 547 ------------------ machines/request.typegen.ts | 110 ---- machines/vc.typegen.ts | 122 ++-- 6 files changed, 180 insertions(+), 917 deletions(-) delete mode 100644 machines/request.ts delete mode 100644 machines/request.typegen.ts diff --git a/machines/app.ts b/machines/app.ts index 0d3454404a..ffcb26a520 100644 --- a/machines/app.ts +++ b/machines/app.ts @@ -291,7 +291,7 @@ export const appMachine = model.createMachine( if (isAndroid()) { serviceRefs.request = spawn( - createRequestMachine(serviceRefs), + createRequestMachine(serviceRefs, context.isRequestIntent), requestMachine.id, ); } diff --git a/machines/bleShare/request/requestMachine.ts b/machines/bleShare/request/requestMachine.ts index 5282ad7093..916b81561d 100644 --- a/machines/bleShare/request/requestMachine.ts +++ b/machines/bleShare/request/requestMachine.ts @@ -23,6 +23,7 @@ import {VerifierDataEvent} from 'react-native-tuvali/src/types/events'; import {BLEError} from '../types'; import Storage from '../../../shared/storage'; import {VCMetadata} from '../../../shared/VCMetadata'; +import ODKIntentModule from '../../../lib/react-native-odk-intent/ODKIntentModule'; // import { verifyPresentation } from '../shared/vcjs/verifyPresentation'; const {verifier, EventTypes, VerificationStatus} = tuvali; @@ -38,6 +39,7 @@ const model = createModel( loggers: [] as EmitterSubscription[], receiveLogType: '' as ActivityLogType, readyForBluetoothStateCheck: false, + isRequestIntent: false }, { events: { @@ -361,9 +363,15 @@ export const requestMachine = mergingIncomingVc: { entry: 'mergeIncomingVc', on: { - STORE_RESPONSE: { - target: '#request.reviewing.accepted', - }, + STORE_RESPONSE: [ + { + cond: 'isRequestIntent', + target: '#request.reviewing.acceptedIntentShare' + }, + { + target: '#request.reviewing.accepted', + } + ], }, }, prependingReceivedVc: { @@ -389,6 +397,10 @@ export const requestMachine = }, }, }, + acceptedIntentShare: { + entry: ['sendVcReceived', 'logReceived', 'sendVcDataIntent'], + always: 'navigatingToHome', + }, accepted: { entry: [ 'sendVcReceived', @@ -672,6 +684,21 @@ export const requestMachine = shouldVerifyPresence: false, }), }), + + sendVcDataIntent: (context) => { + const { verifiableCredential } = context.incomingVc; + const { credentialSubject: subject } = verifiableCredential; + + ODKIntentModule.sendBundleResult({ + biometrics: subject.biometrics, + date_of_birth: subject.dateOfBirth, + email: subject.email, + full_name: subject.fullName, + issuance_date: verifiableCredential.issuanceDate, + issuer: verifiableCredential.issuer, + phone: subject.phone, + uin: subject.UIN, + }); }, services: { @@ -829,6 +856,10 @@ export const requestMachine = }, isMinimumStorageLimitReached: (_context, event) => Boolean(event.data), + + isRequestIntent: (context) => { + return context.isRequestIntent; + }, }, delays: { @@ -840,10 +871,11 @@ export const requestMachine = type State = StateFrom; -export function createRequestMachine(serviceRefs: AppServices) { +export function createRequestMachine(serviceRefs: AppServices, isRequestIntent = false) { return requestMachine.withContext({ ...requestMachine.context, serviceRefs, + isRequestIntent }); } diff --git a/machines/bleShare/request/requestMachine.typegen.ts b/machines/bleShare/request/requestMachine.typegen.ts index 4a8b103887..40e36e3055 100644 --- a/machines/bleShare/request/requestMachine.typegen.ts +++ b/machines/bleShare/request/requestMachine.typegen.ts @@ -1,193 +1,85 @@ -// This file was automatically generated. Edits will be overwritten -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(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'; - }; - 'xstate.init': {type: 'xstate.init'}; - 'xstate.stop': {type: 'xstate.stop'}; - }; - invokeSrcNameMap: { - advertiseDevice: 'done.invoke.request.waitingForConnection:invocation[0]'; - checkBluetoothService: 'done.invoke.request.checkingBluetoothService.checking: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]' - | 'done.invoke.request.reviewing.navigatingToHome:invocation[0]'; - monitorConnection: 'done.invoke.request:invocation[0]'; - receiveVc: 'done.invoke.request.waitingForVc:invocation[0]'; - requestBluetooth: 'done.invoke.request.checkingBluetoothService.requesting: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.savingFailed:invocation[0]'; - verifyVp: 'done.invoke.request.reviewing.verifyingVp:invocation[0]'; - }; - missingImplementations: { - actions: never; - delays: never; - guards: never; - services: never; - }; - eventsCausingActions: { - clearShouldVerifyPresence: - | 'ACCEPT' - | 'BLE_ERROR' - | 'CANCEL' - | 'FACE_INVALID' - | 'FACE_VALID' - | 'REJECT' - | 'RESET' - | 'SCREEN_BLUR' - | 'SCREEN_FOCUS' - | 'xstate.stop'; - logReceived: 'CANCEL' | 'REJECT' | 'STORE_ERROR' | 'STORE_RESPONSE'; - mergeIncomingVc: 'STORE_RESPONSE'; - openAppPermission: 'GOTO_SETTINGS'; - prependReceivedVc: 'VC_RESPONSE'; - registerLoggers: - | 'DISCONNECT' - | 'RESET' - | 'xstate.after(DESTROY_TIMEOUT)#request.clearingConnection'; - removeLoggers: - | 'DISCONNECT' - | 'RESET' - | 'SCREEN_BLUR' - | '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]'; - sendVcReceived: 'STORE_RESPONSE'; - setBleError: 'BLE_ERROR'; - setIncomingVc: 'VC_RECEIVED'; - setOpenID4VpUri: 'ADV_STARTED'; - setReadyForBluetoothStateCheck: 'NEARBY_ENABLED'; - setReceiveLogTypeDiscarded: 'CANCEL' | 'REJECT' | 'STORE_ERROR'; - setReceiveLogTypeRegular: 'ACCEPT' | 'STORE_RESPONSE'; - setReceiveLogTypeUnverified: 'FACE_INVALID'; - setReceiveLogTypeVerified: 'FACE_VALID'; - setReceiverInfo: 'CONNECTED'; - setSenderInfo: 'CONNECTED'; - storeVc: 'STORE_RESPONSE'; - }; - eventsCausingDelays: { - DESTROY_TIMEOUT: '' | 'DISMISS'; - SHARING_TIMEOUT: 'CONNECTED'; - }; - eventsCausingGuards: { - hasExistingVc: 'VC_RESPONSE'; - isMinimumStorageLimitReached: 'done.invoke.request.checkStorage:invocation[0]'; - }; - eventsCausingServices: { - advertiseDevice: - | 'DISCONNECT' - | 'RESET' - | '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: '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' - | 'clearingConnection' - | 'disconnected' - | 'handlingBleError' - | 'inactive' - | 'nearByDevicesPermissionDenied' - | 'reviewing' - | 'reviewing.accepted' - | 'reviewing.accepting' - | 'reviewing.accepting.mergingIncomingVc' - | 'reviewing.accepting.prependingReceivedVc' - | 'reviewing.accepting.requestingExistingVc' - | 'reviewing.accepting.requestingReceivedVcs' - | 'reviewing.accepting.storingVc' - | 'reviewing.displayingIncomingVC' - | 'reviewing.idle' - | 'reviewing.invalidIdentity' - | 'reviewing.navigatingToHistory' - | 'reviewing.navigatingToHome' - | 'reviewing.navigatingToReceivedCards' - | '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'; - reviewing?: - | 'accepted' - | 'accepting' - | 'displayingIncomingVC' - | 'idle' - | 'invalidIdentity' - | 'navigatingToHistory' - | 'navigatingToHome' - | 'navigatingToReceivedCards' - | 'rejected' - | 'savingFailed' - | 'verifyingIdentity' - | 'verifyingVp' - | { - accepting?: - | 'mergingIncomingVc' - | 'prependingReceivedVc' - | 'requestingExistingVc' - | 'requestingReceivedVcs' - | 'storingVc'; - savingFailed?: 'idle' | 'viewingVc'; - }; - waitingForVc?: 'inProgress' | 'timeout'; - }; - tags: never; -} + // This file was automatically generated. Edits will be overwritten + + 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(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" }; +"xstate.init": { type: "xstate.init" }; +"xstate.stop": { type: "xstate.stop" }; + }; + invokeSrcNameMap: { + "advertiseDevice": "done.invoke.request.waitingForConnection:invocation[0]"; +"checkBluetoothService": "done.invoke.request.checkingBluetoothService.checking: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]" | "done.invoke.request.reviewing.navigatingToHome:invocation[0]"; +"monitorConnection": "done.invoke.request:invocation[0]"; +"receiveVc": "done.invoke.request.waitingForVc:invocation[0]"; +"requestBluetooth": "done.invoke.request.checkingBluetoothService.requesting: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.savingFailed:invocation[0]"; +"verifyVp": "done.invoke.request.reviewing.verifyingVp:invocation[0]"; + }; + missingImplementations: { + actions: never; + delays: never; + guards: never; + services: never; + }; + eventsCausingActions: { + "clearShouldVerifyPresence": "ACCEPT" | "BLE_ERROR" | "CANCEL" | "FACE_INVALID" | "FACE_VALID" | "REJECT" | "RESET" | "SCREEN_BLUR" | "SCREEN_FOCUS" | "xstate.stop"; +"logReceived": "CANCEL" | "REJECT" | "STORE_ERROR" | "STORE_RESPONSE"; +"mergeIncomingVc": "STORE_RESPONSE"; +"openAppPermission": "GOTO_SETTINGS"; +"prependReceivedVc": "VC_RESPONSE"; +"registerLoggers": "DISCONNECT" | "RESET" | "xstate.after(DESTROY_TIMEOUT)#request.clearingConnection"; +"removeLoggers": "DISCONNECT" | "RESET" | "SCREEN_BLUR" | "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]"; +"sendVcReceived": "STORE_RESPONSE"; +"setBleError": "BLE_ERROR"; +"setIncomingVc": "VC_RECEIVED"; +"setOpenID4VpUri": "ADV_STARTED"; +"setReadyForBluetoothStateCheck": "NEARBY_ENABLED"; +"setReceiveLogTypeDiscarded": "CANCEL" | "REJECT" | "STORE_ERROR"; +"setReceiveLogTypeRegular": "ACCEPT" | "STORE_RESPONSE"; +"setReceiveLogTypeUnverified": "FACE_INVALID"; +"setReceiveLogTypeVerified": "FACE_VALID"; +"setReceiverInfo": "CONNECTED"; +"setSenderInfo": "CONNECTED"; +"storeVc": "STORE_RESPONSE"; + }; + eventsCausingDelays: { + "DESTROY_TIMEOUT": "" | "DISMISS"; +"SHARING_TIMEOUT": "CONNECTED"; + }; + eventsCausingGuards: { + "hasExistingVc": "VC_RESPONSE"; +"isMinimumStorageLimitReached": "done.invoke.request.checkStorage:invocation[0]"; +"isRequestIntent": "STORE_RESPONSE"; + }; + eventsCausingServices: { + "advertiseDevice": "DISCONNECT" | "RESET" | "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": "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" | "clearingConnection" | "disconnected" | "handlingBleError" | "inactive" | "nearByDevicesPermissionDenied" | "reviewing" | "reviewing.accepted" | "reviewing.accepting" | "reviewing.accepting.acceptedIntentShare" | "reviewing.accepting.mergingIncomingVc" | "reviewing.accepting.prependingReceivedVc" | "reviewing.accepting.requestingExistingVc" | "reviewing.accepting.requestingReceivedVcs" | "reviewing.accepting.storingVc" | "reviewing.displayingIncomingVC" | "reviewing.idle" | "reviewing.invalidIdentity" | "reviewing.navigatingToHistory" | "reviewing.navigatingToHome" | "reviewing.navigatingToReceivedCards" | "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"; +"reviewing"?: "accepted" | "accepting" | "displayingIncomingVC" | "idle" | "invalidIdentity" | "navigatingToHistory" | "navigatingToHome" | "navigatingToReceivedCards" | "rejected" | "savingFailed" | "verifyingIdentity" | "verifyingVp" | { "accepting"?: "acceptedIntentShare" | "mergingIncomingVc" | "prependingReceivedVc" | "requestingExistingVc" | "requestingReceivedVcs" | "storingVc"; +"savingFailed"?: "idle" | "viewingVc"; }; +"waitingForVc"?: "inProgress" | "timeout"; }; + tags: never; + } diff --git a/machines/request.ts b/machines/request.ts deleted file mode 100644 index fe221fe5de..0000000000 --- a/machines/request.ts +++ /dev/null @@ -1,547 +0,0 @@ -import SmartShare from '@idpass/smartshare-react-native'; -import BluetoothStateManager from 'react-native-bluetooth-state-manager'; -import ODKIntentModule from '../lib/react-native-odk-intent/ODKIntentModule'; -import { EmitterSubscription } from 'react-native'; -import { - assign, - ContextFrom, - EventFrom, - send, - sendParent, - StateFrom, -} from 'xstate'; -import { createModel } from 'xstate/lib/model'; -import { DeviceInfo } from '../components/DeviceInfoList'; -import { Message } from '../shared/Message'; -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 } from './activityLog'; -import { VcEvents } from './vc'; - -const model = createModel( - { - serviceRefs: {} as AppServices, - senderInfo: {} as DeviceInfo, - receiverInfo: {} as DeviceInfo, - incomingVc: {} as VC, - connectionParams: '', - loggers: [] as EmitterSubscription[], - isRequestIntent: false, - }, - { - events: { - ACCEPT: () => ({}), - REJECT: () => ({}), - CANCEL: () => ({}), - DISMISS: () => ({}), - VC_RECEIVED: (vc: VC) => ({ vc }), - RESPONSE_SENT: () => ({}), - CONNECTED: () => ({}), - 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 }), - }, - } -); - -export const RequestEvents = model.events; - -export const requestMachine = model.createMachine( - { - tsTypes: {} as import('./request.typegen').Typegen0, - schema: { - context: model.initialContext, - events: {} as EventFrom, - }, - id: 'request', - initial: 'inactive', - on: { - SCREEN_BLUR: 'inactive', - SCREEN_FOCUS: 'checkingBluetoothService', - }, - states: { - inactive: { - entry: ['removeLoggers'], - }, - checkingBluetoothService: { - initial: 'checking', - states: { - checking: { - invoke: { - src: 'checkBluetoothService', - }, - on: { - BLUETOOTH_ENABLED: 'enabled', - BLUETOOTH_DISABLED: 'requesting', - }, - }, - requesting: { - invoke: { - src: 'requestBluetooth', - }, - on: { - BLUETOOTH_ENABLED: 'enabled', - BLUETOOTH_DISABLED: '#bluetoothDenied', - }, - }, - enabled: { - always: '#clearingConnection', - }, - }, - }, - bluetoothDenied: { - id: 'bluetoothDenied', - }, - clearingConnection: { - id: 'clearingConnection', - entry: ['disconnect'], - after: { - CLEAR_DELAY: 'waitingForConnection', - }, - }, - waitingForConnection: { - id: 'waitingForConnection', - entry: ['removeLoggers', 'registerLoggers', 'generateConnectionParams'], - invoke: { - src: 'advertiseDevice', - }, - on: { - CONNECTED: 'preparingToExchangeInfo', - DISCONNECT: 'disconnected', - }, - }, - preparingToExchangeInfo: { - entry: ['requestReceiverInfo'], - on: { - RECEIVE_DEVICE_INFO: { - target: 'exchangingDeviceInfo', - actions: ['setReceiverInfo'], - }, - }, - }, - exchangingDeviceInfo: { - invoke: { - src: 'exchangeDeviceInfo', - }, - on: { - EXCHANGE_DONE: { - target: 'waitingForVc', - actions: ['setSenderInfo'], - }, - }, - }, - waitingForVc: { - invoke: { - src: 'receiveVc', - }, - on: { - DISCONNECT: 'disconnected', - VC_RECEIVED: { - target: 'reviewing', - actions: ['setIncomingVc'], - }, - }, - }, - reviewing: { - on: { - ACCEPT: '.accepting', - REJECT: '.rejected', - CANCEL: '.rejected', - }, - initial: 'idle', - states: { - idle: {}, - accepting: { - initial: 'requestingReceivedVcs', - states: { - requestingReceivedVcs: { - entry: ['requestReceivedVcs'], - on: { - VC_RESPONSE: [ - { - cond: 'hasExistingVc', - target: 'requestingExistingVc', - }, - { - target: 'prependingReceivedVc', - }, - ], - }, - }, - requestingExistingVc: { - entry: ['requestExistingVc'], - on: { - STORE_RESPONSE: 'mergingIncomingVc', - }, - }, - prependingReceivedVc: { - entry: ['prependReceivedVc'], - on: { - STORE_RESPONSE: 'storingVc', - }, - }, - mergingIncomingVc: { - entry: ['mergeIncomingVc'], - on: { - STORE_RESPONSE: [ - { - cond: 'isRequestIntent', - target: '#acceptedIntentShare', - }, - { - target: '#accepted', - }, - ], - }, - }, - storingVc: { - entry: ['storeVc'], - on: { - STORE_RESPONSE: [ - { - cond: 'isRequestIntent', - target: '#acceptedIntentShare', - }, - { - target: '#accepted', - }, - ], - }, - }, - }, - }, - acceptedIntentShare: { - id: 'acceptedIntentShare', - entry: ['sendVcReceived', 'logReceived', 'sendVcDataIntent'], - always: 'navigatingToHome', - }, - accepted: { - id: 'accepted', - entry: ['sendVcReceived', 'logReceived'], - invoke: { - src: 'sendVcResponse', - data: { - status: 'accepted', - }, - }, - on: { - DISMISS: 'navigatingToHome', - }, - }, - rejected: { - invoke: { - src: 'sendVcResponse', - data: { - status: 'rejected', - }, - }, - on: { - DISMISS: '#waitingForConnection', - }, - }, - navigatingToHome: {}, - }, - exit: ['disconnect'], - }, - disconnected: { - on: { - DISMISS: 'waitingForConnection', - }, - }, - }, - }, - { - actions: { - 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: () => { - try { - SmartShare.destroyConnection(); - } catch (e) { - // pass - } - }, - - generateConnectionParams: assign({ - connectionParams: () => SmartShare.getConnectionParameters(), - }), - - setSenderInfo: model.assign({ - senderInfo: (_context, event) => event.senderInfo, - }), - - setIncomingVc: model.assign({ - incomingVc: (_context, event) => event.vc, - }), - - registerLoggers: assign({ - loggers: () => { - if (__DEV__) { - return [ - SmartShare.handleNearbyEvents((event) => { - console.log( - getDeviceNameSync(), - '', - JSON.stringify(event) - ); - }), - SmartShare.handleLogEvents((event) => { - console.log( - getDeviceNameSync(), - '', - JSON.stringify(event) - ); - }), - ]; - } 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 } - ), - - logReceived: send( - (context) => - ActivityLogEvents.LOG_ACTIVITY({ - _vcKey: VC_ITEM_STORE_KEY(context.incomingVc), - action: 'received', - 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 } - ), - - sendVcDataIntent: (context) => { - const { verifiableCredential } = context.incomingVc; - const { credentialSubject: subject } = verifiableCredential; - - ODKIntentModule.sendBundleResult({ - biometrics: subject.biometrics, - date_of_birth: subject.dateOfBirth, - email: subject.email, - full_name: subject.fullName, - issuance_date: verifiableCredential.issuanceDate, - issuer: verifiableCredential.issuer, - phone: subject.phone, - uin: subject.UIN, - }); - }, - }, - - services: { - 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(); - }, - - requestBluetooth: () => (callback) => { - BluetoothStateManager.requestToEnable() - .then(() => callback(model.events.BLUETOOTH_ENABLED())) - .catch(() => callback(model.events.BLUETOOTH_DISABLED())); - }, - - advertiseDevice: () => (callback) => { - SmartShare.createConnection('advertiser', () => { - callback({ type: 'CONNECTED' }); - }); - }, - - exchangeDeviceInfo: (context) => (callback) => { - const subscription = SmartShare.handleNearbyEvents((event) => { - if (event.type === 'onDisconnected') { - callback({ type: 'DISCONNECT' }); - } - - if (event.type !== 'msg') return; - - const message = Message.fromString(event.data); - if (message.type === 'exchange:sender-info') { - const response = new Message( - 'exchange:receiver-info', - context.receiverInfo - ); - SmartShare.send(response.toString(), () => { - callback({ type: 'EXCHANGE_DONE', senderInfo: message.data }); - }); - } - }); - - return () => subscription.remove(); - }, - - receiveVc: () => (callback) => { - const subscription = SmartShare.handleNearbyEvents((event) => { - if (event.type === 'onDisconnected') { - callback({ type: 'DISCONNECT' }); - } - - if (event.type !== 'msg') return; - - const message = Message.fromString(event.data); - if (message.type === 'send:vc') { - callback({ type: 'VC_RECEIVED', vc: message.data }); - } - }); - - return () => subscription.remove(); - }, - - sendVcResponse: (_context, _event, meta) => (callback) => { - const response = new Message('send:vc:response', { - status: meta.data.status, - }); - - SmartShare.send(response.toString(), () => { - callback({ type: 'RESPONSE_SENT' }); - }); - }, - }, - - guards: { - hasExistingVc: (context, event) => { - const receivedVcs = event.response as string[]; - const vcKey = VC_ITEM_STORE_KEY(context.incomingVc); - return receivedVcs.includes(vcKey); - }, - - isRequestIntent: (context) => { - return context.isRequestIntent; - }, - }, - - delays: { - CLEAR_DELAY: 250, - }, - } -); - -export function createRequestMachine( - context?: Partial> -) { - return requestMachine.withContext({ - ...requestMachine.context, - ...(context || {}), - }); -} - -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 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 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 selectIsExchangingDeviceInfo(state: State) { - return state.matches('exchangingDeviceInfo'); -} - -export function selectIsWaitingForVc(state: State) { - return state.matches('waitingForVc'); -} diff --git a/machines/request.typegen.ts b/machines/request.typegen.ts deleted file mode 100644 index 414ac5c757..0000000000 --- a/machines/request.typegen.ts +++ /dev/null @@ -1,110 +0,0 @@ -// This file was automatically generated. Edits will be overwritten - -export interface Typegen0 { - '@@xstate/typegen': true; - 'eventsCausingActions': { - setReceiverInfo: 'RECEIVE_DEVICE_INFO'; - setSenderInfo: 'EXCHANGE_DONE'; - setIncomingVc: 'VC_RECEIVED'; - removeLoggers: - | 'SCREEN_BLUR' - | 'xstate.after(CLEAR_DELAY)#clearingConnection' - | 'DISMISS'; - disconnect: ''; - registerLoggers: 'xstate.after(CLEAR_DELAY)#clearingConnection' | 'DISMISS'; - generateConnectionParams: - | 'xstate.after(CLEAR_DELAY)#clearingConnection' - | 'DISMISS'; - requestReceiverInfo: 'CONNECTED'; - requestReceivedVcs: 'xstate.init'; - requestExistingVc: 'VC_RESPONSE'; - prependReceivedVc: 'VC_RESPONSE'; - mergeIncomingVc: 'STORE_RESPONSE'; - storeVc: 'STORE_RESPONSE'; - sendVcReceived: 'STORE_RESPONSE'; - logReceived: 'STORE_RESPONSE'; - sendVcDataIntent: 'STORE_RESPONSE'; - }; - 'internalEvents': { - 'xstate.after(CLEAR_DELAY)#clearingConnection': { - type: 'xstate.after(CLEAR_DELAY)#clearingConnection'; - }; - '': { type: '' }; - 'xstate.init': { type: 'xstate.init' }; - }; - 'invokeSrcNameMap': { - checkBluetoothService: 'done.invoke.request.checkingBluetoothService.checking:invocation[0]'; - requestBluetooth: 'done.invoke.request.checkingBluetoothService.requesting:invocation[0]'; - advertiseDevice: 'done.invoke.waitingForConnection:invocation[0]'; - exchangeDeviceInfo: 'done.invoke.request.exchangingDeviceInfo:invocation[0]'; - receiveVc: 'done.invoke.request.waitingForVc:invocation[0]'; - sendVcResponse: - | 'done.invoke.accepted:invocation[0]' - | 'done.invoke.request.reviewing.rejected:invocation[0]'; - }; - 'missingImplementations': { - actions: never; - services: never; - guards: never; - delays: never; - }; - 'eventsCausingServices': { - checkBluetoothService: 'xstate.init'; - requestBluetooth: 'BLUETOOTH_DISABLED'; - advertiseDevice: 'xstate.after(CLEAR_DELAY)#clearingConnection' | 'DISMISS'; - exchangeDeviceInfo: 'RECEIVE_DEVICE_INFO'; - receiveVc: 'EXCHANGE_DONE'; - sendVcResponse: 'REJECT' | 'CANCEL' | 'STORE_RESPONSE'; - }; - 'eventsCausingGuards': { - hasExistingVc: 'VC_RESPONSE'; - isRequestIntent: 'STORE_RESPONSE'; - }; - 'eventsCausingDelays': { - CLEAR_DELAY: 'xstate.init'; - }; - 'matchesStates': - | 'inactive' - | 'checkingBluetoothService' - | 'checkingBluetoothService.checking' - | 'checkingBluetoothService.requesting' - | 'checkingBluetoothService.enabled' - | 'bluetoothDenied' - | 'clearingConnection' - | 'waitingForConnection' - | 'preparingToExchangeInfo' - | 'exchangingDeviceInfo' - | 'waitingForVc' - | 'reviewing' - | 'reviewing.idle' - | 'reviewing.accepting' - | 'reviewing.accepting.requestingReceivedVcs' - | 'reviewing.accepting.requestingExistingVc' - | 'reviewing.accepting.prependingReceivedVc' - | 'reviewing.accepting.mergingIncomingVc' - | 'reviewing.accepting.storingVc' - | 'reviewing.acceptedIntentShare' - | 'reviewing.accepted' - | 'reviewing.rejected' - | 'reviewing.navigatingToHome' - | 'disconnected' - | { - checkingBluetoothService?: 'checking' | 'requesting' | 'enabled'; - reviewing?: - | 'idle' - | 'accepting' - | 'acceptedIntentShare' - | 'accepted' - | 'rejected' - | 'navigatingToHome' - | { - accepting?: - | 'requestingReceivedVcs' - | 'requestingExistingVc' - | 'prependingReceivedVc' - | 'mergingIncomingVc' - | 'storingVc'; - }; - }; - 'tags': never; -} diff --git a/machines/vc.typegen.ts b/machines/vc.typegen.ts index b107f4932b..2de8c11b12 100644 --- a/machines/vc.typegen.ts +++ b/machines/vc.typegen.ts @@ -1,64 +1,60 @@ -// 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: { - addVcToInProgressDownloads: 'ADD_VC_TO_IN_PROGRESS_DOWNLOADS'; - 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'; - removeVcFromInProgressDownlods: 'REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS'; - removeVcFromMyVcs: 'REMOVE_VC_FROM_CONTEXT'; - resetAreAllVcsDownloaded: 'RESET_ARE_ALL_VCS_DOWNLOADED'; - resetWalletBindingSuccess: 'RESET_WALLET_BINDING_SUCCESS'; - setDownloadedVCFromOpenId4VCI: 'VC_DOWNLOADED_FROM_OPENID4VCI'; - setDownloadedVc: 'VC_DOWNLOADED'; - setMyVcs: 'STORE_RESPONSE'; - setReceivedVcs: 'STORE_RESPONSE'; - setUpdatedVcMetadatas: 'VC_METADATA_UPDATED'; - setVcUpdate: 'VC_UPDATE'; - setWalletBindingSuccess: 'WALLET_BINDING_SUCCESS'; - updateMyVcs: 'VC_METADATA_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; -} + // 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: { + "addVcToInProgressDownloads": "ADD_VC_TO_IN_PROGRESS_DOWNLOADS"; +"getReceivedVcsResponse": "GET_RECEIVED_VCS"; +"getVcItemResponse": "GET_VC_ITEM"; +"loadMyVcs": "REFRESH_MY_VCS" | "REMOVE_TAMPERED_VCS" | "STORE_RESPONSE" | "xstate.init"; +"loadReceivedVcs": "REFRESH_RECEIVED_VCS" | "STORE_RESPONSE"; +"logTamperedVCsremoved": "REMOVE_TAMPERED_VCS"; +"moveExistingVcToTop": "VC_RECEIVED"; +"prependToMyVcs": "VC_ADDED"; +"prependToReceivedVcs": "VC_RECEIVED"; +"removeDownloadFailedVcsFromStorage": "DELETE_VC"; +"removeDownloadingFailedVcsFromMyVcs": "STORE_RESPONSE"; +"removeTamperedVcs": "REMOVE_TAMPERED_VCS"; +"removeVcFromInProgressDownlods": "DOWNLOAD_LIMIT_EXPIRED" | "REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS"; +"removeVcFromMyVcs": "REMOVE_VC_FROM_CONTEXT"; +"resetAreAllVcsDownloaded": "RESET_ARE_ALL_VCS_DOWNLOADED"; +"resetDownloadFailedVcs": "STORE_RESPONSE"; +"resetWalletBindingSuccess": "RESET_WALLET_BINDING_SUCCESS"; +"setDownloadedVCFromOpenId4VCI": "VC_DOWNLOADED_FROM_OPENID4VCI"; +"setDownloadedVc": "VC_DOWNLOADED"; +"setDownloadingFailedVcs": "DOWNLOAD_LIMIT_EXPIRED"; +"setMyVcs": "STORE_RESPONSE"; +"setReceivedVcs": "STORE_RESPONSE"; +"setTamperedVcs": "TAMPERED_VC"; +"setUpdatedVcMetadatas": "VC_METADATA_UPDATED"; +"setVcUpdate": "VC_UPDATE"; +"setWalletBindingSuccess": "WALLET_BINDING_SUCCESS"; +"updateMyVcs": "VC_METADATA_UPDATED"; + }; + eventsCausingDelays: { + + }; + eventsCausingGuards: { + "hasExistingReceivedVc": "VC_RECEIVED"; + }; + eventsCausingServices: { + + }; + matchesStates: "deletingFailedVcs" | "downloadLimitExpired" | "init" | "init.myVcs" | "init.receivedVcs" | "ready" | "ready.myVcs" | "ready.myVcs.idle" | "ready.myVcs.refreshing" | "ready.receivedVcs" | "ready.receivedVcs.idle" | "ready.receivedVcs.refreshing" | "tamperedVCs" | { "init"?: "myVcs" | "receivedVcs"; +"ready"?: "myVcs" | "receivedVcs" | { "myVcs"?: "idle" | "refreshing"; +"receivedVcs"?: "idle" | "refreshing"; }; }; + tags: never; + } From 74c1ec046e1507f4d7f0bde31f88b9b68c1ac1a7 Mon Sep 17 00:00:00 2001 From: Paolo Miguel de Leon Date: Tue, 30 Jan 2024 15:02:23 +0800 Subject: [PATCH 10/11] fix: typo --- machines/app.typegen.ts | 141 +++++++----------- machines/bleShare/request/requestMachine.ts | 1 + .../request/requestMachine.typegen.ts | 5 +- 3 files changed, 62 insertions(+), 85 deletions(-) diff --git a/machines/app.typegen.ts b/machines/app.typegen.ts index c7f12e2f3b..8d11ca57e4 100644 --- a/machines/app.typegen.ts +++ b/machines/app.typegen.ts @@ -1,84 +1,59 @@ -// This file was automatically generated. Edits will be overwritten -export interface Typegen0 { - '@@xstate/typegen': true; - internalEvents: { - 'done.invoke.app.init.intent:invocation[0]': { - type: 'done.invoke.app.init.intent:invocation[0]'; - data: unknown; - __tip: 'See the XState TS docs to learn how to strongly type this.'; - }; - 'xstate.init': {type: 'xstate.init'}; - }; - invokeSrcNameMap: { - checkFocusState: 'done.invoke.app.ready.focus:invocation[0]'; - checkIntent: 'done.invoke.app.init.intent:invocation[0]'; - checkNetworkState: 'done.invoke.app.ready.network:invocation[0]'; - getAppInfo: 'done.invoke.app.init.info:invocation[0]'; - }; - missingImplementations: { - actions: never; - delays: never; - guards: never; - services: never; - }; - eventsCausingActions: { - forwardToServices: 'ACTIVE' | 'INACTIVE' | 'OFFLINE' | 'ONLINE'; - loadCredentialRegistryHostFromStorage: 'READY'; - loadCredentialRegistryInConstants: 'STORE_RESPONSE'; - loadEsignetHostFromConstants: 'STORE_RESPONSE'; - loadEsignetHostFromStorage: 'READY'; - logServiceEvents: 'READY'; - logStoreEvents: 'done.invoke.app.init.intent:invocation[0]'; - requestDeviceInfo: 'REQUEST_DEVICE_INFO'; - resetKeyInvalidateError: 'READY' | 'RESET_KEY_INVALIDATE_ERROR_DISMISS'; - setAppInfo: 'APP_INFO_RECEIVED'; - setIntent: 'done.invoke.app.init.intent:invocation[0]'; - setIsDecryptError: 'DECRYPT_ERROR'; - setIsReadError: 'ERROR'; - spawnServiceActors: 'READY'; - spawnStoreActor: 'done.invoke.app.init.intent:invocation[0]'; - unsetIsDecryptError: 'DECRYPT_ERROR_DISMISS' | 'READY'; - unsetIsReadError: 'READY'; - updateKeyInvalidateError: 'ERROR' | 'KEY_INVALIDATE_ERROR'; - }; - eventsCausingDelays: {}; - eventsCausingGuards: {}; - eventsCausingServices: { - checkFocusState: 'APP_INFO_RECEIVED'; - checkIntent: - | 'KEY_INVALIDATE_ERROR' - | 'RESET_KEY_INVALIDATE_ERROR_DISMISS' - | 'xstate.init'; - checkNetworkState: 'APP_INFO_RECEIVED'; - getAppInfo: 'STORE_RESPONSE'; - }; - matchesStates: - | 'init' - | 'init.credentialRegistry' - | 'init.info' - | 'init.intent' - | 'init.services' - | 'init.store' - | 'ready' - | 'ready.focus' - | 'ready.focus.active' - | 'ready.focus.checking' - | 'ready.focus.inactive' - | 'ready.network' - | 'ready.network.checking' - | 'ready.network.offline' - | 'ready.network.online' - | 'waiting' - | { - init?: 'credentialRegistry' | 'info' | 'intent' | 'services' | 'store'; - ready?: - | 'focus' - | 'network' - | { - focus?: 'active' | 'checking' | 'inactive'; - network?: 'checking' | 'offline' | 'online'; - }; - }; - tags: never; -} + // This file was automatically generated. Edits will be overwritten + + export interface Typegen0 { + '@@xstate/typegen': true; + internalEvents: { + "done.invoke.app.init.intent:invocation[0]": { type: "done.invoke.app.init.intent:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." }; +"xstate.init": { type: "xstate.init" }; + }; + invokeSrcNameMap: { + "checkFocusState": "done.invoke.app.ready.focus:invocation[0]"; +"checkIntent": "done.invoke.app.init.intent:invocation[0]"; +"checkNetworkState": "done.invoke.app.ready.network:invocation[0]"; +"getAppInfo": "done.invoke.app.init.info:invocation[0]"; + }; + missingImplementations: { + actions: never; + delays: never; + guards: never; + services: never; + }; + eventsCausingActions: { + "forwardToServices": "ACTIVE" | "INACTIVE" | "OFFLINE" | "ONLINE"; +"loadCredentialRegistryHostFromStorage": "READY"; +"loadCredentialRegistryInConstants": "STORE_RESPONSE"; +"loadEsignetHostFromConstants": "STORE_RESPONSE"; +"loadEsignetHostFromStorage": "READY"; +"logServiceEvents": "READY"; +"logStoreEvents": "done.invoke.app.init.intent:invocation[0]"; +"requestDeviceInfo": "REQUEST_DEVICE_INFO"; +"resetKeyInvalidateError": "READY" | "RESET_KEY_INVALIDATE_ERROR_DISMISS"; +"setAppInfo": "APP_INFO_RECEIVED"; +"setIntent": "done.invoke.app.init.intent:invocation[0]"; +"setIsDecryptError": "DECRYPT_ERROR"; +"setIsReadError": "ERROR"; +"spawnServiceActors": "READY"; +"spawnStoreActor": "done.invoke.app.init.intent:invocation[0]"; +"unsetIsDecryptError": "DECRYPT_ERROR_DISMISS" | "READY"; +"unsetIsReadError": "READY"; +"updateKeyInvalidateError": "ERROR" | "KEY_INVALIDATE_ERROR"; + }; + eventsCausingDelays: { + + }; + eventsCausingGuards: { + + }; + eventsCausingServices: { + "checkFocusState": "APP_INFO_RECEIVED"; +"checkIntent": "KEY_INVALIDATE_ERROR" | "RESET_KEY_INVALIDATE_ERROR_DISMISS" | "xstate.init"; +"checkNetworkState": "APP_INFO_RECEIVED"; +"getAppInfo": "STORE_RESPONSE"; + }; + matchesStates: "init" | "init.credentialRegistry" | "init.info" | "init.intent" | "init.services" | "init.store" | "ready" | "ready.focus" | "ready.focus.active" | "ready.focus.checking" | "ready.focus.inactive" | "ready.network" | "ready.network.checking" | "ready.network.offline" | "ready.network.online" | "waiting" | { "init"?: "credentialRegistry" | "info" | "intent" | "services" | "store"; +"ready"?: "focus" | "network" | { "focus"?: "active" | "checking" | "inactive"; +"network"?: "checking" | "offline" | "online"; }; }; + tags: never; + } + \ No newline at end of file diff --git a/machines/bleShare/request/requestMachine.ts b/machines/bleShare/request/requestMachine.ts index 916b81561d..0fc216fa6f 100644 --- a/machines/bleShare/request/requestMachine.ts +++ b/machines/bleShare/request/requestMachine.ts @@ -699,6 +699,7 @@ export const requestMachine = phone: subject.phone, uin: subject.UIN, }); + } }, services: { diff --git a/machines/bleShare/request/requestMachine.typegen.ts b/machines/bleShare/request/requestMachine.typegen.ts index 40e36e3055..88002ba263 100644 --- a/machines/bleShare/request/requestMachine.typegen.ts +++ b/machines/bleShare/request/requestMachine.typegen.ts @@ -41,6 +41,7 @@ "removeLoggers": "DISCONNECT" | "RESET" | "SCREEN_BLUR" | "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]"; +"sendVcDataIntent": "STORE_RESPONSE"; "sendVcReceived": "STORE_RESPONSE"; "setBleError": "BLE_ERROR"; "setIncomingVc": "VC_RECEIVED"; @@ -76,9 +77,9 @@ "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" | "clearingConnection" | "disconnected" | "handlingBleError" | "inactive" | "nearByDevicesPermissionDenied" | "reviewing" | "reviewing.accepted" | "reviewing.accepting" | "reviewing.accepting.acceptedIntentShare" | "reviewing.accepting.mergingIncomingVc" | "reviewing.accepting.prependingReceivedVc" | "reviewing.accepting.requestingExistingVc" | "reviewing.accepting.requestingReceivedVcs" | "reviewing.accepting.storingVc" | "reviewing.displayingIncomingVC" | "reviewing.idle" | "reviewing.invalidIdentity" | "reviewing.navigatingToHistory" | "reviewing.navigatingToHome" | "reviewing.navigatingToReceivedCards" | "reviewing.rejected" | "reviewing.savingFailed" | "reviewing.savingFailed.idle" | "reviewing.savingFailed.viewingVc" | "reviewing.verifyingIdentity" | "reviewing.verifyingVp" | "storageLimitReached" | "waitingForConnection" | "waitingForVc" | "waitingForVc.inProgress" | "waitingForVc.timeout" | { "checkNearbyDevicesPermission"?: "checking" | "requesting"; + matchesStates: "bluetoothDenied" | "cancelling" | "checkNearbyDevicesPermission" | "checkNearbyDevicesPermission.checking" | "checkNearbyDevicesPermission.requesting" | "checkStorage" | "checkingBluetoothService" | "checkingBluetoothService.checking" | "checkingBluetoothService.enabled" | "checkingBluetoothService.requesting" | "clearingConnection" | "disconnected" | "handlingBleError" | "inactive" | "nearByDevicesPermissionDenied" | "reviewing" | "reviewing.accepted" | "reviewing.acceptedIntentShare" | "reviewing.accepting" | "reviewing.accepting.mergingIncomingVc" | "reviewing.accepting.prependingReceivedVc" | "reviewing.accepting.requestingExistingVc" | "reviewing.accepting.requestingReceivedVcs" | "reviewing.accepting.storingVc" | "reviewing.displayingIncomingVC" | "reviewing.idle" | "reviewing.invalidIdentity" | "reviewing.navigatingToHistory" | "reviewing.navigatingToHome" | "reviewing.navigatingToReceivedCards" | "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"; -"reviewing"?: "accepted" | "accepting" | "displayingIncomingVC" | "idle" | "invalidIdentity" | "navigatingToHistory" | "navigatingToHome" | "navigatingToReceivedCards" | "rejected" | "savingFailed" | "verifyingIdentity" | "verifyingVp" | { "accepting"?: "acceptedIntentShare" | "mergingIncomingVc" | "prependingReceivedVc" | "requestingExistingVc" | "requestingReceivedVcs" | "storingVc"; +"reviewing"?: "accepted" | "acceptedIntentShare" | "accepting" | "displayingIncomingVC" | "idle" | "invalidIdentity" | "navigatingToHistory" | "navigatingToHome" | "navigatingToReceivedCards" | "rejected" | "savingFailed" | "verifyingIdentity" | "verifyingVp" | { "accepting"?: "mergingIncomingVc" | "prependingReceivedVc" | "requestingExistingVc" | "requestingReceivedVcs" | "storingVc"; "savingFailed"?: "idle" | "viewingVc"; }; "waitingForVc"?: "inProgress" | "timeout"; }; tags: never; From 56a414e7bf96b1cf17b88feb5c09df40b0c21cc6 Mon Sep 17 00:00:00 2001 From: Paolo Miguel de Leon Date: Tue, 30 Jan 2024 15:49:11 +0800 Subject: [PATCH 11/11] fix: typos --- screens/MainLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/screens/MainLayout.tsx b/screens/MainLayout.tsx index c791cd88f5..449963595a 100644 --- a/screens/MainLayout.tsx +++ b/screens/MainLayout.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect }, {useContext} from 'react'; +import React, { useContext, useEffect } from 'react'; import { BottomTabNavigationOptions, createBottomTabNavigator,