mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-08 21:18:14 -05:00
[INJIMOB-1911]: add logic for QR login via deeplink (#1601)
* [INJIMOB-1911]: add logic for QR login via deeplink Signed-off-by: Alka Prasad <prasadalka1998@gmail.com> * [INJIMOB-1911]: bump up tuvali version Signed-off-by: Alka Prasad <prasadalka1998@gmail.com> * [INJIMOB-1911]: bump up kotlin patch version Signed-off-by: Alka Prasad <prasadalka1998@gmail.com> * [INJIMOB-1911]: rename the singleton variable name Signed-off-by: Alka Prasad <prasadalka1998@gmail.com> * [INJIMOB-1911]: extract common code in a function Signed-off-by: Alka Prasad <prasadalka1998@gmail.com> * [INJIMOB-1911]: refactor some logic and remove redundant code Signed-off-by: Alka Prasad <prasadalka1998@gmail.com> --------- Signed-off-by: Alka Prasad <prasadalka1998@gmail.com>
This commit is contained in:
@@ -258,7 +258,7 @@ dependencies {
|
||||
implementation 'com.facebook.soloader:soloader:0.10.1+'
|
||||
implementation("io.mosip:pixelpass:0.2.0")
|
||||
implementation("io.mosip:secure-keystore:0.2.0")
|
||||
implementation("io.mosip:tuvali:0.5.0")
|
||||
implementation("io.mosip:tuvali:0.5.1-SNAPSHOT")
|
||||
implementation("io.mosip:inji-vci-client:0.1.0")
|
||||
|
||||
def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
|
||||
|
||||
@@ -1,46 +1,86 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.mosip.residentapp" xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="https"/>
|
||||
</intent>
|
||||
</queries>
|
||||
<application tools:replace="usesCleartextTraffic" android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" android:usesCleartextTraffic="false">
|
||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_SDK_VERSION" android:value="48.0.0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://exp.host/@anonymous/inji"/>
|
||||
<activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|locale|layoutDirection" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="io.mosip.residentapp"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
|
||||
</application>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="io.mosip.residentapp">
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.ACCESS_COARSE_LOCATION"
|
||||
android:maxSdkVersion="28" />
|
||||
<uses-permission
|
||||
android:name="android.permission.ACCESS_FINE_LOCATION"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission
|
||||
android:name="android.permission.BLUETOOTH_SCAN"
|
||||
android:usesPermissionFlags="neverForLocation" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="https" />
|
||||
</intent>
|
||||
</queries>
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="false"
|
||||
tools:replace="usesCleartextTraffic">
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.ENABLED"
|
||||
android:value="true" />
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_SDK_VERSION"
|
||||
android:value="48.0.0" />
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH"
|
||||
android:value="ALWAYS" />
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS"
|
||||
android:value="0" />
|
||||
<meta-data
|
||||
android:name="expo.modules.updates.EXPO_UPDATE_URL"
|
||||
android:value="https://exp.host/@anonymous/inji" />
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|locale|layoutDirection"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="io.mosip.residentapp.inji" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -25,6 +25,7 @@ public class InjiPackage implements ReactPackage {
|
||||
modules.add(new RNVersionModule());
|
||||
modules.add(new RNWalletModule(new RNEventEmitter(reactApplicationContext), new Wallet(reactApplicationContext), reactApplicationContext));
|
||||
modules.add(new RNVerifierModule(new RNEventEmitter(reactApplicationContext), new Verifier(reactApplicationContext), reactApplicationContext));
|
||||
modules.add(new RNQrLoginIntentModule(reactApplicationContext));
|
||||
return modules;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.mosip.residentapp;
|
||||
|
||||
public class IntentData {
|
||||
private String qrData = "";
|
||||
private static IntentData intentData;
|
||||
public static IntentData getInstance() {
|
||||
if(intentData == null)
|
||||
intentData = new IntentData();
|
||||
return intentData;
|
||||
}
|
||||
public String getQrData() {
|
||||
return qrData;
|
||||
}
|
||||
|
||||
public void setQrData(String qrData) {
|
||||
this.qrData = qrData;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,20 +3,19 @@ import expo.modules.ReactActivityDelegateWrapper;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactActivityDelegate;
|
||||
import expo.modules.ReactActivityDelegateWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* IMPORTANT NOTE: The Android permission flow here works
|
||||
@@ -43,6 +42,22 @@ public class MainActivity extends ReactActivity {
|
||||
// This is required for expo-splash-screen.
|
||||
setTheme(R.style.AppTheme);
|
||||
super.onCreate(null);
|
||||
Intent intent = getIntent();
|
||||
readAndSetQRLoginIntentData(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
readAndSetQRLoginIntentData(intent);
|
||||
}
|
||||
|
||||
private void readAndSetQRLoginIntentData(Intent intent){
|
||||
Uri data = intent.getData();
|
||||
if(data != null && Objects.equals(data.getScheme(), "io.mosip.residentapp.inji")){
|
||||
IntentData intentData = IntentData.getInstance();
|
||||
intentData.setQrData(String.valueOf(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.mosip.residentapp;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
|
||||
public class RNQrLoginIntentModule extends ReactContextBaseJavaModule {
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "QrLoginIntent";
|
||||
}
|
||||
|
||||
RNQrLoginIntentModule(ReactApplicationContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void isQrLoginByDeepLink(Promise promise) {
|
||||
try {
|
||||
|
||||
IntentData intentData = IntentData.getInstance();
|
||||
promise.resolve(intentData.getQrData());
|
||||
|
||||
} catch (Exception e) {
|
||||
promise.reject("E_UNKNOWN", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void resetQRLoginDeepLinkData(){
|
||||
IntentData intentData = IntentData.getInstance();
|
||||
intentData.setQrData("");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,9 @@ import {
|
||||
createVcMetaMachine,
|
||||
vcMetaMachine,
|
||||
} from './VerifiableCredential/VCMetaMachine/VCMetaMachine';
|
||||
import {NativeModules} from 'react-native';
|
||||
|
||||
const QrLoginIntent = NativeModules.QrLoginIntent;
|
||||
|
||||
const model = createModel(
|
||||
{
|
||||
@@ -40,6 +43,7 @@ const model = createModel(
|
||||
isReadError: false,
|
||||
isDecryptError: false,
|
||||
isKeyInvalidateError: false,
|
||||
linkCode: '',
|
||||
},
|
||||
{
|
||||
events: {
|
||||
@@ -56,6 +60,7 @@ const model = createModel(
|
||||
APP_INFO_RECEIVED: (info: AppInfo) => ({info}),
|
||||
STORE_RESPONSE: (response: unknown) => ({response}),
|
||||
RESET_KEY_INVALIDATE_ERROR_DISMISS: () => ({}),
|
||||
RESET_LINKCODE: () => ({}),
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -78,6 +83,9 @@ export const appMachine = model.createMachine(
|
||||
DECRYPT_ERROR: {
|
||||
actions: ['setIsDecryptError'],
|
||||
},
|
||||
RESET_LINKCODE: {
|
||||
actions: ['resetLinkCode'],
|
||||
},
|
||||
DECRYPT_ERROR_DISMISS: {
|
||||
actions: ['unsetIsDecryptError'],
|
||||
},
|
||||
@@ -166,6 +174,17 @@ export const appMachine = model.createMachine(
|
||||
checking: {},
|
||||
active: {
|
||||
entry: ['forwardToServices'],
|
||||
invoke: [
|
||||
{
|
||||
src: 'isQrLoginByDeepLink',
|
||||
onDone: {
|
||||
actions: ['setLinkCode'],
|
||||
},
|
||||
},
|
||||
{
|
||||
src: 'resetQRLoginDeepLinkData',
|
||||
},
|
||||
],
|
||||
},
|
||||
inactive: {
|
||||
entry: ['forwardToServices'],
|
||||
@@ -198,7 +217,17 @@ export const appMachine = model.createMachine(
|
||||
},
|
||||
{
|
||||
actions: {
|
||||
forwardToServices: pure((context, event) =>
|
||||
setLinkCode: assign({
|
||||
linkCode: (_, event) => {
|
||||
if (event.data != '')
|
||||
return new URL(event.data).searchParams.get('linkCode')!!;
|
||||
return '';
|
||||
},
|
||||
}),
|
||||
resetLinkCode: assign({
|
||||
linkCode: '',
|
||||
}),
|
||||
forwardToSerices: pure((context, event) =>
|
||||
Object.values(context.serviceRefs).map(serviceRef =>
|
||||
send({...event, type: `APP_${event.type}`}, {to: serviceRef}),
|
||||
),
|
||||
@@ -345,6 +374,15 @@ export const appMachine = model.createMachine(
|
||||
},
|
||||
|
||||
services: {
|
||||
isQrLoginByDeepLink: () => async () => {
|
||||
const data = await QrLoginIntent.isQrLoginByDeepLink();
|
||||
//console.log('DeepLink: ', data);
|
||||
return data;
|
||||
},
|
||||
resetQRLoginDeepLinkData: () => async () => {
|
||||
return await QrLoginIntent.resetQRLoginDeepLinkData();
|
||||
},
|
||||
|
||||
getAppInfo: () => async callback => {
|
||||
const appInfo = {
|
||||
deviceId: getDeviceId(),
|
||||
@@ -447,3 +485,7 @@ export function selectIsDecryptError(state: State) {
|
||||
export function selectIsKeyInvalidateError(state: State) {
|
||||
return state.context.isKeyInvalidateError;
|
||||
}
|
||||
|
||||
export function selectIsLinkCode(state: State) {
|
||||
return state.context.linkCode;
|
||||
}
|
||||
|
||||
@@ -1,55 +1,89 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"checkFocusState": "done.invoke.app.ready.focus: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": "KEY_INVALIDATE_ERROR" | "RESET_KEY_INVALIDATE_ERROR_DISMISS" | "xstate.init";
|
||||
"requestDeviceInfo": "REQUEST_DEVICE_INFO";
|
||||
"resetKeyInvalidateError": "READY" | "RESET_KEY_INVALIDATE_ERROR_DISMISS";
|
||||
"setAppInfo": "APP_INFO_RECEIVED";
|
||||
"setIsDecryptError": "DECRYPT_ERROR";
|
||||
"setIsReadError": "ERROR";
|
||||
"spawnServiceActors": "READY";
|
||||
"spawnStoreActor": "KEY_INVALIDATE_ERROR" | "RESET_KEY_INVALIDATE_ERROR_DISMISS" | "xstate.init";
|
||||
"unsetIsDecryptError": "DECRYPT_ERROR_DISMISS" | "READY";
|
||||
"unsetIsReadError": "READY";
|
||||
"updateKeyInvalidateError": "ERROR" | "KEY_INVALIDATE_ERROR";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"checkFocusState": "APP_INFO_RECEIVED";
|
||||
"checkNetworkState": "APP_INFO_RECEIVED";
|
||||
"getAppInfo": "STORE_RESPONSE";
|
||||
};
|
||||
matchesStates: "init" | "init.credentialRegistry" | "init.info" | "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" | "services" | "store";
|
||||
"ready"?: "focus" | "network" | { "focus"?: "active" | "checking" | "inactive";
|
||||
"network"?: "checking" | "offline" | "online"; }; };
|
||||
tags: never;
|
||||
}
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'done.invoke.app.ready.focus.active:invocation[0]': {
|
||||
type: 'done.invoke.app.ready.focus.active: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]';
|
||||
checkNetworkState: 'done.invoke.app.ready.network:invocation[0]';
|
||||
getAppInfo: 'done.invoke.app.init.info:invocation[0]';
|
||||
isQrLoginByDeepLink: 'done.invoke.app.ready.focus.active:invocation[0]';
|
||||
resetQRLoginDeepLinkData: 'done.invoke.app.ready.focus.active:invocation[1]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: 'forwardToServices';
|
||||
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:
|
||||
| 'KEY_INVALIDATE_ERROR'
|
||||
| 'RESET_KEY_INVALIDATE_ERROR_DISMISS'
|
||||
| 'xstate.init';
|
||||
requestDeviceInfo: 'REQUEST_DEVICE_INFO';
|
||||
resetKeyInvalidateError: 'READY' | 'RESET_KEY_INVALIDATE_ERROR_DISMISS';
|
||||
resetLinkCode: 'RESET_LINKCODE';
|
||||
setAppInfo: 'APP_INFO_RECEIVED';
|
||||
setIsDecryptError: 'DECRYPT_ERROR';
|
||||
setIsReadError: 'ERROR';
|
||||
setLinkCode: 'done.invoke.app.ready.focus.active:invocation[0]';
|
||||
spawnServiceActors: 'READY';
|
||||
spawnStoreActor:
|
||||
| 'KEY_INVALIDATE_ERROR'
|
||||
| 'RESET_KEY_INVALIDATE_ERROR_DISMISS'
|
||||
| 'xstate.init';
|
||||
unsetIsDecryptError: 'DECRYPT_ERROR_DISMISS' | 'READY';
|
||||
unsetIsReadError: 'READY';
|
||||
updateKeyInvalidateError: 'ERROR' | 'KEY_INVALIDATE_ERROR';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {};
|
||||
eventsCausingServices: {
|
||||
checkFocusState: 'APP_INFO_RECEIVED';
|
||||
checkNetworkState: 'APP_INFO_RECEIVED';
|
||||
getAppInfo: 'STORE_RESPONSE';
|
||||
isQrLoginByDeepLink: 'ACTIVE';
|
||||
resetQRLoginDeepLinkData: 'ACTIVE';
|
||||
};
|
||||
matchesStates:
|
||||
| 'init'
|
||||
| 'init.credentialRegistry'
|
||||
| 'init.info'
|
||||
| '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' | 'services' | 'store';
|
||||
ready?:
|
||||
| 'focus'
|
||||
| 'network'
|
||||
| {
|
||||
focus?: 'active' | 'checking' | 'inactive';
|
||||
network?: 'checking' | 'offline' | 'online';
|
||||
};
|
||||
};
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -46,12 +46,14 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => {
|
||||
},
|
||||
}),
|
||||
|
||||
resetLinkCode: model.assign({
|
||||
linkcode: '',
|
||||
}),
|
||||
updateShowFaceAuthConsent: model.assign({
|
||||
showFaceAuthConsent: (_, event) => {
|
||||
return event.response || event.response === null;
|
||||
},
|
||||
}),
|
||||
|
||||
setShowFaceAuthConsent: model.assign({
|
||||
showFaceAuthConsent: (_, event) => {
|
||||
return !event.isDoNotAskAgainChecked;
|
||||
@@ -230,6 +232,10 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => {
|
||||
linkCode: (_, event) =>
|
||||
new URL(event.params).searchParams.get('linkCode'),
|
||||
}),
|
||||
|
||||
setLinkCodeFromDeepLink: assign({
|
||||
linkCode: (_, event) => event.linkCode,
|
||||
}),
|
||||
setQuickShareData: assign({
|
||||
quickShareData: (_, event) =>
|
||||
JSON.parse(
|
||||
|
||||
@@ -82,6 +82,20 @@ export const scanMachine =
|
||||
cond: 'isMinimumStorageRequiredForAuditEntryReached',
|
||||
target: 'restrictSharingVc',
|
||||
},
|
||||
{
|
||||
target: 'qrLoginViaDeepLink',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
qrLoginViaDeepLink: {
|
||||
on: {
|
||||
QRLOGIN_VIA_DEEP_LINK: [
|
||||
{
|
||||
actions: ['setChildRef', 'setLinkCodeFromDeepLink'],
|
||||
cond: (_, event) => event.linkCode != '',
|
||||
target: '#scan.showQrLogin',
|
||||
},
|
||||
{
|
||||
target: 'startPermissionCheck',
|
||||
},
|
||||
@@ -362,7 +376,10 @@ export const scanMachine =
|
||||
},
|
||||
},
|
||||
on: {
|
||||
DISMISS: '#scan.checkFaceAuthConsent',
|
||||
DISMISS: {
|
||||
target: '#scan.checkFaceAuthConsent',
|
||||
actions: ['resetLinkCode'],
|
||||
},
|
||||
},
|
||||
initial: 'idle',
|
||||
states: {
|
||||
@@ -385,6 +402,7 @@ export const scanMachine =
|
||||
getStartEventData(TelemetryConstants.FlowType.qrLogin),
|
||||
),
|
||||
],
|
||||
exit: ['resetLinkCode'],
|
||||
},
|
||||
connecting: {
|
||||
invoke: {
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface Typegen0 {
|
||||
type: 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
'xstate.stop': {type: 'xstate.stop'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
checkBluetoothPermission: 'done.invoke.scan.checkBluetoothPermission.checking:invocation[0]';
|
||||
@@ -55,6 +56,7 @@ export interface Typegen0 {
|
||||
| 'removeLoggers'
|
||||
| 'resetFaceCaptureBannerStatus'
|
||||
| 'resetFlowType'
|
||||
| 'resetLinkCode'
|
||||
| 'resetSelectedVc'
|
||||
| 'resetShowQuickShareSuccessBanner'
|
||||
| 'sendBLEConnectionErrorEvent'
|
||||
@@ -67,6 +69,7 @@ export interface Typegen0 {
|
||||
| 'setChildRef'
|
||||
| 'setFlowType'
|
||||
| 'setLinkCode'
|
||||
| 'setLinkCodeFromDeepLink'
|
||||
| 'setQuickShareData'
|
||||
| 'setReadyForBluetoothStateCheck'
|
||||
| 'setReceiverInfo'
|
||||
@@ -132,7 +135,10 @@ export interface Typegen0 {
|
||||
| 'SCREEN_BLUR'
|
||||
| 'STORE_RESPONSE'
|
||||
| 'xstate.init';
|
||||
resetFaceCaptureBannerStatus: 'ACCEPT_REQUEST' | 'CLOSE_BANNER';
|
||||
resetFaceCaptureBannerStatus:
|
||||
| 'ACCEPT_REQUEST'
|
||||
| 'CLOSE_BANNER'
|
||||
| 'STORE_RESPONSE';
|
||||
resetFlowType:
|
||||
| 'DISCONNECT'
|
||||
| 'DISMISS'
|
||||
@@ -141,6 +147,15 @@ export interface Typegen0 {
|
||||
| 'RESET'
|
||||
| 'SCREEN_BLUR'
|
||||
| 'xstate.init';
|
||||
resetLinkCode:
|
||||
| 'BLE_ERROR'
|
||||
| 'DISMISS'
|
||||
| 'DISMISS_QUICK_SHARE_BANNER'
|
||||
| 'RESET'
|
||||
| 'SCREEN_BLUR'
|
||||
| 'SCREEN_FOCUS'
|
||||
| 'SELECT_VC'
|
||||
| 'xstate.stop';
|
||||
resetSelectedVc:
|
||||
| 'DISCONNECT'
|
||||
| 'DISMISS'
|
||||
@@ -151,15 +166,16 @@ export interface Typegen0 {
|
||||
| 'xstate.init';
|
||||
resetShowQuickShareSuccessBanner: 'DISMISS' | 'DISMISS_QUICK_SHARE_BANNER';
|
||||
sendBLEConnectionErrorEvent: 'BLE_ERROR';
|
||||
sendScanData: 'SCAN';
|
||||
sendScanData: 'QRLOGIN_VIA_DEEP_LINK' | 'SCAN';
|
||||
sendVCShareFlowCancelEndEvent: 'CANCEL';
|
||||
sendVCShareFlowTimeoutEndEvent: 'CANCEL' | 'RETRY';
|
||||
sendVcShareSuccessEvent: 'VC_ACCEPTED';
|
||||
sendVcSharingStartEvent: 'SCAN';
|
||||
setBleError: 'BLE_ERROR';
|
||||
setChildRef: 'STORE_RESPONSE';
|
||||
setChildRef: 'QRLOGIN_VIA_DEEP_LINK' | 'STORE_RESPONSE';
|
||||
setFlowType: 'SELECT_VC';
|
||||
setLinkCode: 'SCAN';
|
||||
setLinkCodeFromDeepLink: 'QRLOGIN_VIA_DEEP_LINK';
|
||||
setQuickShareData: 'SCAN';
|
||||
setReadyForBluetoothStateCheck: 'BLUETOOTH_PERMISSION_ENABLED';
|
||||
setReceiverInfo: 'CONNECTED';
|
||||
@@ -194,7 +210,7 @@ export interface Typegen0 {
|
||||
uptoAndroid11: '' | 'START_PERMISSION_CHECK';
|
||||
};
|
||||
eventsCausingServices: {
|
||||
QrLogin: 'SCAN';
|
||||
QrLogin: 'QRLOGIN_VIA_DEEP_LINK' | 'SCAN';
|
||||
checkBluetoothPermission:
|
||||
| ''
|
||||
| 'BLUETOOTH_STATE_DISABLED'
|
||||
@@ -251,6 +267,7 @@ export interface Typegen0 {
|
||||
| 'loadVCS.idle'
|
||||
| 'loadVCS.navigatingToHome'
|
||||
| 'nearByDevicesPermissionDenied'
|
||||
| 'qrLoginViaDeepLink'
|
||||
| 'recheckBluetoothState'
|
||||
| 'recheckBluetoothState.checking'
|
||||
| 'recheckBluetoothState.enabled'
|
||||
|
||||
@@ -55,6 +55,7 @@ const ScanEvents = {
|
||||
}),
|
||||
ALLOWED: () => ({}),
|
||||
DENIED: () => ({}),
|
||||
QRLOGIN_VIA_DEEP_LINK: (linkCode: string) => ({linkCode}),
|
||||
};
|
||||
|
||||
export const ScanModel = createModel(
|
||||
|
||||
@@ -125,3 +125,7 @@ export function selectIsMinimumStorageRequiredForAuditEntryLimitReached(
|
||||
export function selectIsFaceVerificationConsent(state: State) {
|
||||
return state.matches('reviewing.faceVerificationConsent');
|
||||
}
|
||||
|
||||
export function selectIsQrLoginViaDeepLink(state: State) {
|
||||
return state.matches('qrLoginViaDeepLink');
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ import {NotificationsScreen} from '../screens/NotificationsScreen';
|
||||
import {SetupLanguageScreen} from '../screens/SetupLanguageScreen';
|
||||
import {IntroSlidersScreen} from '../screens/Home/IntroSlidersScreen';
|
||||
import {RequestLayout} from '../screens/Request/RequestLayout';
|
||||
import {RequestStackParamList} from '../screens/Request/RequestLayoutController';
|
||||
import {SplashScreen} from '../screens/SplashScreen';
|
||||
import {RequestStackParamList} from './routesConstants';
|
||||
|
||||
export const baseRoutes: Screen[] = [
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useContext} from 'react';
|
||||
import React, {useContext, useEffect} from 'react';
|
||||
import {
|
||||
BottomTabNavigationOptions,
|
||||
createBottomTabNavigator,
|
||||
@@ -17,9 +17,18 @@ import {CopilotProvider} from 'react-native-copilot';
|
||||
import {View} from 'react-native';
|
||||
import {CopilotTooltip} from '../components/CopilotTooltip';
|
||||
import {Copilot} from '../components/ui/Copilot';
|
||||
import {useSelector} from '@xstate/react';
|
||||
import {selectIsLinkCode} from '../machines/app';
|
||||
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||
import {BOTTOM_TAB_ROUTES, ScanStackParamList} from '../routes/routesConstants';
|
||||
import {MainBottomTabParamList} from '../routes/routeTypes';
|
||||
|
||||
const {Navigator, Screen} = createBottomTabNavigator();
|
||||
|
||||
type ScanLayoutNavigation = NavigationProp<
|
||||
ScanStackParamList & MainBottomTabParamList
|
||||
>;
|
||||
|
||||
export const MainLayout: React.FC = () => {
|
||||
const {t} = useTranslation('MainLayout');
|
||||
|
||||
@@ -31,6 +40,15 @@ export const MainLayout: React.FC = () => {
|
||||
tabBarActiveTintColor: Theme.Colors.IconBg,
|
||||
...Theme.BottomTabBarStyle,
|
||||
};
|
||||
const navigation = useNavigation<ScanLayoutNavigation>();
|
||||
|
||||
const linkCode = useSelector(appService, selectIsLinkCode);
|
||||
|
||||
useEffect(() => {
|
||||
if (linkCode != '') {
|
||||
navigation.navigate(BOTTOM_TAB_ROUTES.share);
|
||||
}
|
||||
}, [linkCode]);
|
||||
|
||||
return (
|
||||
<CopilotProvider
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
selectIsFaceIdentityVerified,
|
||||
selectCredential,
|
||||
selectVerifiableCredentialData,
|
||||
selectIsQrLoginViaDeepLink,
|
||||
} from '../../machines/bleShare/scan/scanSelectors';
|
||||
import {
|
||||
selectBleError,
|
||||
@@ -43,6 +44,7 @@ import {BOTTOM_TAB_ROUTES, SCAN_ROUTES} from '../../routes/routesConstants';
|
||||
import {ScanStackParamList} from '../../routes/routesConstants';
|
||||
import {VCShareFlowType} from '../../shared/Utils';
|
||||
import {Theme} from '../../components/ui/styleUtils';
|
||||
import {APP_EVENTS, selectIsLinkCode} from '../../machines/app';
|
||||
|
||||
type ScanLayoutNavigation = NavigationProp<
|
||||
ScanStackParamList & MainBottomTabParamList
|
||||
@@ -75,6 +77,10 @@ export function useScanLayout() {
|
||||
scanService,
|
||||
selectVerifiableCredentialData,
|
||||
);
|
||||
const isQrLoginViaDeepLink = useSelector(
|
||||
scanService,
|
||||
selectIsQrLoginViaDeepLink,
|
||||
);
|
||||
|
||||
const locationError = {message: '', button: ''};
|
||||
|
||||
@@ -121,6 +127,7 @@ export function useScanLayout() {
|
||||
scanService,
|
||||
selectIsExchangingDeviceInfoTimeout,
|
||||
);
|
||||
const linkCode = useSelector(appService, selectIsLinkCode);
|
||||
const isAccepted = useSelector(scanService, selectIsAccepted);
|
||||
const isRejected = useSelector(scanService, selectIsRejected);
|
||||
const isSent = useSelector(scanService, selectIsSent);
|
||||
@@ -262,6 +269,9 @@ export function useScanLayout() {
|
||||
if (isDone) {
|
||||
changeTabBarVisible('flex');
|
||||
navigation.navigate(BOTTOM_TAB_ROUTES.home);
|
||||
} else if (isQrLoginViaDeepLink) {
|
||||
scanService.send(ScanEvents.QRLOGIN_VIA_DEEP_LINK(linkCode));
|
||||
appService.send(APP_EVENTS.RESET_LINKCODE());
|
||||
} else if (
|
||||
isReviewing &&
|
||||
flowType === VCShareFlowType.SIMPLE_SHARE &&
|
||||
@@ -284,6 +294,7 @@ export function useScanLayout() {
|
||||
isBleError,
|
||||
flowType,
|
||||
isAccepted,
|
||||
isQrLoginViaDeepLink,
|
||||
]);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user