[INJIMOB-3181] - Add Deeplink support for iOS (#1907)

* [INJIMOB-3181]: add deep link support for ios

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: add deep link support for ios

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: add deep link support for ios

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: show popup for qrlogin when inital setup of app is incomplete

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: show popup for qrlogin when inital setup of app is incomplete

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: refactor deep link flow for future features

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: refactor deep link flow for future features

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: update locales for no shareable VCs

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: refactor auth selector

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

* [INJIMOB-3181]: refactor deeplink native modules

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>

---------

Signed-off-by: adityankannan-tw <adityan.kannan@thoughtworks.com>
This commit is contained in:
adityankannan-tw
2025-04-25 19:12:30 +05:30
committed by GitHub
parent 7d7671075a
commit 858343a7c9
14 changed files with 200 additions and 11 deletions

30
App.tsx
View File

@@ -1,4 +1,4 @@
import React, {useContext, useEffect} from 'react';
import React, {useContext, useEffect, useState} from 'react';
import {AppLayout} from './screens/AppLayout';
import {useFont} from "./shared/hooks/useFont";
import {GlobalContextProvider} from './components/GlobalContextProvider';
@@ -9,6 +9,7 @@ import {
APP_EVENTS,
selectIsDecryptError,
selectIsKeyInvalidateError,
selectIsLinkCode,
selectIsReadError,
selectIsReady,
} from './machines/app';
@@ -28,6 +29,7 @@ import i18n from './i18n';
import {CopilotProvider} from 'react-native-copilot';
import {CopilotTooltip} from './components/CopilotTooltip';
import {Theme} from './components/ui/styleUtils';
import { selectAppSetupComplete } from './machines/auth';
const {RNSecureKeystoreModule} = NativeModules;
// kludge: this is a bad practice but has been done temporarily to surface
@@ -49,8 +51,15 @@ const DecryptErrorAlert = (controller, t) => {
const AppLayoutWrapper: React.FC = () => {
const {appService} = useContext(GlobalContext);
const isDecryptError = useSelector(appService, selectIsDecryptError);
const isQrLogin = useSelector(appService, selectIsLinkCode);
const controller = useApp();
const {t} = useTranslation('WelcomeScreen');
const authService = appService.children.get('auth');
const isAppSetupComplete = useSelector(authService, selectAppSetupComplete);
const [isOverlayVisible, setOverlayVisible] = useState(isQrLogin !== '');
useEffect(() => {
if (AppState.currentState === 'active') {
appService.send(APP_EVENTS.ACTIVE());
@@ -59,11 +68,28 @@ const AppLayoutWrapper: React.FC = () => {
}
}, []);
useEffect(() => {
setOverlayVisible(isQrLogin !== '');
}, [isQrLogin]);
if (isDecryptError) {
DecryptErrorAlert(controller, t);
}
configureTelemetry();
return <AppLayout />;
return (
<>
<AppLayout />
<MessageOverlay
isVisible={isOverlayVisible && !isAppSetupComplete}
title={t('qrLoginOverlay.title')}
message={t('qrLoginOverlay.message')}
onButtonPress={() => {setOverlayVisible(false)}}
buttonText={t('common:ok')}
minHeight={'auto'}
/>
</>
);
};
const AppLoadingWrapper: React.FC = () => {

View File

@@ -13,6 +13,9 @@
1E6875E92CA554E80086D870 /* OpenID4VP in Frameworks */ = {isa = PBXBuildFile; productRef = 1E6875E82CA554E80086D870 /* OpenID4VP */; };
1E6875EB2CA554FD0086D870 /* RNOpenID4VPModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */; };
1E6875ED2CA5550F0086D870 /* RNOpenID4VPModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */; };
1EED69F92DA913D30042EAFC /* IntentData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EED69F82DA913D30042EAFC /* IntentData.swift */; };
1EED69FB2DA914130042EAFC /* RNDeepLinkIntentModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EED69FA2DA914130042EAFC /* RNDeepLinkIntentModule.swift */; };
1EED69FD2DA914D00042EAFC /* RNDeepLinkIntentModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EED69FC2DA914D00042EAFC /* RNDeepLinkIntentModule.m */; };
34873E472CD8DAF3004DE734 /* VCIClient in Frameworks */ = {isa = PBXBuildFile; productRef = 34873E462CD8DAF3004DE734 /* VCIClient */; };
34873E4D2CD8DD11004DE734 /* pixelpass in Frameworks */ = {isa = PBXBuildFile; productRef = 34873E4C2CD8DD11004DE734 /* pixelpass */; };
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
@@ -68,6 +71,9 @@
1D23B9CD47CFD7F3C87D202F /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Inji/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNOpenID4VPModule.m; sourceTree = "<group>"; };
1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNOpenID4VPModule.swift; sourceTree = "<group>"; };
1EED69F82DA913D30042EAFC /* IntentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentData.swift; sourceTree = "<group>"; };
1EED69FA2DA914130042EAFC /* RNDeepLinkIntentModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNDeepLinkIntentModule.swift; sourceTree = "<group>"; };
1EED69FC2DA914D00042EAFC /* RNDeepLinkIntentModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNDeepLinkIntentModule.m; sourceTree = "<group>"; };
58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Inji.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Inji.a"; sourceTree = BUILT_PRODUCTS_DIR; };
6C2E3173556A471DD304B334 /* Pods-Inji.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Inji.debug.xcconfig"; path = "Target Support Files/Pods-Inji/Pods-Inji.debug.xcconfig"; sourceTree = "<group>"; };
7A4D352CD337FB3A3BF06240 /* Pods-Inji.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Inji.release.xcconfig"; path = "Target Support Files/Pods-Inji/Pods-Inji.release.xcconfig"; sourceTree = "<group>"; };
@@ -155,6 +161,9 @@
1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */,
1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */,
1D23B9CD47CFD7F3C87D202F /* PrivacyInfo.xcprivacy */,
1EED69F82DA913D30042EAFC /* IntentData.swift */,
1EED69FA2DA914130042EAFC /* RNDeepLinkIntentModule.swift */,
1EED69FC2DA914D00042EAFC /* RNDeepLinkIntentModule.m */,
);
name = Inji;
sourceTree = "<group>";
@@ -541,6 +550,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1EED69FD2DA914D00042EAFC /* RNDeepLinkIntentModule.m in Sources */,
1E6875ED2CA5550F0086D870 /* RNOpenID4VPModule.swift in Sources */,
9C48504F2C3E59B5002ECBD5 /* RNVersionModule.swift in Sources */,
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
@@ -551,11 +561,13 @@
9C4850532C3E59E2002ECBD5 /* RNEventEmitterProtocol.swift in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
9C4850502C3E59B5002ECBD5 /* RNEventMapper.swift in Sources */,
1EED69FB2DA914130042EAFC /* RNDeepLinkIntentModule.swift in Sources */,
9C7CDF432C7CC13500243A9A /* RNSecureKeystoreModule.m in Sources */,
E86208172C0335EC007C3E24 /* RNVCIClientModule.m in Sources */,
9C48504E2C3E59B5002ECBD5 /* RNEventEmitter.swift in Sources */,
9C7CDF3E2C7CBEDE00243A9A /* RNSecureKeystoreModule.swift in Sources */,
9C48504B2C3E59B5002ECBD5 /* RNWalletModule.swift in Sources */,
1EED69F92DA913D30042EAFC /* IntentData.swift in Sources */,
9C48504D2C3E59B5002ECBD5 /* RNWalletModule.m in Sources */,
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */,
9C4850512C3E59B5002ECBD5 /* RNVersionModule.m in Sources */,

