@rick427/react-native-liveness 0.2.0 → 0.2.1
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/README.md +115 -32
- package/lib/module/LivenessCamera.js +160 -87
- package/lib/module/LivenessCamera.js.map +1 -1
- package/lib/module/LivenessDetector.js +27 -7
- package/lib/module/LivenessDetector.js.map +1 -1
- package/lib/module/useLivenessCamera.js +67 -12
- package/lib/module/useLivenessCamera.js.map +1 -1
- package/lib/typescript/src/LivenessCamera.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/LivenessCamera.tsx +93 -98
package/README.md
CHANGED
|
@@ -16,10 +16,13 @@ The library scores each camera frame against a set of liveness signals (face siz
|
|
|
16
16
|
|
|
17
17
|
- Real-time passive liveness detection (no gestures required)
|
|
18
18
|
- On-device ML — works fully offline (ML Kit)
|
|
19
|
-
-
|
|
20
|
-
-
|
|
19
|
+
- Circle guide with animated scanner — sweeping scan line, rotating corner brackets, confidence progress arc
|
|
20
|
+
- Score-driven border colour: white → yellow → green
|
|
21
|
+
- Built-in modal via `LivenessCameraModal` — one import, zero wiring
|
|
22
|
+
- Configurable animation type, close button style, and font
|
|
21
23
|
- Auto photo capture via Vision Camera's `takePhoto()`
|
|
22
|
-
-
|
|
24
|
+
- 60 fps preview, ML Kit capped at 20 fps via `runAtTargetFps`
|
|
25
|
+
- Optional shutter sound (respects silent mode)
|
|
23
26
|
- Fully typed TypeScript API
|
|
24
27
|
|
|
25
28
|
---
|
|
@@ -41,29 +44,30 @@ Install these if you don't already have them:
|
|
|
41
44
|
| `react-native-vision-camera` | `>= 4.0.0` |
|
|
42
45
|
| `react-native-svg` | `>= 13.0.0` |
|
|
43
46
|
| `react-native-worklets-core` | `>= 1.0.0` |
|
|
47
|
+
| `react-native-reanimated` | `>= 4.0.0` |
|
|
44
48
|
|
|
45
49
|
```sh
|
|
46
|
-
npm install react-native-vision-camera react-native-svg react-native-worklets-core
|
|
50
|
+
npm install react-native-vision-camera react-native-svg react-native-worklets-core react-native-reanimated
|
|
47
51
|
```
|
|
48
52
|
|
|
49
53
|
### Configure worklets Babel plugin
|
|
50
54
|
|
|
51
|
-
The library uses Vision Camera frame processors which run in a worklet context. Add the appropriate plugin to your `babel.config.js
|
|
55
|
+
The library uses Vision Camera frame processors which run in a worklet context. Add the appropriate plugin to your `babel.config.js`:
|
|
52
56
|
|
|
53
57
|
```js
|
|
54
58
|
// babel.config.js
|
|
55
59
|
module.exports = {
|
|
56
60
|
presets: ['module:@react-native/babel-preset'], // or 'babel-preset-expo'
|
|
57
61
|
plugins: [
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
'react-native-worklets-core/plugin', // frame processor worklets
|
|
63
|
+
'react-native-reanimated/plugin', // SVG animations (must come last)
|
|
60
64
|
],
|
|
61
65
|
};
|
|
62
66
|
```
|
|
63
67
|
|
|
64
|
-
> **Already have
|
|
68
|
+
> **Already have both plugins?** Just confirm both lines are present — order matters, Reanimated must come after worklets-core.
|
|
65
69
|
|
|
66
|
-
After updating
|
|
70
|
+
After updating Babel config, clear the Metro cache:
|
|
67
71
|
|
|
68
72
|
```sh
|
|
69
73
|
npx react-native start --reset-cache
|
|
@@ -86,22 +90,84 @@ Add `NSCameraUsageDescription` to your `Info.plist`:
|
|
|
86
90
|
|
|
87
91
|
### Android
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
ML Kit and all native dependencies are included automatically via `build.gradle`. No extra steps needed.
|
|
90
94
|
|
|
91
95
|
---
|
|
92
96
|
|
|
93
97
|
## Usage
|
|
94
98
|
|
|
95
|
-
|
|
99
|
+
There are two ways to use the library depending on how much control you need.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Option 1 — `LivenessCameraModal` (recommended)
|
|
104
|
+
|
|
105
|
+
The easiest integration. Pass `visible` / `onClose` and you're done — the modal, close button, and full-screen layout are all handled for you.
|
|
96
106
|
|
|
97
107
|
```tsx
|
|
98
|
-
import {
|
|
108
|
+
import { useState } from 'react';
|
|
109
|
+
import { LivenessCameraModal } from '@rick427/react-native-liveness';
|
|
99
110
|
import type { CaptureResult } from '@rick427/react-native-liveness';
|
|
100
111
|
|
|
101
112
|
export default function VerificationScreen() {
|
|
113
|
+
const [showLiveness, setShowLiveness] = useState(false);
|
|
114
|
+
|
|
102
115
|
const handleCapture = (result: CaptureResult) => {
|
|
103
116
|
console.log('Photo path:', result.photo.path);
|
|
104
117
|
console.log('Liveness score:', result.livenessScore); // 0.0 – 1.0
|
|
118
|
+
setShowLiveness(false);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<>
|
|
123
|
+
{/* Trigger however you like */}
|
|
124
|
+
<Button title="Verify Identity" onPress={() => setShowLiveness(true)} />
|
|
125
|
+
|
|
126
|
+
<LivenessCameraModal
|
|
127
|
+
visible={showLiveness}
|
|
128
|
+
onClose={() => setShowLiveness(false)}
|
|
129
|
+
onCapture={handleCapture}
|
|
130
|
+
onLivenessConfirmed={() => console.log('Live face confirmed!')}
|
|
131
|
+
onError={(err) => console.error(err)}
|
|
132
|
+
/>
|
|
133
|
+
</>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### `LivenessCameraModal` props
|
|
139
|
+
|
|
140
|
+
| Prop | Type | Default | Description |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| `visible` | `boolean` | **required** | Controls modal visibility. |
|
|
143
|
+
| `onClose` | `() => void` | **required** | Called when the × button is pressed or Android back is fired. |
|
|
144
|
+
| `onCapture` | `(result: CaptureResult) => void` | **required** | Fired after photo is captured. |
|
|
145
|
+
| `animationType` | `'slide' \| 'fade' \| 'none'` | `'slide'` | Modal entrance/exit animation. |
|
|
146
|
+
| `closeButtonStyle` | `ViewStyle` | — | Override the close button container style (position, size, colours). |
|
|
147
|
+
| `closeButtonIconColor` | `string` | `'#fff'` | Colour of the × icon. |
|
|
148
|
+
| `closeButtonIconSize` | `number` | `18` | Size of the × icon in dp. |
|
|
149
|
+
| `onLivenessConfirmed` | `() => void` | — | Fired the moment liveness is confirmed, before countdown. |
|
|
150
|
+
| `onError` | `(err: Error) => void` | — | Fired on unrecoverable errors. |
|
|
151
|
+
| `countdownFrom` | `number` | `3` | Countdown start value. |
|
|
152
|
+
| `livenessThreshold` | `number` | `0.75` | Score (0–1) required to confirm liveness. |
|
|
153
|
+
| `confirmFrames` | `number` | `10` | Consecutive high-score frames required (~500 ms at 20 fps). |
|
|
154
|
+
| `soundEnabled` | `boolean` | `true` | Play native shutter sound on capture. |
|
|
155
|
+
| `fontFamily` | `string` | `'Baloo-Medium'` | Font applied to all text inside the component. |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### Option 2 — `LivenessCamera` (embedded)
|
|
160
|
+
|
|
161
|
+
Use this when you want full layout control — embed the camera directly inside your own screen or custom modal.
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { LivenessCamera } from '@rick427/react-native-liveness';
|
|
165
|
+
import type { CaptureResult } from '@rick427/react-native-liveness';
|
|
166
|
+
|
|
167
|
+
export default function VerificationScreen() {
|
|
168
|
+
const handleCapture = (result: CaptureResult) => {
|
|
169
|
+
console.log('Photo path:', result.photo.path);
|
|
170
|
+
console.log('Liveness score:', result.livenessScore);
|
|
105
171
|
};
|
|
106
172
|
|
|
107
173
|
return (
|
|
@@ -115,20 +181,23 @@ export default function VerificationScreen() {
|
|
|
115
181
|
}
|
|
116
182
|
```
|
|
117
183
|
|
|
118
|
-
|
|
184
|
+
#### `LivenessCamera` props
|
|
119
185
|
|
|
120
186
|
| Prop | Type | Default | Description |
|
|
121
187
|
|---|---|---|---|
|
|
122
|
-
| `onCapture` | `(result: CaptureResult) => void` | **required** | Fired after photo is
|
|
123
|
-
| `onLivenessConfirmed` | `() => void` | — | Fired the moment liveness is confirmed, before
|
|
188
|
+
| `onCapture` | `(result: CaptureResult) => void` | **required** | Fired after photo is captured. |
|
|
189
|
+
| `onLivenessConfirmed` | `() => void` | — | Fired the moment liveness is confirmed, before countdown. |
|
|
124
190
|
| `onError` | `(err: Error) => void` | — | Fired on unrecoverable errors. |
|
|
125
191
|
| `countdownFrom` | `number` | `3` | Countdown start value. |
|
|
126
|
-
| `livenessThreshold` | `number` | `0.75` | Score (0–1) required
|
|
127
|
-
| `confirmFrames` | `number` | `
|
|
128
|
-
| `soundEnabled` | `boolean` | `true` | Play
|
|
192
|
+
| `livenessThreshold` | `number` | `0.75` | Score (0–1) required to confirm liveness. |
|
|
193
|
+
| `confirmFrames` | `number` | `10` | Consecutive high-score frames required (~500 ms at 20 fps). |
|
|
194
|
+
| `soundEnabled` | `boolean` | `true` | Play native shutter sound on capture. |
|
|
195
|
+
| `fontFamily` | `string` | `'Baloo-Medium'` | Font applied to all text inside the component. |
|
|
129
196
|
| `style` | `ViewStyle` | — | Style for the root container. |
|
|
130
197
|
|
|
131
|
-
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### `CaptureResult`
|
|
132
201
|
|
|
133
202
|
```ts
|
|
134
203
|
type CaptureResult = {
|
|
@@ -140,34 +209,48 @@ type CaptureResult = {
|
|
|
140
209
|
|
|
141
210
|
---
|
|
142
211
|
|
|
212
|
+
## Scanner animation
|
|
213
|
+
|
|
214
|
+
The circle guide layers three animations built entirely with `Animated` + `react-native-svg` — no extra dependencies.
|
|
215
|
+
|
|
216
|
+
| Layer | Behaviour |
|
|
217
|
+
|---|---|
|
|
218
|
+
| **Dim base ring** | Always visible; gives a positioning target before any progress starts. |
|
|
219
|
+
| **Sweep scan line** | A gradient bar ping-pongs top → bottom inside the circle (1.8 s/leg). Fades out on confirm. |
|
|
220
|
+
| **Rotating brackets** | Four corner arcs rotate slowly (1 rev / 6 s), suggesting the circle boundary during scanning. Freeze in place on confirm. |
|
|
221
|
+
| **Progress arc** | The circle border draws itself in clockwise from 12 o'clock as `livenessScore / livenessThreshold` builds. White → yellow → green. |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
143
225
|
## How liveness scoring works
|
|
144
226
|
|
|
145
|
-
Each camera frame is scored across four signals:
|
|
227
|
+
Each camera frame is scored across four signals at up to **20 fps** (ML Kit is throttled via `runAtTargetFps` while the preview renders at 60 fps):
|
|
146
228
|
|
|
147
229
|
| Signal | Weight | Detail |
|
|
148
230
|
|---|---|---|
|
|
149
|
-
| Face detected | 20% | ML Kit found a face in the frame |
|
|
150
|
-
| Face size | 20% | Face width is
|
|
151
|
-
| Head pose | 30% | Yaw < ±
|
|
152
|
-
| Eyes open | 30% | Average of left/right eye open probability from ML Kit |
|
|
231
|
+
| Face detected | 20% | ML Kit found a face in the frame. |
|
|
232
|
+
| Face size | 20% | Face width is 15–80% of the frame. Soft-edge scoring at boundaries. |
|
|
233
|
+
| Head pose | 30% | Yaw < ±25° and pitch < ±25° from frontal. Soft decay outside range. |
|
|
234
|
+
| Eyes open | 30% | Average of left/right eye open probability from ML Kit. |
|
|
153
235
|
|
|
154
|
-
A rolling window of the last 20 frame scores is maintained. Liveness is confirmed once `confirmFrames` consecutive frames all score above `livenessThreshold`.
|
|
236
|
+
A rolling window of the last 20 frame scores is maintained. Liveness is confirmed once `confirmFrames` consecutive frames all score above `livenessThreshold`. Bad frames **decay** the streak by 2 instead of resetting it, making detection resilient to momentary noise.
|
|
155
237
|
|
|
156
238
|
---
|
|
157
239
|
|
|
158
240
|
## Architecture
|
|
159
241
|
|
|
160
242
|
```
|
|
161
|
-
Camera
|
|
243
|
+
Camera (60 fps preview)
|
|
162
244
|
↓ [worklet thread — Vision Camera frame processor]
|
|
163
|
-
Native plugin (Swift / Kotlin)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
↓ [
|
|
245
|
+
runAtTargetFps(20) → Native plugin (Swift / Kotlin)
|
|
246
|
+
→ ML Kit Face Detection
|
|
247
|
+
→ { bounds, yawAngle, pitchAngle, leftEyeOpenProbability, … }
|
|
248
|
+
↓ [Worklets.createRunOnJS → JS thread, ~20×/sec]
|
|
167
249
|
useLivenessCamera hook
|
|
168
|
-
→ scoreFrame()
|
|
250
|
+
→ scoreFrame() — soft-edge signals, weighted sum
|
|
169
251
|
→ rolling 20-frame window
|
|
170
|
-
→
|
|
252
|
+
→ consecutiveGood++ on pass, decay -2 on fail
|
|
253
|
+
→ 10 consecutive frames > threshold → liveness confirmed
|
|
171
254
|
↓
|
|
172
255
|
Countdown 3 → 2 → 1 (React Native Animated)
|
|
173
256
|
↓
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { Animated
|
|
4
|
+
import { Animated as RNAnimated, StyleSheet, Text, View } from 'react-native';
|
|
5
|
+
import Animated, { cancelAnimation, Easing, useAnimatedProps, useSharedValue, withRepeat, withSequence, withTiming } from 'react-native-reanimated';
|
|
5
6
|
import { Camera, useCameraDevice, useCameraFormat, useCameraPermission } from 'react-native-vision-camera';
|
|
6
7
|
import { Circle, ClipPath, Defs, G, LinearGradient, Path, Rect, Stop, Svg } from 'react-native-svg';
|
|
7
8
|
import { useLivenessCamera } from "./useLivenessCamera.js";
|
|
8
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
-
// ─── Animated SVG components
|
|
10
|
-
//
|
|
10
|
+
// ─── Animated SVG components (Reanimated) ────────────────────────────────────
|
|
11
|
+
// createAnimatedComponent from react-native-reanimated properly drives SVG
|
|
12
|
+
// presentation attributes (strokeDashoffset, y, rotation) on the UI thread.
|
|
11
13
|
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
|
|
12
14
|
const AnimatedG = Animated.createAnimatedComponent(G);
|
|
13
15
|
const AnimatedRect = Animated.createAnimatedComponent(Rect);
|
|
@@ -61,6 +63,21 @@ function bracketArcPath(cx, cy, r, centerDeg, spanDeg) {
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
// ─── CircleOverlay ────────────────────────────────────────────────────────────
|
|
66
|
+
const _worklet_15111972513221_init_data = {
|
|
67
|
+
code: "function LivenessCameraTsx1(){const{cy,r,scanProgress,SCAN_LINE_HEIGHT,scanOpacity}=this.__closure;return{y:cy-r+2+scanProgress.value*(2*r-SCAN_LINE_HEIGHT-4),opacity:scanOpacity.value};}",
|
|
68
|
+
location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx",
|
|
69
|
+
sourceMap: "{\"version\":3,\"names\":[\"LivenessCameraTsx1\",\"cy\",\"r\",\"scanProgress\",\"SCAN_LINE_HEIGHT\",\"scanOpacity\",\"__closure\",\"y\",\"value\",\"opacity\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx\"],\"mappings\":\"AAmII,SAAAA,mBAAA,QAAAC,EAAA,CAAAC,CAAA,CAAAC,YAAA,CAAAC,gBAAA,CAAAC,WAAA,OAAAC,SAAA,OAAO,CAELC,CAAC,CAAEN,EAAE,CAAGC,CAAC,CAAG,CAAC,CAAGC,YAAY,CAACK,KAAK,EAAI,CAAC,CAAGN,CAAC,CAAGE,gBAAgB,CAAG,CAAC,CAAC,CACnEK,OAAO,CAAEJ,WAAW,CAACG,KACvB,CAAC\",\"ignoreList\":[]}"
|
|
70
|
+
};
|
|
71
|
+
const _worklet_14693916078586_init_data = {
|
|
72
|
+
code: "function LivenessCameraTsx2(){const{bracketRot,cx,cy}=this.__closure;return{rotation:bracketRot.value%360,originX:cx,originY:cy};}",
|
|
73
|
+
location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx",
|
|
74
|
+
sourceMap: "{\"version\":3,\"names\":[\"LivenessCameraTsx2\",\"bracketRot\",\"cx\",\"cy\",\"__closure\",\"rotation\",\"value\",\"originX\",\"originY\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx\"],\"mappings\":\"AA4II,SAAAA,mBAAA,QAAAC,UAAA,CAAAC,EAAA,CAAAC,EAAA,OAAAC,SAAA,OAAO,CAELC,QAAQ,CAAEJ,UAAU,CAACK,KAAK,CAAG,GAAG,CAChCC,OAAO,CAAEL,EAAE,CACXM,OAAO,CAAEL,EACX,CAAC\",\"ignoreList\":[]}"
|
|
75
|
+
};
|
|
76
|
+
const _worklet_1688522500078_init_data = {
|
|
77
|
+
code: "function LivenessCameraTsx3(){const{circumference,livenessProgress,livenessThreshold}=this.__closure;return{strokeDashoffset:circumference-livenessProgress.value/livenessThreshold*circumference};}",
|
|
78
|
+
location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx",
|
|
79
|
+
sourceMap: "{\"version\":3,\"names\":[\"LivenessCameraTsx3\",\"circumference\",\"livenessProgress\",\"livenessThreshold\",\"__closure\",\"strokeDashoffset\",\"value\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx\"],\"mappings\":\"AAsJI,SAAAA,mBAAA,QAAAC,aAAA,CAAAC,gBAAA,CAAAC,iBAAA,OAAAC,SAAA,OAAO,CACLC,gBAAgB,CACdJ,aAAa,CACZC,gBAAgB,CAACI,KAAK,CAAGH,iBAAiB,CAAIF,aACnD,CAAC\",\"ignoreList\":[]}"
|
|
80
|
+
};
|
|
64
81
|
function CircleOverlay({
|
|
65
82
|
width,
|
|
66
83
|
height,
|
|
@@ -68,99 +85,156 @@ function CircleOverlay({
|
|
|
68
85
|
score,
|
|
69
86
|
livenessThreshold
|
|
70
87
|
}) {
|
|
71
|
-
// ──
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
88
|
+
// ── Shared values — all hooks before any early return ─────────────────────
|
|
89
|
+
// scanProgress 0=top 1=bottom, ping-pongs continuously
|
|
90
|
+
const scanProgress = useSharedValue(0);
|
|
91
|
+
const scanOpacity = useSharedValue(1);
|
|
92
|
+
// bracketRot drives the slow bracket rotation in degrees
|
|
93
|
+
const bracketRot = useSharedValue(0);
|
|
94
|
+
// livenessProgress tracks smoothed score for the arc
|
|
95
|
+
const livenessProgress = useSharedValue(0);
|
|
96
|
+
|
|
97
|
+
// ── Geometry — computed before useAnimatedProps (safe when 0) ─────────────
|
|
98
|
+
const cx = width / 2;
|
|
99
|
+
const cy = height * 0.42;
|
|
100
|
+
const r = width * CIRCLE_DIAMETER_RATIO / 2;
|
|
101
|
+
const circumference = 2 * Math.PI * r;
|
|
102
|
+
const color = getCircleColor(state, score);
|
|
103
|
+
|
|
104
|
+
// ── Animated props — UI-thread worklets, deps rebuilt when geometry changes
|
|
105
|
+
const scanAnimProps = useAnimatedProps(function LivenessCameraTsx1Factory({
|
|
106
|
+
_worklet_15111972513221_init_data,
|
|
107
|
+
cy,
|
|
108
|
+
r,
|
|
109
|
+
scanProgress,
|
|
110
|
+
SCAN_LINE_HEIGHT,
|
|
111
|
+
scanOpacity
|
|
112
|
+
}) {
|
|
113
|
+
const _e = [new global.Error(), -6, -27];
|
|
114
|
+
const LivenessCameraTsx1 = () => ({
|
|
115
|
+
// Map 0→1 progress onto the pixel range inside the circle
|
|
116
|
+
y: cy - r + 2 + scanProgress.value * (2 * r - SCAN_LINE_HEIGHT - 4),
|
|
117
|
+
opacity: scanOpacity.value
|
|
118
|
+
});
|
|
119
|
+
LivenessCameraTsx1.__closure = {
|
|
120
|
+
cy,
|
|
121
|
+
r,
|
|
122
|
+
scanProgress,
|
|
123
|
+
SCAN_LINE_HEIGHT,
|
|
124
|
+
scanOpacity
|
|
125
|
+
};
|
|
126
|
+
LivenessCameraTsx1.__workletHash = 15111972513221;
|
|
127
|
+
LivenessCameraTsx1.__pluginVersion = "0.8.3";
|
|
128
|
+
LivenessCameraTsx1.__initData = _worklet_15111972513221_init_data;
|
|
129
|
+
LivenessCameraTsx1.__stackDetails = _e;
|
|
130
|
+
return LivenessCameraTsx1;
|
|
131
|
+
}({
|
|
132
|
+
_worklet_15111972513221_init_data,
|
|
133
|
+
cy,
|
|
134
|
+
r,
|
|
135
|
+
scanProgress,
|
|
136
|
+
SCAN_LINE_HEIGHT,
|
|
137
|
+
scanOpacity
|
|
138
|
+
}), [cy, r]);
|
|
139
|
+
const bracketAnimProps = useAnimatedProps(function LivenessCameraTsx2Factory({
|
|
140
|
+
_worklet_14693916078586_init_data,
|
|
141
|
+
bracketRot,
|
|
142
|
+
cx,
|
|
143
|
+
cy
|
|
144
|
+
}) {
|
|
145
|
+
const _e = [new global.Error(), -4, -27];
|
|
146
|
+
const LivenessCameraTsx2 = () => ({
|
|
147
|
+
// react-native-svg accepts numeric rotation + origin instead of a string
|
|
148
|
+
rotation: bracketRot.value % 360,
|
|
149
|
+
originX: cx,
|
|
150
|
+
originY: cy
|
|
151
|
+
});
|
|
152
|
+
LivenessCameraTsx2.__closure = {
|
|
153
|
+
bracketRot,
|
|
154
|
+
cx,
|
|
155
|
+
cy
|
|
156
|
+
};
|
|
157
|
+
LivenessCameraTsx2.__workletHash = 14693916078586;
|
|
158
|
+
LivenessCameraTsx2.__pluginVersion = "0.8.3";
|
|
159
|
+
LivenessCameraTsx2.__initData = _worklet_14693916078586_init_data;
|
|
160
|
+
LivenessCameraTsx2.__stackDetails = _e;
|
|
161
|
+
return LivenessCameraTsx2;
|
|
162
|
+
}({
|
|
163
|
+
_worklet_14693916078586_init_data,
|
|
164
|
+
bracketRot,
|
|
165
|
+
cx,
|
|
166
|
+
cy
|
|
167
|
+
}), [cx, cy]);
|
|
168
|
+
const progressAnimProps = useAnimatedProps(function LivenessCameraTsx3Factory({
|
|
169
|
+
_worklet_1688522500078_init_data,
|
|
170
|
+
circumference,
|
|
171
|
+
livenessProgress,
|
|
172
|
+
livenessThreshold
|
|
173
|
+
}) {
|
|
174
|
+
const _e = [new global.Error(), -4, -27];
|
|
175
|
+
const LivenessCameraTsx3 = () => ({
|
|
176
|
+
strokeDashoffset: circumference - livenessProgress.value / livenessThreshold * circumference
|
|
177
|
+
});
|
|
178
|
+
LivenessCameraTsx3.__closure = {
|
|
179
|
+
circumference,
|
|
180
|
+
livenessProgress,
|
|
181
|
+
livenessThreshold
|
|
182
|
+
};
|
|
183
|
+
LivenessCameraTsx3.__workletHash = 1688522500078;
|
|
184
|
+
LivenessCameraTsx3.__pluginVersion = "0.8.3";
|
|
185
|
+
LivenessCameraTsx3.__initData = _worklet_1688522500078_init_data;
|
|
186
|
+
LivenessCameraTsx3.__stackDetails = _e;
|
|
187
|
+
return LivenessCameraTsx3;
|
|
188
|
+
}({
|
|
189
|
+
_worklet_1688522500078_init_data,
|
|
190
|
+
circumference,
|
|
191
|
+
livenessProgress,
|
|
192
|
+
livenessThreshold
|
|
193
|
+
}), [circumference, livenessThreshold]);
|
|
78
194
|
|
|
79
195
|
// ── Start scan line + bracket rotation on mount ───────────────────────────
|
|
80
196
|
useEffect(() => {
|
|
81
|
-
|
|
82
|
-
scanLoopRef.current = Animated.loop(Animated.sequence([Animated.timing(scanAnim, {
|
|
83
|
-
toValue: 1,
|
|
197
|
+
scanProgress.value = withRepeat(withSequence(withTiming(1, {
|
|
84
198
|
duration: 1800,
|
|
85
|
-
easing: Easing.linear
|
|
86
|
-
|
|
87
|
-
}), Animated.timing(scanAnim, {
|
|
88
|
-
toValue: 0,
|
|
199
|
+
easing: Easing.linear
|
|
200
|
+
}), withTiming(0, {
|
|
89
201
|
duration: 1800,
|
|
90
|
-
easing: Easing.linear
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
scanLoopRef.current.start();
|
|
94
|
-
|
|
95
|
-
// Brackets: one full rotation every 6 s — slow, atmospheric
|
|
96
|
-
bracketLoopRef.current = Animated.loop(Animated.timing(bracketAnim, {
|
|
97
|
-
toValue: 360,
|
|
202
|
+
easing: Easing.linear
|
|
203
|
+
})), -1, false);
|
|
204
|
+
bracketRot.value = withRepeat(withTiming(360, {
|
|
98
205
|
duration: 6000,
|
|
99
|
-
easing: Easing.linear
|
|
100
|
-
|
|
101
|
-
}));
|
|
102
|
-
bracketLoopRef.current.start();
|
|
206
|
+
easing: Easing.linear
|
|
207
|
+
}), -1, false);
|
|
103
208
|
return () => {
|
|
104
|
-
|
|
105
|
-
|
|
209
|
+
cancelAnimation(scanProgress);
|
|
210
|
+
cancelAnimation(bracketRot);
|
|
106
211
|
};
|
|
107
212
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
108
213
|
|
|
109
|
-
// ── On confirmed:
|
|
214
|
+
// ── On liveness confirmed: freeze brackets, fade scan line out ────────────
|
|
110
215
|
useEffect(() => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
duration: 350,
|
|
118
|
-
useNativeDriver: false
|
|
119
|
-
}).start();
|
|
216
|
+
if (state !== 'scanning') {
|
|
217
|
+
cancelAnimation(scanProgress);
|
|
218
|
+
cancelAnimation(bracketRot);
|
|
219
|
+
scanOpacity.value = withTiming(0, {
|
|
220
|
+
duration: 350
|
|
221
|
+
});
|
|
120
222
|
}
|
|
121
|
-
}, [state
|
|
223
|
+
}, [state]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
122
224
|
|
|
123
225
|
// ── Drive progress arc from live score ────────────────────────────────────
|
|
124
226
|
useEffect(() => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}).start();
|
|
130
|
-
}, [score, livenessThreshold, progressAnim]);
|
|
227
|
+
livenessProgress.value = withTiming(Math.min(score, livenessThreshold), {
|
|
228
|
+
duration: 180
|
|
229
|
+
});
|
|
230
|
+
}, [score, livenessThreshold]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
131
231
|
|
|
132
232
|
// ── Guard — render nothing until dimensions are known ─────────────────────
|
|
133
233
|
if (width === 0 || height === 0) return null;
|
|
134
234
|
|
|
135
|
-
//
|
|
136
|
-
const cx = width / 2;
|
|
137
|
-
const cy = height * 0.42;
|
|
138
|
-
const r = width * CIRCLE_DIAMETER_RATIO / 2;
|
|
139
|
-
const circumference = 2 * Math.PI * r;
|
|
140
|
-
const color = getCircleColor(state, score);
|
|
141
|
-
|
|
142
|
-
// Scrim: full-screen dark rect with transparent circle hole
|
|
235
|
+
// Scrim: full-screen rect with transparent circle cutout (evenodd rule)
|
|
143
236
|
const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
|
|
144
237
|
|
|
145
|
-
// Scan line Y: sweeps from just inside top to just inside bottom of circle
|
|
146
|
-
const scanLineY = scanAnim.interpolate({
|
|
147
|
-
inputRange: [0, 1],
|
|
148
|
-
outputRange: [cy - r + 2, cy + r - SCAN_LINE_HEIGHT - 2]
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// Progress arc: strokeDashoffset goes from full (no arc) → 0 (full arc)
|
|
152
|
-
const strokeDashoffset = progressAnim.interpolate({
|
|
153
|
-
inputRange: [0, livenessThreshold],
|
|
154
|
-
outputRange: [circumference, 0],
|
|
155
|
-
extrapolate: 'clamp'
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// Bracket group rotation — centred on the circle
|
|
159
|
-
const bracketTransform = bracketAnim.interpolate({
|
|
160
|
-
inputRange: [0, 360],
|
|
161
|
-
outputRange: [`rotate(0, ${cx}, ${cy})`, `rotate(360, ${cx}, ${cy})`]
|
|
162
|
-
});
|
|
163
|
-
|
|
164
238
|
// 4 corner brackets at NE / SE / SW / NW diagonal positions
|
|
165
239
|
const bracketD = [45, 135, 225, 315].map(deg => bracketArcPath(cx, cy, r, deg, BRACKET_SPAN_DEG)).join(' ');
|
|
166
240
|
return /*#__PURE__*/_jsxs(Svg, {
|
|
@@ -214,14 +288,13 @@ function CircleOverlay({
|
|
|
214
288
|
clipPath: "url(#liveness-circle-clip)",
|
|
215
289
|
children: /*#__PURE__*/_jsx(AnimatedRect, {
|
|
216
290
|
x: cx - r,
|
|
217
|
-
y: scanLineY,
|
|
218
291
|
width: r * 2,
|
|
219
292
|
height: SCAN_LINE_HEIGHT,
|
|
220
293
|
fill: "url(#scan-gradient)",
|
|
221
|
-
|
|
294
|
+
animatedProps: scanAnimProps
|
|
222
295
|
})
|
|
223
296
|
}), /*#__PURE__*/_jsx(AnimatedG, {
|
|
224
|
-
|
|
297
|
+
animatedProps: bracketAnimProps,
|
|
225
298
|
children: /*#__PURE__*/_jsx(Path, {
|
|
226
299
|
d: bracketD,
|
|
227
300
|
fill: "none",
|
|
@@ -238,9 +311,9 @@ function CircleOverlay({
|
|
|
238
311
|
stroke: color,
|
|
239
312
|
strokeWidth: STROKE_WIDTH,
|
|
240
313
|
strokeDasharray: circumference,
|
|
241
|
-
strokeDashoffset: strokeDashoffset,
|
|
242
314
|
strokeLinecap: "round",
|
|
243
|
-
transform: `rotate(-90, ${cx}, ${cy})
|
|
315
|
+
transform: `rotate(-90, ${cx}, ${cy})`,
|
|
316
|
+
animatedProps: progressAnimProps
|
|
244
317
|
})]
|
|
245
318
|
});
|
|
246
319
|
}
|
|
@@ -250,26 +323,26 @@ function CountdownBubble({
|
|
|
250
323
|
value,
|
|
251
324
|
fontFamily
|
|
252
325
|
}) {
|
|
253
|
-
const scale = useRef(new
|
|
254
|
-
const opacity = useRef(new
|
|
326
|
+
const scale = useRef(new RNAnimated.Value(0)).current;
|
|
327
|
+
const opacity = useRef(new RNAnimated.Value(0)).current;
|
|
255
328
|
useEffect(() => {
|
|
256
|
-
|
|
329
|
+
RNAnimated.parallel([RNAnimated.sequence([RNAnimated.spring(scale, {
|
|
257
330
|
toValue: 1.2,
|
|
258
331
|
stiffness: 200,
|
|
259
332
|
damping: 6,
|
|
260
333
|
useNativeDriver: true
|
|
261
|
-
}),
|
|
334
|
+
}), RNAnimated.spring(scale, {
|
|
262
335
|
toValue: 1.0,
|
|
263
336
|
stiffness: 150,
|
|
264
337
|
damping: 8,
|
|
265
338
|
useNativeDriver: true
|
|
266
|
-
})]),
|
|
339
|
+
})]), RNAnimated.timing(opacity, {
|
|
267
340
|
toValue: 1,
|
|
268
341
|
duration: 150,
|
|
269
342
|
useNativeDriver: true
|
|
270
343
|
})]).start();
|
|
271
344
|
return () => {
|
|
272
|
-
|
|
345
|
+
RNAnimated.timing(opacity, {
|
|
273
346
|
toValue: 0,
|
|
274
347
|
duration: 200,
|
|
275
348
|
useNativeDriver: true
|
|
@@ -277,7 +350,7 @@ function CountdownBubble({
|
|
|
277
350
|
};
|
|
278
351
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
279
352
|
|
|
280
|
-
return /*#__PURE__*/_jsx(
|
|
353
|
+
return /*#__PURE__*/_jsx(RNAnimated.View, {
|
|
281
354
|
style: [styles.countdownBubble, {
|
|
282
355
|
opacity,
|
|
283
356
|
transform: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useEffect","useRef","useState","Animated","Easing","StyleSheet","Text","View","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","ClipPath","Defs","G","LinearGradient","Path","Rect","Stop","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","AnimatedCircle","createAnimatedComponent","AnimatedG","AnimatedRect","DEFAULT_FONT","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","SCAN_LINE_HEIGHT","BRACKET_SPAN_DEG","BRACKET_STROKE","getCircleColor","state","score","circlePath","cx","cy","r","join","bracketArcPath","centerDeg","spanDeg","toRad","d","Math","PI","a1","a2","x1","cos","y1","sin","x2","y2","CircleOverlay","width","height","livenessThreshold","scanAnim","Value","current","scanOpacity","progressAnim","bracketAnim","scanLoopRef","bracketLoopRef","loop","sequence","timing","toValue","duration","easing","linear","useNativeDriver","start","stop","isActive","min","circumference","color","scrimD","scanLineY","interpolate","inputRange","outputRange","strokeDashoffset","extrapolate","bracketTransform","bracketD","map","deg","style","absoluteFill","children","id","offset","stopColor","stopOpacity","fill","fillRule","stroke","strokeWidth","clipPath","x","y","opacity","transform","strokeLinecap","strokeDasharray","CountdownBubble","value","fontFamily","scale","parallel","spring","stiffness","damping","styles","countdownBubble","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","Error","root","centered","permissionText","onLayout","ref","photo","pixelFormat","feedbackContainer","feedbackText","countdownContainer","captureFlash","pointerEvents","create","flex","backgroundColor","overflow","justifyContent","alignItems","fontSize","textAlign","paddingHorizontal","position","bottom","left","right","textShadowColor","textShadowOffset","textShadowRadius","absoluteFillObject","borderRadius","borderWidth","borderColor","lineHeight"],"sourceRoot":"../../src","sources":["LivenessCamera.tsx"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useRef","useState","Animated","RNAnimated","StyleSheet","Text","View","cancelAnimation","Easing","useAnimatedProps","useSharedValue","withRepeat","withSequence","withTiming","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","ClipPath","Defs","G","LinearGradient","Path","Rect","Stop","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","AnimatedCircle","createAnimatedComponent","AnimatedG","AnimatedRect","DEFAULT_FONT","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","SCAN_LINE_HEIGHT","BRACKET_SPAN_DEG","BRACKET_STROKE","getCircleColor","state","score","circlePath","cx","cy","r","join","bracketArcPath","centerDeg","spanDeg","toRad","d","Math","PI","a1","a2","x1","cos","y1","sin","x2","y2","_worklet_15111972513221_init_data","code","location","sourceMap","_worklet_14693916078586_init_data","_worklet_1688522500078_init_data","CircleOverlay","width","height","livenessThreshold","scanProgress","scanOpacity","bracketRot","livenessProgress","circumference","color","scanAnimProps","LivenessCameraTsx1Factory","_e","global","Error","LivenessCameraTsx1","y","value","opacity","__closure","__workletHash","__pluginVersion","__initData","__stackDetails","bracketAnimProps","LivenessCameraTsx2Factory","LivenessCameraTsx2","rotation","originX","originY","progressAnimProps","LivenessCameraTsx3Factory","LivenessCameraTsx3","strokeDashoffset","duration","easing","linear","min","scrimD","bracketD","map","deg","style","absoluteFill","children","id","offset","stopColor","stopOpacity","fill","fillRule","stroke","strokeWidth","clipPath","x","animatedProps","strokeLinecap","strokeDasharray","transform","CountdownBubble","fontFamily","scale","Value","current","parallel","sequence","spring","toValue","stiffness","damping","useNativeDriver","timing","start","styles","countdownBubble","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","root","centered","permissionText","onLayout","ref","isActive","photo","pixelFormat","feedbackContainer","feedbackText","countdownContainer","captureFlash","pointerEvents","create","flex","backgroundColor","overflow","justifyContent","alignItems","fontSize","textAlign","paddingHorizontal","position","bottom","left","right","textShadowColor","textShadowOffset","textShadowRadius","absoluteFillObject","borderRadius","borderWidth","borderColor","lineHeight"],"sourceRoot":"../../src","sources":["LivenessCamera.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,19 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
import { useMemo } from 'react';
|
|
4
4
|
import { VisionCameraProxy } from 'react-native-vision-camera';
|
|
5
|
+
const _worklet_4012480599600_init_data = {
|
|
6
|
+
code: "function LivenessDetectorTs1(frame){const{plugin}=this.__closure;const result=plugin.call(frame);return result;}",
|
|
7
|
+
location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessDetector.ts",
|
|
8
|
+
sourceMap: "{\"version\":3,\"names\":[\"LivenessDetectorTs1\",\"frame\",\"plugin\",\"__closure\",\"result\",\"call\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessDetector.ts\"],\"mappings\":\"AAsBoB,QAAC,CAAAA,mBAAkCA,CAAAC,KAAA,QAAAC,MAAA,OAAAC,SAAA,CAEjD,KAAM,CAAAC,MAAM,CAAGF,MAAM,CAACG,IAAI,CAACJ,KAAK,CAAC,CAEjC,MAAO,CAAAG,MAAM,CACf\",\"ignoreList\":[]}"
|
|
9
|
+
};
|
|
5
10
|
function createPlugin() {
|
|
6
11
|
const plugin = VisionCameraProxy.initFrameProcessorPlugin('detectLiveness', {});
|
|
7
12
|
if (!plugin) {
|
|
8
13
|
throw new Error('[LivenessCamera] Frame Processor Plugin "detectLiveness" not found. ' + 'Make sure the native module is linked correctly.');
|
|
9
14
|
}
|
|
10
15
|
return {
|
|
11
|
-
detectLiveness:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
detectLiveness: function LivenessDetectorTs1Factory({
|
|
17
|
+
_worklet_4012480599600_init_data,
|
|
18
|
+
plugin
|
|
19
|
+
}) {
|
|
20
|
+
const _e = [new global.Error(), -2, -27];
|
|
21
|
+
const LivenessDetectorTs1 = function (frame) {
|
|
22
|
+
const result = plugin.call(frame);
|
|
23
|
+
// plugin.call returns a loosely-typed BasicParameterType — cast via unknown
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
LivenessDetectorTs1.__closure = {
|
|
27
|
+
plugin
|
|
28
|
+
};
|
|
29
|
+
LivenessDetectorTs1.__workletHash = 4012480599600;
|
|
30
|
+
LivenessDetectorTs1.__pluginVersion = "0.8.3";
|
|
31
|
+
LivenessDetectorTs1.__initData = _worklet_4012480599600_init_data;
|
|
32
|
+
LivenessDetectorTs1.__stackDetails = _e;
|
|
33
|
+
return LivenessDetectorTs1;
|
|
34
|
+
}({
|
|
35
|
+
_worklet_4012480599600_init_data,
|
|
36
|
+
plugin
|
|
37
|
+
})
|
|
18
38
|
};
|
|
19
39
|
}
|
|
20
40
|
export function useLivenessPlugin() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useMemo","VisionCameraProxy","createPlugin","plugin","initFrameProcessorPlugin","Error","detectLiveness","frame","result","call","useLivenessPlugin"],"sourceRoot":"../../src","sources":["LivenessDetector.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SAASC,iBAAiB,QAAoB,4BAA4B;
|
|
1
|
+
{"version":3,"names":["useMemo","VisionCameraProxy","_worklet_4012480599600_init_data","code","location","sourceMap","createPlugin","plugin","initFrameProcessorPlugin","Error","detectLiveness","LivenessDetectorTs1Factory","_e","global","LivenessDetectorTs1","frame","result","call","__closure","__workletHash","__pluginVersion","__initData","__stackDetails","useLivenessPlugin"],"sourceRoot":"../../src","sources":["LivenessDetector.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SAASC,iBAAiB,QAAoB,4BAA4B;AAAC,MAAAC,gCAAA;EAAAC,IAAA;EAAAC,QAAA;EAAAC,SAAA;AAAA;AAO3E,SAASC,YAAYA,CAAA,EAAmB;EACtC,MAAMC,MAAM,GAAGN,iBAAiB,CAACO,wBAAwB,CACvD,gBAAgB,EAChB,CAAC,CACH,CAAC;EAED,IAAI,CAACD,MAAM,EAAE;IACX,MAAM,IAAIE,KAAK,CACb,sEAAsE,GACpE,kDACJ,CAAC;EACH;EAEA,OAAO;IACLC,cAAc,EAAE,SAAAC,2BAAA;MAAAT,gCAAA;MAECK;IAAM;MAAA,MAAAK,EAAA,QAAAC,MAAA,CAAAJ,KAAA;MAAA,MAAAK,mBAAA,YAAAA,CAFNC,KAAY,EAAsB;QAEjD,MAAMC,MAAM,GAAGT,MAAM,CAACU,IAAI,CAACF,KAAK,CAAC;QACjC;QACA,OAAOC,MAAM;MACf,CAAC;MAAAF,mBAAA,CAAAI,SAAA;QAHgBX;MAAM;MAAAO,mBAAA,CAAAK,aAAA;MAAAL,mBAAA,CAAAM,eAAA;MAAAN,mBAAA,CAAAO,UAAA,GAAAnB,gCAAA;MAAAY,mBAAA,CAAAQ,cAAA,GAAAV,EAAA;MAAA,OAAAE,mBAAA;IAAA,CAFP;MAAAZ,gCAAA;MAECK;IAAM;EAIzB,CAAC;AACH;AAEA,OAAO,SAASgB,iBAAiBA,CAAA,EAAmB;EAClD,OAAOvB,OAAO,CAAC,MAAMM,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC;AAC1C","ignoreList":[]}
|
|
@@ -9,6 +9,16 @@ const WINDOW_SIZE = 20;
|
|
|
9
9
|
// How many frames to decay consecutiveGood by on a bad frame.
|
|
10
10
|
// Decay (not hard reset) means one noisy frame won't erase all progress.
|
|
11
11
|
const CONSECUTIVE_DECAY = 2;
|
|
12
|
+
const _worklet_11184642299290_init_data = {
|
|
13
|
+
code: "function useLivenessCameraTs1(){const{plugin,frame,handleFaceDataJS}=this.__closure;const face=plugin.detectLiveness(frame);handleFaceDataJS(face,frame.width);}",
|
|
14
|
+
location: "/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts",
|
|
15
|
+
sourceMap: "{\"version\":3,\"names\":[\"useLivenessCameraTs1\",\"plugin\",\"frame\",\"handleFaceDataJS\",\"__closure\",\"face\",\"detectLiveness\",\"width\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts\"],\"mappings\":\"AAuNyB,SAAAA,oBAAMA,CAAA,QAAAC,MAAA,CAAAC,KAAA,CAAAC,gBAAA,OAAAC,SAAA,CAEvB,KAAM,CAAAC,IAAI,CAAGJ,MAAM,CAACK,cAAc,CAACJ,KAAK,CAAC,CACzCC,gBAAgB,CAACE,IAAI,CAAEH,KAAK,CAACK,KAAK,CAAC,CACrC\",\"ignoreList\":[]}"
|
|
16
|
+
};
|
|
17
|
+
const _worklet_14471027507603_init_data = {
|
|
18
|
+
code: "function useLivenessCameraTs2(frame){const{runAtTargetFps,_worklet_11184642299290_init_data,plugin,handleFaceDataJS}=this.__closure;runAtTargetFps(20,function useLivenessCameraTs1Factory({_worklet_11184642299290_init_data:_worklet_11184642299290_init_data,plugin:plugin,frame:frame,handleFaceDataJS:handleFaceDataJS}){const _e=[new global.Error(),-4,-27];const useLivenessCameraTs1=function(){const face=plugin.detectLiveness(frame);handleFaceDataJS(face,frame.width);};useLivenessCameraTs1.__closure={plugin:plugin,frame:frame,handleFaceDataJS:handleFaceDataJS};useLivenessCameraTs1.__workletHash=11184642299290;useLivenessCameraTs1.__pluginVersion=\"0.8.3\";useLivenessCameraTs1.__initData=_worklet_11184642299290_init_data;useLivenessCameraTs1.__stackDetails=_e;return useLivenessCameraTs1;}({_worklet_11184642299290_init_data:_worklet_11184642299290_init_data,plugin:plugin,frame:frame,handleFaceDataJS:handleFaceDataJS}));}",
|
|
19
|
+
location: "/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts",
|
|
20
|
+
sourceMap: "{\"version\":3,\"names\":[\"useLivenessCameraTs2\",\"frame\",\"runAtTargetFps\",\"_worklet_11184642299290_init_data\",\"plugin\",\"handleFaceDataJS\",\"__closure\",\"useLivenessCameraTs1Factory\",\"_e\",\"global\",\"Error\",\"useLivenessCameraTs1\",\"face\",\"detectLiveness\",\"width\",\"__workletHash\",\"__pluginVersion\",\"__initData\",\"__stackDetails\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts\"],\"mappings\":\"AAmNI,QAAC,CAAAA,oBAAiBA,CAAAC,KAAA,QAAAC,cAAA,CAAAC,iCAAA,CAAAC,MAAA,CAAAC,gBAAA,OAAAC,SAAA,CAIhBJ,cAAc,CAAC,EAAE,CAAE,SAAAK,4BAAA,CAAAJ,iCAAA,CAAAA,iCAAA,CAEJC,MAAM,CAANA,MAAM,CAAgBH,KAAK,CAALA,KAAK,CACxCI,gBAAA,CAAAA,gBAAgB,SAAAG,EAAA,MAAAC,MAAA,CAAAC,KAAA,iBAAAC,oBAAA,SAAAA,CAAA,CAHO,CAEvB,KAAM,CAAAC,IAAI,CAAGR,MAAM,CAACS,cAAc,CAACZ,KAAK,CAAC,CACzCI,gBAAgB,CAACO,IAAI,CAAEX,KAAK,CAACa,KAAK,CAAC,CACrC,CAAC,CAAAH,oBAAA,CAAAL,SAAA,EAFcF,MAAM,CAANA,MAAM,CAAgBH,KAAK,CAALA,KAAK,CACxCI,gBAAA,CAAAA,gBAAgB,EAAAM,oBAAA,CAAAI,aAAA,gBAAAJ,oBAAA,CAAAK,eAAA,SAAAL,oBAAA,CAAAM,UAAA,CAAAd,iCAAA,CAAAQ,oBAAA,CAAAO,cAAA,CAAAV,EAAA,QAAAG,oBAAA,EAHC,EAAAR,iCAAA,CAAAA,iCAAA,CAEJC,MAAM,CAANA,MAAM,CAAgBH,KAAK,CAALA,KAAK,CACxCI,gBAAA,CAAAA,gBAAgB,EACjB,CAAC,CACJ\",\"ignoreList\":[]}"
|
|
21
|
+
};
|
|
12
22
|
export function useLivenessCamera(options) {
|
|
13
23
|
const {
|
|
14
24
|
livenessThreshold,
|
|
@@ -168,18 +178,63 @@ export function useLivenessCamera(options) {
|
|
|
168
178
|
// ─── Frame processor ──────────────────────────────────────────────────────
|
|
169
179
|
|
|
170
180
|
const handleFaceDataJS = useMemo(() => Worklets.createRunOnJS(handleFaceData), [handleFaceData]);
|
|
171
|
-
const frameProcessor = useFrameProcessor(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
const frameProcessor = useFrameProcessor(function useLivenessCameraTs2Factory({
|
|
182
|
+
_worklet_14471027507603_init_data,
|
|
183
|
+
runAtTargetFps,
|
|
184
|
+
_worklet_11184642299290_init_data,
|
|
185
|
+
plugin,
|
|
186
|
+
handleFaceDataJS
|
|
187
|
+
}) {
|
|
188
|
+
const _e = [new global.Error(), -5, -27];
|
|
189
|
+
const useLivenessCameraTs2 = function (frame) {
|
|
190
|
+
// Camera preview renders at full fps (60). ML Kit only needs ~20fps —
|
|
191
|
+
// running it on every frame would block the render thread unnecessarily.
|
|
192
|
+
runAtTargetFps(20, function useLivenessCameraTs1Factory({
|
|
193
|
+
_worklet_11184642299290_init_data,
|
|
194
|
+
plugin,
|
|
195
|
+
frame,
|
|
196
|
+
handleFaceDataJS
|
|
197
|
+
}) {
|
|
198
|
+
const _e = [new global.Error(), -4, -27];
|
|
199
|
+
const useLivenessCameraTs1 = function () {
|
|
200
|
+
const face = plugin.detectLiveness(frame);
|
|
201
|
+
handleFaceDataJS(face, frame.width);
|
|
202
|
+
};
|
|
203
|
+
useLivenessCameraTs1.__closure = {
|
|
204
|
+
plugin,
|
|
205
|
+
frame,
|
|
206
|
+
handleFaceDataJS
|
|
207
|
+
};
|
|
208
|
+
useLivenessCameraTs1.__workletHash = 11184642299290;
|
|
209
|
+
useLivenessCameraTs1.__pluginVersion = "0.8.3";
|
|
210
|
+
useLivenessCameraTs1.__initData = _worklet_11184642299290_init_data;
|
|
211
|
+
useLivenessCameraTs1.__stackDetails = _e;
|
|
212
|
+
return useLivenessCameraTs1;
|
|
213
|
+
}({
|
|
214
|
+
_worklet_11184642299290_init_data,
|
|
215
|
+
plugin,
|
|
216
|
+
frame,
|
|
217
|
+
handleFaceDataJS
|
|
218
|
+
}));
|
|
219
|
+
};
|
|
220
|
+
useLivenessCameraTs2.__closure = {
|
|
221
|
+
runAtTargetFps,
|
|
222
|
+
_worklet_11184642299290_init_data,
|
|
223
|
+
plugin,
|
|
224
|
+
handleFaceDataJS
|
|
225
|
+
};
|
|
226
|
+
useLivenessCameraTs2.__workletHash = 14471027507603;
|
|
227
|
+
useLivenessCameraTs2.__pluginVersion = "0.8.3";
|
|
228
|
+
useLivenessCameraTs2.__initData = _worklet_14471027507603_init_data;
|
|
229
|
+
useLivenessCameraTs2.__stackDetails = _e;
|
|
230
|
+
return useLivenessCameraTs2;
|
|
231
|
+
}({
|
|
232
|
+
_worklet_14471027507603_init_data,
|
|
233
|
+
runAtTargetFps,
|
|
234
|
+
_worklet_11184642299290_init_data,
|
|
235
|
+
plugin,
|
|
236
|
+
handleFaceDataJS
|
|
237
|
+
}), [plugin, handleFaceDataJS]);
|
|
183
238
|
useEffect(() => {
|
|
184
239
|
return () => {
|
|
185
240
|
frameScores.current = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","runAtTargetFps","useFrameProcessor","Worklets","useLivenessPlugin","getFeedback","rollingAverage","scoreFrame","WINDOW_SIZE","CONSECUTIVE_DECAY","useLivenessCamera","options","livenessThreshold","confirmFrames","countdownFrom","soundEnabled","cameraRef","onCapture","onLivenessConfirmed","onError","plugin","frameScores","consecutiveGood","frameWidth","stateRef","isCaptured","FEEDBACK_DEBOUNCE_MS","feedbackTimer","pendingFeedback","state","setState","livenessState","livenessScore","countdown","feedback","setLivenessState","next","current","prev","capture","photo","takePhoto","flash","enableShutterSound","score","timestamp","Date","now","err","Error","String","startCountdown","tick","interval","setInterval","clearInterval","handleFaceData","face","width","safeFace","detected","bounds","x","y","height","yawAngle","pitchAngle","rollAngle","leftEyeOpenProbability","rightEyeOpenProbability","smilingProbability","total","push","length","shift","avgScore","Math","max","isLive","newFeedback","clearTimeout","setTimeout","handleFaceDataJS","createRunOnJS","frameProcessor","frame","detectLiveness"],"sourceRoot":"../../src","sources":["useLivenessCamera.ts"],"mappings":";;AAAA,SAASA,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAEzE,SAASC,cAAc,EAAEC,iBAAiB,QAAQ,4BAA4B;AAC9E,SAASC,QAAQ,QAAQ,4BAA4B;AACrD,SAASC,iBAAiB,QAAQ,uBAAoB;AACtD,SAASC,WAAW,EAAEC,cAAc,EAAEC,UAAU,QAAQ,sBAAmB;AAQ3E,MAAMC,WAAW,GAAG,EAAE;AACtB;AACA;AACA,MAAMC,iBAAiB,GAAG,CAAC;
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","runAtTargetFps","useFrameProcessor","Worklets","useLivenessPlugin","getFeedback","rollingAverage","scoreFrame","WINDOW_SIZE","CONSECUTIVE_DECAY","_worklet_11184642299290_init_data","code","location","sourceMap","_worklet_14471027507603_init_data","useLivenessCamera","options","livenessThreshold","confirmFrames","countdownFrom","soundEnabled","cameraRef","onCapture","onLivenessConfirmed","onError","plugin","frameScores","consecutiveGood","frameWidth","stateRef","isCaptured","FEEDBACK_DEBOUNCE_MS","feedbackTimer","pendingFeedback","state","setState","livenessState","livenessScore","countdown","feedback","setLivenessState","next","current","prev","capture","photo","takePhoto","flash","enableShutterSound","score","timestamp","Date","now","err","Error","String","startCountdown","tick","interval","setInterval","clearInterval","handleFaceData","face","width","safeFace","detected","bounds","x","y","height","yawAngle","pitchAngle","rollAngle","leftEyeOpenProbability","rightEyeOpenProbability","smilingProbability","total","push","length","shift","avgScore","Math","max","isLive","newFeedback","clearTimeout","setTimeout","handleFaceDataJS","createRunOnJS","frameProcessor","useLivenessCameraTs2Factory","_e","global","useLivenessCameraTs2","frame","useLivenessCameraTs1Factory","useLivenessCameraTs1","detectLiveness","__closure","__workletHash","__pluginVersion","__initData","__stackDetails"],"sourceRoot":"../../src","sources":["useLivenessCamera.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AA8SlE,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,aAAiB,EACjB,iBAAwB,EACxB,aAAkB,EAClB,YAAmB,EACnB,UAAyB,EACzB,KAAK,GACN,EAAE,mBAAmB,2CA+FrB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rick427/react-native-liveness",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Liveness detection library for React Native using Vision Camera v4 and ML Kit",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -75,8 +75,10 @@
|
|
|
75
75
|
"react": "19.2.0",
|
|
76
76
|
"react-native": "0.83.6",
|
|
77
77
|
"react-native-builder-bob": "^0.41.0",
|
|
78
|
+
"react-native-reanimated": "^4.3.0",
|
|
78
79
|
"react-native-svg": "^15.0.0",
|
|
79
80
|
"react-native-vision-camera": "^4.0.0",
|
|
81
|
+
"react-native-worklets": "0.8.x",
|
|
80
82
|
"react-native-worklets-core": "^1.3.3",
|
|
81
83
|
"turbo": "^2.8.21",
|
|
82
84
|
"typescript": "^6.0.2"
|
|
@@ -84,6 +86,7 @@
|
|
|
84
86
|
"peerDependencies": {
|
|
85
87
|
"react": "*",
|
|
86
88
|
"react-native": "*",
|
|
89
|
+
"react-native-reanimated": ">=4.0.0",
|
|
87
90
|
"react-native-svg": ">=13.0.0",
|
|
88
91
|
"react-native-vision-camera": ">=4.0.0",
|
|
89
92
|
"react-native-worklets-core": ">=1.0.0"
|
|
@@ -99,7 +102,8 @@
|
|
|
99
102
|
[
|
|
100
103
|
"module",
|
|
101
104
|
{
|
|
102
|
-
"esm": true
|
|
105
|
+
"esm": true,
|
|
106
|
+
"configFile": true
|
|
103
107
|
}
|
|
104
108
|
],
|
|
105
109
|
[
|
package/src/LivenessCamera.tsx
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { Animated
|
|
2
|
+
import { Animated as RNAnimated, StyleSheet, Text, View } from 'react-native';
|
|
3
|
+
import Animated, {
|
|
4
|
+
cancelAnimation,
|
|
5
|
+
Easing,
|
|
6
|
+
useAnimatedProps,
|
|
7
|
+
useSharedValue,
|
|
8
|
+
withRepeat,
|
|
9
|
+
withSequence,
|
|
10
|
+
withTiming,
|
|
11
|
+
} from 'react-native-reanimated';
|
|
3
12
|
import {
|
|
4
13
|
Camera,
|
|
5
14
|
useCameraDevice,
|
|
@@ -20,8 +29,9 @@ import {
|
|
|
20
29
|
import { useLivenessCamera } from './useLivenessCamera';
|
|
21
30
|
import type { LivenessCameraProps, LivenessState } from './types';
|
|
22
31
|
|
|
23
|
-
// ─── Animated SVG components
|
|
24
|
-
//
|
|
32
|
+
// ─── Animated SVG components (Reanimated) ────────────────────────────────────
|
|
33
|
+
// createAnimatedComponent from react-native-reanimated properly drives SVG
|
|
34
|
+
// presentation attributes (strokeDashoffset, y, rotation) on the UI thread.
|
|
25
35
|
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
|
|
26
36
|
const AnimatedG = Animated.createAnimatedComponent(G);
|
|
27
37
|
const AnimatedRect = Animated.createAnimatedComponent(Rect);
|
|
@@ -101,108 +111,94 @@ function CircleOverlay({
|
|
|
101
111
|
score: number;
|
|
102
112
|
livenessThreshold: number;
|
|
103
113
|
}) {
|
|
104
|
-
// ──
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
|
|
114
|
+
// ── Shared values — all hooks before any early return ─────────────────────
|
|
115
|
+
// scanProgress 0=top 1=bottom, ping-pongs continuously
|
|
116
|
+
const scanProgress = useSharedValue(0);
|
|
117
|
+
const scanOpacity = useSharedValue(1);
|
|
118
|
+
// bracketRot drives the slow bracket rotation in degrees
|
|
119
|
+
const bracketRot = useSharedValue(0);
|
|
120
|
+
// livenessProgress tracks smoothed score for the arc
|
|
121
|
+
const livenessProgress = useSharedValue(0);
|
|
122
|
+
|
|
123
|
+
// ── Geometry — computed before useAnimatedProps (safe when 0) ─────────────
|
|
124
|
+
const cx = width / 2;
|
|
125
|
+
const cy = height * 0.42;
|
|
126
|
+
const r = (width * CIRCLE_DIAMETER_RATIO) / 2;
|
|
127
|
+
const circumference = 2 * Math.PI * r;
|
|
128
|
+
const color = getCircleColor(state, score);
|
|
129
|
+
|
|
130
|
+
// ── Animated props — UI-thread worklets, deps rebuilt when geometry changes
|
|
131
|
+
const scanAnimProps = useAnimatedProps(
|
|
132
|
+
() => ({
|
|
133
|
+
// Map 0→1 progress onto the pixel range inside the circle
|
|
134
|
+
y: cy - r + 2 + scanProgress.value * (2 * r - SCAN_LINE_HEIGHT - 4),
|
|
135
|
+
opacity: scanOpacity.value,
|
|
136
|
+
}),
|
|
137
|
+
[cy, r]
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const bracketAnimProps = useAnimatedProps(
|
|
141
|
+
() => ({
|
|
142
|
+
// react-native-svg accepts numeric rotation + origin instead of a string
|
|
143
|
+
rotation: bracketRot.value % 360,
|
|
144
|
+
originX: cx,
|
|
145
|
+
originY: cy,
|
|
146
|
+
}),
|
|
147
|
+
[cx, cy]
|
|
148
|
+
);
|
|
109
149
|
|
|
110
|
-
const
|
|
111
|
-
|
|
150
|
+
const progressAnimProps = useAnimatedProps(
|
|
151
|
+
() => ({
|
|
152
|
+
strokeDashoffset:
|
|
153
|
+
circumference -
|
|
154
|
+
(livenessProgress.value / livenessThreshold) * circumference,
|
|
155
|
+
}),
|
|
156
|
+
[circumference, livenessThreshold]
|
|
157
|
+
);
|
|
112
158
|
|
|
113
159
|
// ── Start scan line + bracket rotation on mount ───────────────────────────
|
|
114
160
|
useEffect(() => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
useNativeDriver: false,
|
|
123
|
-
}),
|
|
124
|
-
Animated.timing(scanAnim, {
|
|
125
|
-
toValue: 0,
|
|
126
|
-
duration: 1800,
|
|
127
|
-
easing: Easing.linear,
|
|
128
|
-
useNativeDriver: false,
|
|
129
|
-
}),
|
|
130
|
-
])
|
|
161
|
+
scanProgress.value = withRepeat(
|
|
162
|
+
withSequence(
|
|
163
|
+
withTiming(1, { duration: 1800, easing: Easing.linear }),
|
|
164
|
+
withTiming(0, { duration: 1800, easing: Easing.linear })
|
|
165
|
+
),
|
|
166
|
+
-1,
|
|
167
|
+
false
|
|
131
168
|
);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
Animated.timing(bracketAnim, {
|
|
137
|
-
toValue: 360,
|
|
138
|
-
duration: 6000,
|
|
139
|
-
easing: Easing.linear,
|
|
140
|
-
useNativeDriver: false,
|
|
141
|
-
})
|
|
169
|
+
bracketRot.value = withRepeat(
|
|
170
|
+
withTiming(360, { duration: 6000, easing: Easing.linear }),
|
|
171
|
+
-1,
|
|
172
|
+
false
|
|
142
173
|
);
|
|
143
|
-
bracketLoopRef.current.start();
|
|
144
|
-
|
|
145
174
|
return () => {
|
|
146
|
-
|
|
147
|
-
|
|
175
|
+
cancelAnimation(scanProgress);
|
|
176
|
+
cancelAnimation(bracketRot);
|
|
148
177
|
};
|
|
149
178
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
150
179
|
|
|
151
|
-
// ── On confirmed:
|
|
180
|
+
// ── On liveness confirmed: freeze brackets, fade scan line out ────────────
|
|
152
181
|
useEffect(() => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
Animated.timing(scanOpacity, {
|
|
158
|
-
toValue: 0,
|
|
159
|
-
duration: 350,
|
|
160
|
-
useNativeDriver: false,
|
|
161
|
-
}).start();
|
|
182
|
+
if (state !== 'scanning') {
|
|
183
|
+
cancelAnimation(scanProgress);
|
|
184
|
+
cancelAnimation(bracketRot);
|
|
185
|
+
scanOpacity.value = withTiming(0, { duration: 350 });
|
|
162
186
|
}
|
|
163
|
-
}, [state
|
|
187
|
+
}, [state]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
164
188
|
|
|
165
189
|
// ── Drive progress arc from live score ────────────────────────────────────
|
|
166
190
|
useEffect(() => {
|
|
167
|
-
|
|
168
|
-
toValue: Math.min(score, livenessThreshold),
|
|
191
|
+
livenessProgress.value = withTiming(Math.min(score, livenessThreshold), {
|
|
169
192
|
duration: 180,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}, [score, livenessThreshold, progressAnim]);
|
|
193
|
+
});
|
|
194
|
+
}, [score, livenessThreshold]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
173
195
|
|
|
174
196
|
// ── Guard — render nothing until dimensions are known ─────────────────────
|
|
175
197
|
if (width === 0 || height === 0) return null;
|
|
176
198
|
|
|
177
|
-
//
|
|
178
|
-
const cx = width / 2;
|
|
179
|
-
const cy = height * 0.42;
|
|
180
|
-
const r = (width * CIRCLE_DIAMETER_RATIO) / 2;
|
|
181
|
-
const circumference = 2 * Math.PI * r;
|
|
182
|
-
const color = getCircleColor(state, score);
|
|
183
|
-
|
|
184
|
-
// Scrim: full-screen dark rect with transparent circle hole
|
|
199
|
+
// Scrim: full-screen rect with transparent circle cutout (evenodd rule)
|
|
185
200
|
const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
|
|
186
201
|
|
|
187
|
-
// Scan line Y: sweeps from just inside top to just inside bottom of circle
|
|
188
|
-
const scanLineY = scanAnim.interpolate({
|
|
189
|
-
inputRange: [0, 1],
|
|
190
|
-
outputRange: [cy - r + 2, cy + r - SCAN_LINE_HEIGHT - 2],
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
// Progress arc: strokeDashoffset goes from full (no arc) → 0 (full arc)
|
|
194
|
-
const strokeDashoffset = progressAnim.interpolate({
|
|
195
|
-
inputRange: [0, livenessThreshold],
|
|
196
|
-
outputRange: [circumference, 0],
|
|
197
|
-
extrapolate: 'clamp',
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// Bracket group rotation — centred on the circle
|
|
201
|
-
const bracketTransform = bracketAnim.interpolate({
|
|
202
|
-
inputRange: [0, 360],
|
|
203
|
-
outputRange: [`rotate(0, ${cx}, ${cy})`, `rotate(360, ${cx}, ${cy})`],
|
|
204
|
-
});
|
|
205
|
-
|
|
206
202
|
// 4 corner brackets at NE / SE / SW / NW diagonal positions
|
|
207
203
|
const bracketD = [45, 135, 225, 315]
|
|
208
204
|
.map((deg) => bracketArcPath(cx, cy, r, deg, BRACKET_SPAN_DEG))
|
|
@@ -243,16 +239,15 @@ function CircleOverlay({
|
|
|
243
239
|
<G clipPath="url(#liveness-circle-clip)">
|
|
244
240
|
<AnimatedRect
|
|
245
241
|
x={cx - r}
|
|
246
|
-
y={scanLineY}
|
|
247
242
|
width={r * 2}
|
|
248
243
|
height={SCAN_LINE_HEIGHT}
|
|
249
244
|
fill="url(#scan-gradient)"
|
|
250
|
-
|
|
245
|
+
animatedProps={scanAnimProps}
|
|
251
246
|
/>
|
|
252
247
|
</G>
|
|
253
248
|
|
|
254
249
|
{/* ── Rotating corner brackets ─────────────────────────────────────── */}
|
|
255
|
-
<AnimatedG
|
|
250
|
+
<AnimatedG animatedProps={bracketAnimProps}>
|
|
256
251
|
<Path
|
|
257
252
|
d={bracketD}
|
|
258
253
|
fill="none"
|
|
@@ -264,7 +259,7 @@ function CircleOverlay({
|
|
|
264
259
|
</AnimatedG>
|
|
265
260
|
|
|
266
261
|
{/* ── Progress arc — draws in as liveness confidence builds ────────── */}
|
|
267
|
-
{/*
|
|
262
|
+
{/* transform rotates -90° so arc starts at 12 o'clock, goes clockwise */}
|
|
268
263
|
<AnimatedCircle
|
|
269
264
|
cx={cx}
|
|
270
265
|
cy={cy}
|
|
@@ -273,9 +268,9 @@ function CircleOverlay({
|
|
|
273
268
|
stroke={color}
|
|
274
269
|
strokeWidth={STROKE_WIDTH}
|
|
275
270
|
strokeDasharray={circumference}
|
|
276
|
-
strokeDashoffset={strokeDashoffset}
|
|
277
271
|
strokeLinecap="round"
|
|
278
272
|
transform={`rotate(-90, ${cx}, ${cy})`}
|
|
273
|
+
animatedProps={progressAnimProps}
|
|
279
274
|
/>
|
|
280
275
|
</Svg>
|
|
281
276
|
);
|
|
@@ -289,26 +284,26 @@ function CountdownBubble({
|
|
|
289
284
|
value: number;
|
|
290
285
|
fontFamily: string;
|
|
291
286
|
}) {
|
|
292
|
-
const scale = useRef(new
|
|
293
|
-
const opacity = useRef(new
|
|
287
|
+
const scale = useRef(new RNAnimated.Value(0)).current;
|
|
288
|
+
const opacity = useRef(new RNAnimated.Value(0)).current;
|
|
294
289
|
|
|
295
290
|
useEffect(() => {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
291
|
+
RNAnimated.parallel([
|
|
292
|
+
RNAnimated.sequence([
|
|
293
|
+
RNAnimated.spring(scale, {
|
|
299
294
|
toValue: 1.2,
|
|
300
295
|
stiffness: 200,
|
|
301
296
|
damping: 6,
|
|
302
297
|
useNativeDriver: true,
|
|
303
298
|
}),
|
|
304
|
-
|
|
299
|
+
RNAnimated.spring(scale, {
|
|
305
300
|
toValue: 1.0,
|
|
306
301
|
stiffness: 150,
|
|
307
302
|
damping: 8,
|
|
308
303
|
useNativeDriver: true,
|
|
309
304
|
}),
|
|
310
305
|
]),
|
|
311
|
-
|
|
306
|
+
RNAnimated.timing(opacity, {
|
|
312
307
|
toValue: 1,
|
|
313
308
|
duration: 150,
|
|
314
309
|
useNativeDriver: true,
|
|
@@ -316,7 +311,7 @@ function CountdownBubble({
|
|
|
316
311
|
]).start();
|
|
317
312
|
|
|
318
313
|
return () => {
|
|
319
|
-
|
|
314
|
+
RNAnimated.timing(opacity, {
|
|
320
315
|
toValue: 0,
|
|
321
316
|
duration: 200,
|
|
322
317
|
useNativeDriver: true,
|
|
@@ -325,11 +320,11 @@ function CountdownBubble({
|
|
|
325
320
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
326
321
|
|
|
327
322
|
return (
|
|
328
|
-
<
|
|
323
|
+
<RNAnimated.View
|
|
329
324
|
style={[styles.countdownBubble, { opacity, transform: [{ scale }] }]}
|
|
330
325
|
>
|
|
331
326
|
<Text style={[styles.countdownText, { fontFamily }]}>{value}</Text>
|
|
332
|
-
</
|
|
327
|
+
</RNAnimated.View>
|
|
333
328
|
);
|
|
334
329
|
}
|
|
335
330
|
|