@trustchex/react-native-sdk 1.464.0 → 1.475.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +3 -3
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +190 -12
- package/ios/Camera/TrustchexCameraView.swift +244 -46
- package/ios/Permission/PermissionModule.m +22 -0
- package/ios/Permission/PermissionModule.swift +67 -0
- package/lib/module/Screens/Debug/MRZTestScreen.js +121 -147
- package/lib/module/Screens/Dynamic/LivenessDetectionScreen.js +24 -3
- package/lib/module/Screens/Dynamic/VerbalConsentScreen.js +1 -1
- package/lib/module/Screens/Dynamic/VideoCallScreen.js +7 -12
- package/lib/module/Screens/Static/ResultScreen.js +9 -1
- package/lib/module/Shared/Components/EIDScanner.js +166 -163
- package/lib/module/Shared/Components/FaceCamera.js +14 -8
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +45 -10
- package/lib/module/Shared/Libs/MRZ_KNOWN_ISSUES.md +112 -0
- package/lib/module/Shared/Libs/PERMISSIONS_MANAGER.md +268 -0
- package/lib/module/Shared/Libs/index.js +20 -0
- package/lib/module/Shared/Libs/mrz.utils.js +570 -16
- package/lib/module/Shared/Libs/mrzFrameAggregator.js +301 -0
- package/lib/module/Shared/Libs/mrzOcrIntegration.js +109 -0
- package/lib/module/Shared/Libs/permissions.utils.js +199 -0
- package/lib/module/Translation/Resources/en.js +1 -0
- package/lib/module/Translation/Resources/tr.js +1 -0
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Screens/Debug/MRZTestScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/LivenessDetectionScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Dynamic/VideoCallScreen.d.ts.map +1 -1
- package/lib/typescript/src/Screens/Static/ResultScreen.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/EIDScanner.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/index.d.ts +20 -0
- package/lib/typescript/src/Shared/Libs/index.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts +8 -0
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/mrzFrameAggregator.d.ts +76 -0
- package/lib/typescript/src/Shared/Libs/mrzFrameAggregator.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/mrzOcrIntegration.d.ts +73 -0
- package/lib/typescript/src/Shared/Libs/mrzOcrIntegration.d.ts.map +1 -0
- package/lib/typescript/src/Shared/Libs/permissions.utils.d.ts +58 -0
- package/lib/typescript/src/Shared/Libs/permissions.utils.d.ts.map +1 -0
- package/lib/typescript/src/Translation/Resources/en.d.ts +1 -0
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +1 -0
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +14 -10
- package/src/Screens/Debug/MRZTestScreen.tsx +137 -166
- package/src/Screens/Dynamic/LivenessDetectionScreen.tsx +45 -5
- package/src/Screens/Dynamic/VerbalConsentScreen.tsx +1 -1
- package/src/Screens/Dynamic/VideoCallScreen.tsx +8 -19
- package/src/Screens/Static/ResultScreen.tsx +18 -9
- package/src/Shared/Components/EIDScanner.tsx +210 -160
- package/src/Shared/Components/FaceCamera.tsx +19 -16
- package/src/Shared/Components/IdentityDocumentCamera.tsx +53 -13
- package/src/Shared/Libs/MRZ_KNOWN_ISSUES.md +112 -0
- package/src/Shared/Libs/PERMISSIONS_MANAGER.md +268 -0
- package/src/Shared/Libs/index.ts +63 -0
- package/src/Shared/Libs/mrz.utils.ts +639 -11
- package/src/Shared/Libs/mrzFrameAggregator.ts +370 -0
- package/src/Shared/Libs/mrzOcrIntegration.ts +175 -0
- package/src/Shared/Libs/permissions.utils.ts +251 -0
- package/src/Translation/Resources/en.ts +1 -0
- package/src/Translation/Resources/tr.ts +1 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# MRZ Reading & Correction — Known Issues & Limitations
|
|
2
|
+
|
|
3
|
+
This documents the **inherent limitations** and **deliberate trade-offs** of the
|
|
4
|
+
MRZ camera scanner (`mrz.utils.ts`, `mrzFrameAggregator.ts`, and the native
|
|
5
|
+
`TrustchexCameraView` scan-frame OCR). These are not bugs — they are constraints
|
|
6
|
+
of the ICAO 9303 standard and OCR, and the design decisions made around them.
|
|
7
|
+
|
|
8
|
+
For the camera/OCR pipeline overview, see the doc comments in
|
|
9
|
+
`mrzFrameAggregator.ts` and `mrz.utils.ts`.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Check-digit MOD-10 collisions: `1↔L` and `6↔G` are indistinguishable
|
|
14
|
+
|
|
15
|
+
**Issue.** ICAO's 7-3-1 check digit weights letters by value (`A`=10 … `Z`=35),
|
|
16
|
+
then takes the result mod 10. Some OCR look-alikes are **mod-10 equal** to the
|
|
17
|
+
digit they resemble:
|
|
18
|
+
|
|
19
|
+
| Look-alike | Letter value | Digit | mod 10 |
|
|
20
|
+
| --- | --- | --- | --- |
|
|
21
|
+
| `L` ↔ `1` | 21 | 1 | both ≡ **1** |
|
|
22
|
+
| `G` ↔ `6` | 16 | 6 | both ≡ **6** |
|
|
23
|
+
|
|
24
|
+
So a document number read as `SPECL2345` produces the **exact same check digit**
|
|
25
|
+
as the correct `SPEC12345`. The MRZ **validates either way** — the check digit
|
|
26
|
+
cannot tell them apart.
|
|
27
|
+
|
|
28
|
+
**Impact.** If OCR reads a `1` as `L` (or `6` as `G`) in a *numeric* position of a
|
|
29
|
+
field that also accepts letters (e.g. an alphanumeric document number), the MRZ
|
|
30
|
+
will validate but may carry the letter form.
|
|
31
|
+
|
|
32
|
+
**Mitigation.**
|
|
33
|
+
|
|
34
|
+
- **Multi-frame voting** (`mrzFrameAggregator`) usually resolves it: across frames
|
|
35
|
+
the correct glyph wins the per-character vote.
|
|
36
|
+
- **NFC chip read (eID)** is authoritative — when available it overrides the
|
|
37
|
+
camera reading.
|
|
38
|
+
- Other digit↔letter confusions (`0↔O/Q/D`, `2↔Z`, `5↔S`, `8↔B`, `4↔A`, `1↔I`) are
|
|
39
|
+
**not** mod-10 collisions and *are* recovered to the correct digit.
|
|
40
|
+
|
|
41
|
+
Covered by `mrz.ambiguous.test.ts` ("documents the … MOD-10 collision").
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 2. Unprotected fields (TD1 optional / national-ID) can't be self-corrected
|
|
46
|
+
|
|
47
|
+
**Issue.** TD1's optional-data field (which on Turkish IDs holds the 11-digit
|
|
48
|
+
national ID / TC number) has **no per-field check digit** — it is only covered by
|
|
49
|
+
the composite check digit. If OCR corrupts the optional field **and** the
|
|
50
|
+
composite digit is also dropped/misread (common on glossy cards), there is no
|
|
51
|
+
independent anchor to detect the error.
|
|
52
|
+
|
|
53
|
+
**Mitigation.** High-confidence numeric normalisation (`B→8`, `S→5`, `O→0`, …) is
|
|
54
|
+
applied to the all-digit optional field, and **multi-frame voting** is the
|
|
55
|
+
primary safeguard. A single noisy frame is not trusted; the consensus is.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 3. Filler-letter normalisation is conservative in name fields (by design)
|
|
60
|
+
|
|
61
|
+
**Issue.** The `<` filler is frequently OCR'd as a letter (`K`, and under glare
|
|
62
|
+
`C`/`E`/`G`). We normalise these back to `<` **only** in structurally
|
|
63
|
+
unambiguous positions — the trailing filler run, the TD1 issuing-state field, and
|
|
64
|
+
the document-code filler.
|
|
65
|
+
|
|
66
|
+
**Deliberate trade-off.** A `K`/`C`/`E`/`G` **inside the name field** is *not*
|
|
67
|
+
normalised, because it cannot be distinguished from a real name letter (surnames
|
|
68
|
+
like `AKTAS`, `KAYA`, `CETIN`, or a 2-letter `AK` start with these). Corrupting a
|
|
69
|
+
real name is worse than a cosmetic filler glyph, so:
|
|
70
|
+
|
|
71
|
+
- Names are **preserved verbatim** — `AKTAS` stays `AKTAS`.
|
|
72
|
+
- A genuine filler misread *in the middle of a name region* may remain as a
|
|
73
|
+
letter (cosmetic only; the name field has no check digit, so validity is
|
|
74
|
+
unaffected, and the document number / dates — the identity-critical fields —
|
|
75
|
+
are always cleaned).
|
|
76
|
+
|
|
77
|
+
Covered by the "real letters in names are not eaten" tests in `mrz.utils.test.ts`.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 4. OCR throughput / image-quality dependence
|
|
82
|
+
|
|
83
|
+
- **Resolution.** ML Kit needs ~16 px per character. A full-frame capture leaves a
|
|
84
|
+
30–44-char MRZ line below that floor, so the native pipeline **crops to the
|
|
85
|
+
on-screen scan frame and upscales + grayscale/contrast-enhances** before OCR.
|
|
86
|
+
The MRZ band must be reasonably filled within the on-screen guide.
|
|
87
|
+
- **Glare / lamination.** Heavy glare on a glossy laminated card still degrades
|
|
88
|
+
OCR; the enhancement helps but does not eliminate it. Steadying the card and
|
|
89
|
+
reducing direct glare improves convergence.
|
|
90
|
+
- **Throughput.** OCR runs at a few frames/sec; the JS handler is throttled
|
|
91
|
+
(~400 ms) and the recovery search is time-bounded so the UI stays responsive.
|
|
92
|
+
A pathological/garbage frame fails fast (recovery budget) rather than blocking.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 5. Structurally broken frames are (correctly) rejected
|
|
97
|
+
|
|
98
|
+
Truncated or wrong-length line-sets that cannot be repaired by ambiguous-char
|
|
99
|
+
swaps or ±1 indel are reported **invalid** — the flow will not advance on a
|
|
100
|
+
guess. This is intentional: a wrong-but-plausible reconstruction must never leak
|
|
101
|
+
through. Multi-frame scanning accumulates until a check-digit-valid consensus is
|
|
102
|
+
reached.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 6. Platform parity
|
|
107
|
+
|
|
108
|
+
The scan-frame ROI crop + grayscale/contrast enhancement exists on **both Android
|
|
109
|
+
(Kotlin) and iOS (Swift / Core Image)**. The JS recovery, voting, and field
|
|
110
|
+
mapping are shared, so behaviour is consistent across platforms. Debug builds
|
|
111
|
+
require Metro to be reachable; build a **Release** variant for untethered device
|
|
112
|
+
testing.
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# PermissionManager Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`PermissionManager` is a centralized utility for handling all platform-specific permission requests (camera, microphone, NFC, etc.) in the React Native SDK. It abstracts away platform differences (iOS vs Android) and provides a clean, consistent API.
|
|
6
|
+
|
|
7
|
+
## Location
|
|
8
|
+
|
|
9
|
+
- **File**: `src/Shared/Libs/permissions.utils.ts`
|
|
10
|
+
- **Export**: Can be imported from `src/Shared/Libs/index.ts`
|
|
11
|
+
|
|
12
|
+
## Supported Permissions
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
type PermissionType = 'camera' | 'microphone' | 'nfc';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Permission | iOS | Android | Notes |
|
|
19
|
+
| ------------ | --- | ------- | ---------------------------------------- |
|
|
20
|
+
| `camera` | ✅ | ✅ | Camera access for video recording |
|
|
21
|
+
| `microphone` | ✅ | ✅ | Microphone access for audio recording |
|
|
22
|
+
| `nfc` | ✅ | ✅ | NFC chip reading (document verification) |
|
|
23
|
+
|
|
24
|
+
## API Reference
|
|
25
|
+
|
|
26
|
+
### Request Methods
|
|
27
|
+
|
|
28
|
+
#### `requestPermission(permission: PermissionType): Promise<boolean>`
|
|
29
|
+
|
|
30
|
+
Request a single permission. Returns `true` if granted, `false` if denied.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import PermissionManager from '../../Shared/Libs/permissions.utils';
|
|
34
|
+
|
|
35
|
+
const hasCamera = await PermissionManager.requestPermission('camera');
|
|
36
|
+
if (!hasCamera) {
|
|
37
|
+
console.log('Camera permission denied');
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
#### `requestPermissions(permissions: PermissionType[]): Promise<Map<PermissionType, boolean>>`
|
|
42
|
+
|
|
43
|
+
Request multiple permissions at once. Returns a Map with permission status for each.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const results = await PermissionManager.requestPermissions([
|
|
47
|
+
'camera',
|
|
48
|
+
'microphone',
|
|
49
|
+
]);
|
|
50
|
+
const hasCamera = results.get('camera') ?? false;
|
|
51
|
+
const hasMicrophone = results.get('microphone') ?? false;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### `requestCameraAndMicrophone(): Promise<boolean>`
|
|
55
|
+
|
|
56
|
+
**⭐ Convenience method** — Request camera and microphone together (common for video recording). Returns `true` only if BOTH are granted.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const hasBothPermissions = await PermissionManager.requestCameraAndMicrophone();
|
|
60
|
+
if (!hasBothPermissions) {
|
|
61
|
+
showError('Camera and microphone access required for video call');
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### `requestCamera(): Promise<boolean>`
|
|
66
|
+
|
|
67
|
+
Request camera permission only.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const hasCamera = await PermissionManager.requestCamera();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### `requestMicrophone(): Promise<boolean>`
|
|
74
|
+
|
|
75
|
+
Request microphone permission only.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
const hasMicrophone = await PermissionManager.requestMicrophone();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### `requestNFC(): Promise<boolean>`
|
|
82
|
+
|
|
83
|
+
Request NFC permission for document verification.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
const hasNFC = await PermissionManager.requestNFC();
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### `requestWithFallback(permission: PermissionType, onDenied?: () => void): Promise<boolean>`
|
|
90
|
+
|
|
91
|
+
Request permission with custom callback when denied.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const granted = await PermissionManager.requestWithFallback('camera', () => {
|
|
95
|
+
showAlert('Camera access is required for verification');
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Check Methods (Non-requesting)
|
|
100
|
+
|
|
101
|
+
Check if a permission is already granted without requesting.
|
|
102
|
+
|
|
103
|
+
#### `checkPermission(permission: PermissionType): Promise<boolean>`
|
|
104
|
+
|
|
105
|
+
Check a single permission status.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const hasCamera = await PermissionManager.checkPermission('camera');
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### `hasCameraAndMicrophone(): Promise<boolean>`
|
|
112
|
+
|
|
113
|
+
Check if both camera and microphone are granted.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const ready = await PermissionManager.hasCameraAndMicrophone();
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### `hasCamera(): Promise<boolean>`
|
|
120
|
+
|
|
121
|
+
Check if camera is granted.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const hasCamera = await PermissionManager.hasCamera();
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### `hasMicrophone(): Promise<boolean>`
|
|
128
|
+
|
|
129
|
+
Check if microphone is granted.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const hasMicrophone = await PermissionManager.hasMicrophone();
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### `hasNFC(): Promise<boolean>`
|
|
136
|
+
|
|
137
|
+
Check if NFC is granted.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
const hasNFC = await PermissionManager.hasNFC();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Common Patterns
|
|
144
|
+
|
|
145
|
+
### Pattern 1: Video Call Setup (Camera + Microphone)
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import PermissionManager from '../../Shared/Libs/permissions.utils';
|
|
149
|
+
|
|
150
|
+
async function initializeVideoCall() {
|
|
151
|
+
const hasBothPermissions =
|
|
152
|
+
await PermissionManager.requestCameraAndMicrophone();
|
|
153
|
+
|
|
154
|
+
if (!hasBothPermissions) {
|
|
155
|
+
setConnectionState('permissions_denied');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Proceed with video call initialization
|
|
160
|
+
const stream = await service.initialize();
|
|
161
|
+
setLocalStream(stream);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Pattern 2: Document Verification (NFC)
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const hasNFC = await PermissionManager.requestNFC();
|
|
169
|
+
|
|
170
|
+
if (!hasNFC) {
|
|
171
|
+
showError('NFC access required to read document');
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const result = await readNFCChip();
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Pattern 3: Check Before Requesting
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// First check if permission is already granted
|
|
182
|
+
const alreadyHasCamera = await PermissionManager.checkPermission('camera');
|
|
183
|
+
|
|
184
|
+
if (alreadyHasCamera) {
|
|
185
|
+
// Skip request dialog
|
|
186
|
+
startCamera();
|
|
187
|
+
} else {
|
|
188
|
+
// Request permission (shows OS dialog)
|
|
189
|
+
const granted = await PermissionManager.requestCamera();
|
|
190
|
+
if (granted) {
|
|
191
|
+
startCamera();
|
|
192
|
+
} else {
|
|
193
|
+
showErrorMessage('Camera access required');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Platform Implementation Details
|
|
199
|
+
|
|
200
|
+
### iOS
|
|
201
|
+
|
|
202
|
+
Uses the `react-native-permissions` library with `RNPermissions` module.
|
|
203
|
+
|
|
204
|
+
**Permissions layout location**: `ios/App.xcodeproj/Info.plist`
|
|
205
|
+
|
|
206
|
+
Required Info.plist keys:
|
|
207
|
+
|
|
208
|
+
- `NSCameraUsageDescription` — Camera access explanation
|
|
209
|
+
- `NSMicrophoneUsageDescription` — Microphone access explanation
|
|
210
|
+
- `NFCReaderUsageDescription` — NFC access explanation
|
|
211
|
+
|
|
212
|
+
### Android
|
|
213
|
+
|
|
214
|
+
Uses built-in `PermissionsAndroid` from React Native core.
|
|
215
|
+
|
|
216
|
+
**Permissions manifest location**: `android/app/src/main/AndroidManifest.xml`
|
|
217
|
+
|
|
218
|
+
Required manifest permissions:
|
|
219
|
+
|
|
220
|
+
- `android.permission.CAMERA` — Camera access
|
|
221
|
+
- `android.permission.RECORD_AUDIO` — Microphone access
|
|
222
|
+
- `android.permission.NFC` — NFC chip reading
|
|
223
|
+
|
|
224
|
+
## Error Handling
|
|
225
|
+
|
|
226
|
+
The PermissionManager handles errors internally and logs them using the debug utility. All methods return clear boolean or Map results so you can check status directly:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
const granted = await PermissionManager.requestCamera();
|
|
230
|
+
|
|
231
|
+
// Simple check
|
|
232
|
+
if (!granted) {
|
|
233
|
+
// Handle permission denied
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Best Practices
|
|
238
|
+
|
|
239
|
+
1. ✅ **Use convenience methods** — `requestCameraAndMicrophone()` instead of manually requesting both
|
|
240
|
+
2. ✅ **Request at the right time** — Request permissions when the feature is about to be used
|
|
241
|
+
3. ✅ **Check before requesting** — Use `checkPermission()` if you want to skip the OS dialog
|
|
242
|
+
4. ✅ **Handle denial gracefully** — Always provide clear error messages when permissions are denied
|
|
243
|
+
5. ✅ **Use the centralized manager** — Never import React Native permissions directly; always use PermissionManager
|
|
244
|
+
|
|
245
|
+
## Troubleshooting
|
|
246
|
+
|
|
247
|
+
### Permission request dialog not appearing
|
|
248
|
+
|
|
249
|
+
- Check that you're using `request*` methods, not `check*` methods
|
|
250
|
+
- Verify the permission is in the app's manifest (Android) or Info.plist (iOS)
|
|
251
|
+
- Test on a device where the permission hasn't been granted yet
|
|
252
|
+
|
|
253
|
+
### Camera/Microphone not working after permission granted
|
|
254
|
+
|
|
255
|
+
- Check that you're handling successful permission grant and initializing the feature
|
|
256
|
+
- Verify other features aren't holding exclusive access to the device
|
|
257
|
+
|
|
258
|
+
### NFC not working on iOS
|
|
259
|
+
|
|
260
|
+
- Ensure `NFCReaderUsageDescription` is set in Info.plist
|
|
261
|
+
- The app must be signed with proper entitlements for NFC
|
|
262
|
+
- NFC requires iPhone XS or later
|
|
263
|
+
|
|
264
|
+
## Related Files
|
|
265
|
+
|
|
266
|
+
- `src/Screens/Dynamic/VideoCallScreen.tsx` — Example usage with video calls
|
|
267
|
+
- `src/Shared/Libs/index.ts` — Exported for easy importing
|
|
268
|
+
- `src/Shared/Libs/debug.utils.ts` — Used internally for debug logging
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Export utility modules with validated symbols only.
|
|
2
|
+
export { default as PermissionManager } from './permissions.utils';
|
|
3
|
+
export type { PermissionType } from './permissions.utils';
|
|
4
|
+
export { SignalingClient } from './SignalingClient';
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
setDebugMode,
|
|
8
|
+
setLogLevel,
|
|
9
|
+
isDebugEnabled,
|
|
10
|
+
getLogLevel,
|
|
11
|
+
traceLog,
|
|
12
|
+
debugLog,
|
|
13
|
+
infoLog,
|
|
14
|
+
debugWarn,
|
|
15
|
+
debugError,
|
|
16
|
+
logError,
|
|
17
|
+
logWarn,
|
|
18
|
+
} from './debug.utils';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
default as HTTPClient,
|
|
22
|
+
HttpClientError,
|
|
23
|
+
UnauthorizedError,
|
|
24
|
+
ForbiddenError,
|
|
25
|
+
NotFoundError,
|
|
26
|
+
BadRequestError,
|
|
27
|
+
TooManyRequestsError,
|
|
28
|
+
InternalServerError,
|
|
29
|
+
} from './http-client';
|
|
30
|
+
|
|
31
|
+
export * from './analytics.utils';
|
|
32
|
+
export type { Rect } from './contains';
|
|
33
|
+
export { getLocalizedCountryName } from './country-display.utils';
|
|
34
|
+
export { getSessionKey, encryptWithAes, decryptWithAes } from './crypto.utils';
|
|
35
|
+
export { default as debounce } from './debounce.utils';
|
|
36
|
+
export { handleDeepLink } from './deeplink.utils';
|
|
37
|
+
export { getSimulatedDemoData, isDemoSession } from './demo.utils';
|
|
38
|
+
export { default as MRZUtils } from './mrz.utils';
|
|
39
|
+
export { NativeDeviceInfo } from './native-device-info.utils';
|
|
40
|
+
export { default as getDeviceInfo } from './native-device-info.utils';
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
useKeepAwake,
|
|
44
|
+
enableKeepAwake,
|
|
45
|
+
disableKeepAwake,
|
|
46
|
+
isKeepAwakeCurrentlyActive,
|
|
47
|
+
getKeepAwakeStats,
|
|
48
|
+
} from './native-keep-awake.utils';
|
|
49
|
+
|
|
50
|
+
export { runWithRetry } from './promise.utils';
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
configureStatusBarForWhiteBackground,
|
|
54
|
+
useStatusBarWhiteBackground,
|
|
55
|
+
} from './status-bar.utils';
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
speak,
|
|
59
|
+
speakWithDebounce,
|
|
60
|
+
stopSpeaking,
|
|
61
|
+
resetLastMessage,
|
|
62
|
+
initializeTTS,
|
|
63
|
+
} from './tts.utils';
|