View File

@@ -3,8 +3,17 @@
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <ExpoModulesCore-Swift.h>
#import "Inji-Swift.h"
@implementation AppDelegate
typedef NS_ENUM(NSInteger, URLScheme) {
URLSchemeInji,
URLSchemeOpenID4VP,
URLSchemeUnknown
};
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"main";
@@ -42,9 +51,36 @@
// Linking API
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
[self handleIntent:url];
return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
}
- (void)handleIntent:(NSURL *)url {
URLScheme scheme = [self schemeFromURL:url];
IntentData *intentData = [IntentData shared];
switch (scheme) {
case URLSchemeInji:
[intentData setQrData:url.absoluteString];
break;
case URLSchemeOpenID4VP:
[intentData setOvpQrData:url.absoluteString];
break;
case URLSchemeUnknown:
break;
}
}
- (URLScheme)schemeFromURL:(NSURL *)url {
if ([url.scheme isEqualToString:@"io.mosip.residentapp.inji"]) {
return URLSchemeInji;
} else if ([url.scheme isEqualToString:@"openid4vp"]) {
return URLSchemeOpenID4VP;
}
return URLSchemeUnknown;
}
// Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];

View File

@@ -28,6 +28,12 @@
<string>io.mosip.residentapp</string>
</array>
</dict>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>io.mosip.residentapp.inji</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>

63
ios/IntentData.swift Normal file
View File

@@ -0,0 +1,63 @@
import Foundation
@objc public class IntentData: NSObject {
@objc public static let shared = IntentData()
private let syncQueue = DispatchQueue(label: "com.intentdata.syncQueue", attributes: .concurrent)
private var qrData: String = ""
private var ovpQrData: String = ""
private override init() {
super.init()
}
@objc public func getQrData() -> String {
var data: String = ""
syncQueue.sync {
data = qrData
}
return data
}
@objc public func setQrData(_ newValue: String) {
syncQueue.async(flags: .barrier) {
self.qrData = newValue
}
}
@objc public func getOvpQrData() -> String {
var data: String = ""
syncQueue.sync {
data = ovpQrData
}
return data
}
@objc public func setOvpQrData(_ newValue: String) {
syncQueue.async(flags: .barrier) {
self.ovpQrData = newValue
}
}
func getDataByFlow(_ flowType: String?) -> String {
switch flowType {
case "qrLoginFlow":
return getQrData()
case "ovpFlow":
return getOvpQrData()
default:
return ""
}
}
func resetDataByFlow(_ flowType: String) {
switch flowType {
case "qrLoginFlow":
setQrData("")
case "ovpFlow":
setOvpQrData("")
default:
break
}
}
}

View File

@@ -0,0 +1,9 @@
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(DeepLinkIntent,NSObject)
RCT_EXTERN_METHOD(getDeepLinkIntentData:(NSString *)flowType resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(resetDeepLinkIntentData:(NSString *)flowType)
@end

View File

@@ -0,0 +1,24 @@
import Foundation
import React
@objc(DeepLinkIntent)
class RNDeepLinkIntentModule: NSObject, RCTBridgeModule {
static func moduleName() -> String {
return "DeepLinkIntent"
}
@objc func getDeepLinkIntentData(_ flowType: String, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
let intentData = IntentData.shared
let result = intentData.getDataByFlow(flowType)
resolve(result)
}
@objc func resetDeepLinkIntentData(_ flowType: String) {
IntentData.shared.resetDataByFlow(flowType)
}
@objc static func requiresMainQueueSetup() -> Bool {
return false
}
}

View File

@@ -675,7 +675,7 @@
"shareWithSelfieMessageQrLogin": "من أجل الوصول إلى البوابة، ستحتاج إلى مشاركة بيانات الاعتماد التي يمكن التحقق منها والتحقق من هويتك بشكل آمن باستخدام التحقق من الوجه. من خلال المتابعة، فإنك توافق على استخدام Inji للكاميرا الخاصة بك لهذا الغرض. \n\n سيتم استخدام بيانات وجهك فقط للتحقق ولن تتم مشاركتها. بعد التحقق بنجاح، يمكنك اختيار التفاصيل التي تريد مشاركتها.",
"ConfirmButton": "أفهم",
"doNotAskMessage": "لا تسألني مرة أخرى",
"noShareableVcs": "لا تتوفر بطاقات قابلة للمشاركة",
"noShareableVcs": "لا توجد بطاقات متاحة للمشاركة.",
"bluetoothStateAndroid": "يرجى تشغيل البلوتوث من الإعدادات السريعة لدعم المشاركة المحلية",
"bluetoothStateIos": "يرجى تشغيل البلوتوث من مركز التحكم لدعم المشاركة المحلية",
"enableBluetoothMessage": "يرجى تمكين أذونات البلوتوث لدعم المشاركة المحلية",

View File

@@ -683,7 +683,7 @@
"shareWithSelfieMessageQrLogin": "In order to access the portal, youll need to share your Verifiable Credentials and verify your identity securely using face verification. By continuing, you consent to Inji using your camera for this purpose. \n\n Your facial data will only be used for verification and will not be shared. After successful verification, you can choose which details to share.",
"ConfirmButton": "I Understand",
"doNotAskMessage": "Don't ask me again",
"noShareableVcs": "No shareable cards are available.",
"noShareableVcs": "No cards are available for sharing.",
"sharingVc": "Sharing card",
"bluetoothStateIos": "Bluetooth is turned OFF, please turn it ON from Control center",
"bluetoothStateAndroid": "Bluetooth is turned OFF, please turn it ON from Quick settings menu",
@@ -989,6 +989,10 @@
"message": "Due to the fingerprint / facial recognition update, app security was impacted, and downloaded cards were removed. Please download again."
}
},
"qrLoginOverlay": {
"title": "Setup incomplete",
"message": "Please finish the initial setup to proceed."
},
"ignore": "Ignore"
},
"SetupLanguage": {

View File

@@ -678,7 +678,7 @@
"shareWithSelfieMessageQrLogin": "Upang ma-access ang portal, kakailanganin mong ibahagi ang iyong Mga Na-verify na Kredensyal at secure na i-verify ang iyong pagkakakilanlan gamit ang pag-verify sa mukha. Sa pagpapatuloy, pumapayag ka sa Inji na gamitin ang iyong camera para sa layuning ito. \n\n Gagamitin lang ang iyong facial data para sa pag-verify at hindi ibabahagi. Pagkatapos ng matagumpay na pag-verify, maaari mong piliin kung aling mga detalye ang ibabahagi.",
"ConfirmButton": "Naiintindihan ko",
"doNotAskMessage": "Huwag mo na akong tanungin",
"noShareableVcs": "Walang magagamit na mga card na maibabahagi.",
"noShareableVcs": "Walang available na card para sa pagbabahagi.",
"sharingVc": "Pagbabahagi ng card",
"bluetoothStateIos": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",
"bluetoothStateAndroid": "Naka-OFF ang Bluetooth, paki-ON ito mula sa control center",

View File

@@ -681,7 +681,7 @@
"shareWithSelfieMessageQrLogin": "Iपोर्टल तक पहुंचने के लिए, आपको अपने सत्यापन योग्य क्रेडेंशियल साझा करने और चेहरे के सत्यापन का उपयोग करके अपनी पहचान को सुरक्षित रूप से सत्यापित करने की आवश्यकता होगी। जारी रखकर, आप इंजी को इस उद्देश्य के लिए अपने कैमरे का उपयोग करने के लिए सहमति देते हैं। \n\n आपके चेहरे का डेटा केवल सत्यापन के लिए उपयोग किया जाएगा और साझा नहीं किया जाएगा। सफल सत्यापन के बाद, आप चुन सकते हैं कि कौन सा विवरण साझा करना है।",
"ConfirmButton": "मैं समझता हूँ",
"doNotAskMessage": "मुझसे दोबारा मत पूछना",
"noShareableVcs": "कोई साझा करने योग्य कार्ड उपलब्ध नहीं है।",
"noShareableVcs": "कोई भी कार्ड साझा करने के लिए उपलब्ध नहीं है।",
"sharingVc": "कार्ड साझा करना",
"bluetoothStateIos": "ब्लूटूथ बंद है, कृपया इसे नियंत्रण केंद्र से चालू करें",
"bluetoothStateAndroid": "ब्लूटूथ बंद है, कृपया इसे त्वरित सेटिंग मेनू से चालू करें",

View File

@@ -679,7 +679,7 @@
"shareWithSelfieMessageQrLogin": "ಪೋರ್ಟಲ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು, ನೀವು ನಿಮ್ಮ ಪರಿಶೀಲಿಸಬಹುದಾದ ರುಜುವಾತುಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಬೇಕು ಮತ್ತು ಮುಖ ಪರಿಶೀಲನೆಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಗುರುತನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಪರಿಶೀಲಿಸಬೇಕು. ಮುಂದುವರಿಯುವ ಮೂಲಕ, ಈ ಉದ್ದೇಶಕ್ಕಾಗಿ ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಲು ನೀವು ಇಂಜಿಗೆ ಸಮ್ಮತಿಸುತ್ತೀರಿ. \n\n ನಿಮ್ಮ ಮುಖದ ಡೇಟಾವನ್ನು ಪರಿಶೀಲನೆಗಾಗಿ ಮಾತ್ರ ಬಳಸಲಾಗುತ್ತದೆ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳಲಾಗುವುದಿಲ್ಲ. ಯಶಸ್ವಿ ಪರಿಶೀಲನೆಯ ನಂತರ, ಯಾವ ವಿವರಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಬೇಕೆಂದು ನೀವು ಆಯ್ಕೆ ಮಾಡಬಹುದು.",
"ConfirmButton": "ನಾನು ಅರ್ಥಮಾಡಿಕೊಂಡಿದ್ದೇನೆ",
"doNotAskMessage": "ಅಂತ ಮತ್ತೆ ಕೇಳಬೇಡ",
"noShareableVcs": "ಹಂಚಿಕೊಳ್ಳಬಹುದಾದ ಯಾವುದೇ ಕಾರ್ಡ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ.",
"noShareableVcs": "ಹಂಚಿಕೊಳ್ಳಲು ಯಾವುದೇ ಕಾರ್ಡ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ.",
"sharingVc": "ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ",
"bluetoothStateIos": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ಅದನ್ನು ನಿಯಂತ್ರಣ ಕೇಂದ್ರದಿಂದ ಆನ್ ಮಾಡಿ",
"bluetoothStateAndroid": "ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ, ದಯವಿಟ್ಟು ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಮೆನುವಿನಿಂದ ಅದನ್ನು ಆನ್ ಮಾಡಿ",

View File

@@ -679,7 +679,7 @@
"shareWithSelfieMessageQrLogin": "போர்ட்டலை அணுக, உங்கள் சரிபார்க்கக்கூடிய சான்றுகளைப் பகிர வேண்டும் மற்றும் முகச் சரிபார்ப்பைப் பயன்படுத்தி உங்கள் அடையாளத்தைப் பாதுகாப்பாகச் சரிபார்க்க வேண்டும். தொடர்வதன் மூலம், இந்த நோக்கத்திற்காக உங்கள் கேமராவைப் பயன்படுத்துவதற்கு இன்ஜி ஒப்புக்கொள்கிறீர்கள். \n\n உங்கள் முகத் தரவு சரிபார்ப்புக்கு மட்டுமே பயன்படுத்தப்படும் மற்றும் பகிரப்படாது. வெற்றிகரமான சரிபார்ப்புக்குப் பிறகு, எந்த விவரங்களைப் பகிர வேண்டும் என்பதை நீங்கள் தேர்வு செய்யலாம்.",
"ConfirmButton": "எனக்கு புரிகிறது",
"doNotAskMessage": "மீண்டும் என்னிடம் கேட்காதே",
"noShareableVcs": "பகிரக்கூடிய அட்டைகள் எதுவும் இல்லை.",
"noShareableVcs": "பகிர்வதற்கு எந்த அட்டைகளும் கிடைக்கவில்லை.",
"sharingVc": "பகிர்கிறது அட்டை",
"bluetoothStateIos": "புளூடூத் முடக்கப்பட்டுள்ளது, கட்டுப்பாட்டு மையத்திலிருந்து அதை இயக்கவும்",
"bluetoothStateAndroid": "புளூடூத் முடக்கப்பட்டுள்ளது, விரைவு அமைப்புகள் மெனுவிலிருந்து அதை இயக்கவும்",

View File

@@ -18,6 +18,7 @@ const model = createModel(
isOnboarding: true,
isInitialDownload: true,
isTourGuide: false,
appInitialSetupDone: false,
},
{
events: {
@@ -123,11 +124,11 @@ export const authMachine = model.createMachine(
on: {
SETUP_PASSCODE: {
target: 'authorized',
actions: ['setPasscode', 'setLanguage', 'storeContext'],
},
actions: ['setPasscode', 'setLanguage', 'setAppSetupComplete', 'storeContext'],
},
SETUP_BIOMETRICS: {
target: 'authorized',
actions: ['setBiometrics', 'setLanguage', 'storeContext'],
actions: ['setBiometrics', 'setLanguage', 'setAppSetupComplete', 'storeContext'],
},
},
},
@@ -193,6 +194,10 @@ export const authMachine = model.createMachine(
selectLanguage: context => true,
}),
setAppSetupComplete: assign({
appInitialSetupDone: context => true,
}),
setPasscodeSalt: assign({
passcodeSalt: (context, event) => {
return event.data as string;
@@ -251,6 +256,10 @@ export function selectPasscode(state: State) {
return state?.context?.passcode;
}
export function selectAppSetupComplete(state: State) {
return state.context.appInitialSetupDone;
}
export function selectPasscodeSalt(state: State) {
return state.context.passcodeSalt;
}