react-native-debug-toolkit 3.2.3 → 3.2.4
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/src/main/java/com/reactnativedebugtoolkit/DebugToolkitDevConnectModule.java +43 -8
- package/ios/DebugToolkitDevConnect.mm +54 -1
- package/lib/commonjs/core/initialize.js +15 -3
- package/lib/commonjs/core/initialize.js.map +1 -1
- package/lib/commonjs/features/devConnect/DevConnectTab.js +30 -47
- package/lib/commonjs/features/devConnect/DevConnectTab.js.map +1 -1
- package/lib/commonjs/features/devConnect/devConnectUtils.js +8 -0
- package/lib/commonjs/features/devConnect/devConnectUtils.js.map +1 -1
- package/lib/commonjs/features/devConnect/index.js +22 -3
- package/lib/commonjs/features/devConnect/index.js.map +1 -1
- package/lib/commonjs/features/devConnect/nativeDevConnect.js +26 -0
- package/lib/commonjs/features/devConnect/nativeDevConnect.js.map +1 -1
- package/lib/commonjs/ui/DebugView.js +10 -2
- package/lib/commonjs/ui/DebugView.js.map +1 -1
- package/lib/commonjs/utils/DaemonClient.js +5 -0
- package/lib/commonjs/utils/DaemonClient.js.map +1 -1
- package/lib/module/core/initialize.js +16 -4
- package/lib/module/core/initialize.js.map +1 -1
- package/lib/module/features/devConnect/DevConnectTab.js +30 -47
- package/lib/module/features/devConnect/DevConnectTab.js.map +1 -1
- package/lib/module/features/devConnect/devConnectUtils.js +7 -0
- package/lib/module/features/devConnect/devConnectUtils.js.map +1 -1
- package/lib/module/features/devConnect/index.js +19 -5
- package/lib/module/features/devConnect/index.js.map +1 -1
- package/lib/module/features/devConnect/nativeDevConnect.js +24 -0
- package/lib/module/features/devConnect/nativeDevConnect.js.map +1 -1
- package/lib/module/ui/DebugView.js +11 -3
- package/lib/module/ui/DebugView.js.map +1 -1
- package/lib/module/utils/DaemonClient.js +5 -0
- package/lib/module/utils/DaemonClient.js.map +1 -1
- package/lib/typescript/src/core/initialize.d.ts +4 -2
- package/lib/typescript/src/core/initialize.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/DevConnectTab.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts +1 -0
- package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/index.d.ts +1 -0
- package/lib/typescript/src/features/devConnect/index.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts +2 -0
- package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts.map +1 -1
- package/lib/typescript/src/features/devConnect/types.d.ts +1 -1
- package/lib/typescript/src/features/devConnect/types.d.ts.map +1 -1
- package/lib/typescript/src/ui/DebugView.d.ts.map +1 -1
- package/lib/typescript/src/utils/DaemonClient.d.ts +2 -0
- package/lib/typescript/src/utils/DaemonClient.d.ts.map +1 -1
- package/package.json +2 -10
- package/src/core/initialize.ts +17 -5
- package/src/features/devConnect/DevConnectTab.tsx +18 -34
- package/src/features/devConnect/devConnectUtils.ts +8 -0
- package/src/features/devConnect/index.ts +18 -5
- package/src/features/devConnect/nativeDevConnect.ts +28 -0
- package/src/features/devConnect/types.ts +1 -1
- package/src/ui/DebugView.tsx +12 -3
- package/src/utils/DaemonClient.ts +7 -0
- package/lib/commonjs/features/devConnect/DevConnectQrScanner.js +0 -248
- package/lib/commonjs/features/devConnect/DevConnectQrScanner.js.map +0 -1
- package/lib/commonjs/features/devConnect/cameraKit.js +0 -54
- package/lib/commonjs/features/devConnect/cameraKit.js.map +0 -1
- package/lib/module/features/devConnect/DevConnectQrScanner.js +0 -243
- package/lib/module/features/devConnect/DevConnectQrScanner.js.map +0 -1
- package/lib/module/features/devConnect/cameraKit.js +0 -49
- package/lib/module/features/devConnect/cameraKit.js.map +0 -1
- package/lib/typescript/src/features/devConnect/DevConnectQrScanner.d.ts +0 -10
- package/lib/typescript/src/features/devConnect/DevConnectQrScanner.d.ts.map +0 -1
- package/lib/typescript/src/features/devConnect/cameraKit.d.ts +0 -47
- package/lib/typescript/src/features/devConnect/cameraKit.d.ts.map +0 -1
- package/src/features/devConnect/DevConnectQrScanner.tsx +0 -214
- package/src/features/devConnect/cameraKit.ts +0 -93
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React, { Component, useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
5
|
-
import { Colors } from '../../ui/theme/colors';
|
|
6
|
-
import { getScannerModule } from './cameraKit';
|
|
7
|
-
import { parseMetroQrPayload } from './devConnectUtils';
|
|
8
|
-
|
|
9
|
-
// ─── Camera Error Boundary ─────────────────────────────────
|
|
10
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
class CameraErrorBoundary extends Component {
|
|
12
|
-
state = {
|
|
13
|
-
hasError: false
|
|
14
|
-
};
|
|
15
|
-
static getDerivedStateFromError() {
|
|
16
|
-
return {
|
|
17
|
-
hasError: true
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
componentDidCatch(error) {
|
|
21
|
-
console.warn('[DevConnect] Camera error:', error.message);
|
|
22
|
-
this.props.onCameraError(error.message || 'Camera failed to initialize.');
|
|
23
|
-
}
|
|
24
|
-
render() {
|
|
25
|
-
if (this.state.hasError) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
return this.props.children;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// ─── QR Scanner ─────────────────────────────────────────────
|
|
33
|
-
|
|
34
|
-
export function DevConnectQrScanner({
|
|
35
|
-
visible,
|
|
36
|
-
onClose,
|
|
37
|
-
onScanTarget
|
|
38
|
-
}) {
|
|
39
|
-
const scannedRef = useRef(false);
|
|
40
|
-
const [error, setError] = useState(null);
|
|
41
|
-
const [cameraFailed, setCameraFailed] = useState(false);
|
|
42
|
-
const scanner = getScannerModule();
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
if (visible) {
|
|
45
|
-
scannedRef.current = false;
|
|
46
|
-
setError(null);
|
|
47
|
-
setCameraFailed(false);
|
|
48
|
-
}
|
|
49
|
-
}, [visible]);
|
|
50
|
-
const handleScanned = useCallback(rawValue => {
|
|
51
|
-
if (scannedRef.current) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
if (typeof rawValue !== 'string') {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const parsed = parseMetroQrPayload(rawValue);
|
|
58
|
-
if (!parsed) {
|
|
59
|
-
setError('QR code does not contain a supported Metro URL.');
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
scannedRef.current = true;
|
|
63
|
-
setError(null);
|
|
64
|
-
onScanTarget({
|
|
65
|
-
computerHost: parsed.computerHost,
|
|
66
|
-
metroPort: parsed.metroPort
|
|
67
|
-
});
|
|
68
|
-
onClose();
|
|
69
|
-
}, [onClose, onScanTarget]);
|
|
70
|
-
const handleCameraKitRead = useCallback(event => {
|
|
71
|
-
handleScanned(event.nativeEvent?.codeStringValue ?? '');
|
|
72
|
-
}, [handleScanned]);
|
|
73
|
-
const handleExpoScanned = useCallback(result => {
|
|
74
|
-
handleScanned(result.value ?? '');
|
|
75
|
-
}, [handleScanned]);
|
|
76
|
-
const handleCameraError = useCallback(_msg => {
|
|
77
|
-
setCameraFailed(true);
|
|
78
|
-
}, []);
|
|
79
|
-
if (!visible || !scanner) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
return /*#__PURE__*/_jsx(Modal, {
|
|
83
|
-
visible: visible,
|
|
84
|
-
animationType: "slide",
|
|
85
|
-
presentationStyle: "fullScreen",
|
|
86
|
-
onRequestClose: onClose,
|
|
87
|
-
children: /*#__PURE__*/_jsxs(View, {
|
|
88
|
-
style: styles.container,
|
|
89
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
90
|
-
style: styles.previewLayer,
|
|
91
|
-
children: [!cameraFailed && /*#__PURE__*/_jsx(CameraErrorBoundary, {
|
|
92
|
-
onCameraError: handleCameraError,
|
|
93
|
-
children: scanner.kind === 'camera-kit' && scanner.CameraKit ? /*#__PURE__*/_jsx(scanner.CameraKit.Camera, {
|
|
94
|
-
style: styles.camera,
|
|
95
|
-
cameraType: scanner.CameraKit.CameraType?.Back,
|
|
96
|
-
scanBarcode: true,
|
|
97
|
-
onReadCode: handleCameraKitRead,
|
|
98
|
-
showFrame: true,
|
|
99
|
-
laserColor: Colors.primary,
|
|
100
|
-
frameColor: Colors.primary,
|
|
101
|
-
allowedBarcodeTypes: ['qr']
|
|
102
|
-
}) : scanner.kind === 'expo-camera' && scanner.ExpoCamera ? /*#__PURE__*/_jsx(scanner.ExpoCamera.Camera, {
|
|
103
|
-
style: styles.camera,
|
|
104
|
-
onBarCodeScanned: handleExpoScanned,
|
|
105
|
-
barCodeScannerSettings: {
|
|
106
|
-
barCodeTypes: ['qr']
|
|
107
|
-
}
|
|
108
|
-
}) : null
|
|
109
|
-
}), cameraFailed && /*#__PURE__*/_jsxs(View, {
|
|
110
|
-
style: styles.cameraFallback,
|
|
111
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
112
|
-
style: styles.cameraFallbackText,
|
|
113
|
-
children: "Camera unavailable."
|
|
114
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
115
|
-
style: styles.cameraFallbackHint,
|
|
116
|
-
children: "Please enter computer IP manually."
|
|
117
|
-
})]
|
|
118
|
-
})]
|
|
119
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
120
|
-
style: styles.topBar,
|
|
121
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
122
|
-
style: styles.titleGroup,
|
|
123
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
124
|
-
style: styles.title,
|
|
125
|
-
children: "Scan Metro QR"
|
|
126
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
127
|
-
style: styles.subtitle,
|
|
128
|
-
children: "Expo or Metro URL"
|
|
129
|
-
})]
|
|
130
|
-
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
131
|
-
style: styles.closeButton,
|
|
132
|
-
onPress: onClose,
|
|
133
|
-
activeOpacity: 0.75,
|
|
134
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
135
|
-
style: styles.closeButtonText,
|
|
136
|
-
children: "Close"
|
|
137
|
-
})
|
|
138
|
-
})]
|
|
139
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
140
|
-
style: [styles.statusPill, error && styles.statusPillError],
|
|
141
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
142
|
-
style: [styles.statusText, error && styles.statusTextError],
|
|
143
|
-
children: error ?? 'Point the camera at exp:// or http:// Metro URL.'
|
|
144
|
-
})
|
|
145
|
-
})]
|
|
146
|
-
})
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
const styles = StyleSheet.create({
|
|
150
|
-
container: {
|
|
151
|
-
flex: 1,
|
|
152
|
-
backgroundColor: '#000'
|
|
153
|
-
},
|
|
154
|
-
previewLayer: {
|
|
155
|
-
...StyleSheet.absoluteFillObject
|
|
156
|
-
},
|
|
157
|
-
camera: {
|
|
158
|
-
...StyleSheet.absoluteFillObject
|
|
159
|
-
},
|
|
160
|
-
cameraFallback: {
|
|
161
|
-
...StyleSheet.absoluteFillObject,
|
|
162
|
-
justifyContent: 'center',
|
|
163
|
-
alignItems: 'center',
|
|
164
|
-
padding: 24
|
|
165
|
-
},
|
|
166
|
-
cameraFallbackText: {
|
|
167
|
-
fontSize: 16,
|
|
168
|
-
color: '#fff',
|
|
169
|
-
fontWeight: '600',
|
|
170
|
-
marginBottom: 8
|
|
171
|
-
},
|
|
172
|
-
cameraFallbackHint: {
|
|
173
|
-
fontSize: 13,
|
|
174
|
-
color: 'rgba(255,255,255,0.6)',
|
|
175
|
-
textAlign: 'center'
|
|
176
|
-
},
|
|
177
|
-
topBar: {
|
|
178
|
-
position: 'absolute',
|
|
179
|
-
top: 44,
|
|
180
|
-
left: 16,
|
|
181
|
-
right: 16,
|
|
182
|
-
flexDirection: 'row',
|
|
183
|
-
alignItems: 'center',
|
|
184
|
-
justifyContent: 'space-between',
|
|
185
|
-
paddingLeft: 14,
|
|
186
|
-
paddingRight: 8,
|
|
187
|
-
paddingVertical: 8,
|
|
188
|
-
borderRadius: 12,
|
|
189
|
-
backgroundColor: 'rgba(0,0,0,0.62)'
|
|
190
|
-
},
|
|
191
|
-
titleGroup: {
|
|
192
|
-
flex: 1,
|
|
193
|
-
paddingRight: 10
|
|
194
|
-
},
|
|
195
|
-
title: {
|
|
196
|
-
color: '#fff',
|
|
197
|
-
fontSize: 15,
|
|
198
|
-
fontWeight: '700'
|
|
199
|
-
},
|
|
200
|
-
subtitle: {
|
|
201
|
-
color: 'rgba(255,255,255,0.68)',
|
|
202
|
-
fontSize: 11,
|
|
203
|
-
marginTop: 2
|
|
204
|
-
},
|
|
205
|
-
closeButton: {
|
|
206
|
-
alignItems: 'center',
|
|
207
|
-
justifyContent: 'center',
|
|
208
|
-
paddingHorizontal: 12,
|
|
209
|
-
paddingVertical: 8,
|
|
210
|
-
borderRadius: 8,
|
|
211
|
-
backgroundColor: 'rgba(255,255,255,0.14)'
|
|
212
|
-
},
|
|
213
|
-
closeButtonText: {
|
|
214
|
-
color: '#fff',
|
|
215
|
-
fontSize: 14,
|
|
216
|
-
fontWeight: '600'
|
|
217
|
-
},
|
|
218
|
-
statusPill: {
|
|
219
|
-
position: 'absolute',
|
|
220
|
-
left: 16,
|
|
221
|
-
right: 16,
|
|
222
|
-
bottom: 30,
|
|
223
|
-
paddingHorizontal: 14,
|
|
224
|
-
paddingVertical: 11,
|
|
225
|
-
borderRadius: 12,
|
|
226
|
-
backgroundColor: 'rgba(0,0,0,0.62)'
|
|
227
|
-
},
|
|
228
|
-
statusPillError: {
|
|
229
|
-
backgroundColor: `${Colors.error}22`,
|
|
230
|
-
borderWidth: 1,
|
|
231
|
-
borderColor: `${Colors.error}66`
|
|
232
|
-
},
|
|
233
|
-
statusText: {
|
|
234
|
-
color: '#fff',
|
|
235
|
-
fontSize: 13,
|
|
236
|
-
textAlign: 'center',
|
|
237
|
-
lineHeight: 18
|
|
238
|
-
},
|
|
239
|
-
statusTextError: {
|
|
240
|
-
color: '#fff'
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
//# sourceMappingURL=DevConnectQrScanner.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","Component","useCallback","useEffect","useRef","useState","Modal","StyleSheet","Text","TouchableOpacity","View","Colors","getScannerModule","parseMetroQrPayload","jsx","_jsx","jsxs","_jsxs","CameraErrorBoundary","state","hasError","getDerivedStateFromError","componentDidCatch","error","console","warn","message","props","onCameraError","render","children","DevConnectQrScanner","visible","onClose","onScanTarget","scannedRef","setError","cameraFailed","setCameraFailed","scanner","current","handleScanned","rawValue","parsed","computerHost","metroPort","handleCameraKitRead","event","nativeEvent","codeStringValue","handleExpoScanned","result","value","handleCameraError","_msg","animationType","presentationStyle","onRequestClose","style","styles","container","previewLayer","kind","CameraKit","Camera","camera","cameraType","CameraType","Back","scanBarcode","onReadCode","showFrame","laserColor","primary","frameColor","allowedBarcodeTypes","ExpoCamera","onBarCodeScanned","barCodeScannerSettings","barCodeTypes","cameraFallback","cameraFallbackText","cameraFallbackHint","topBar","titleGroup","title","subtitle","closeButton","onPress","activeOpacity","closeButtonText","statusPill","statusPillError","statusText","statusTextError","create","flex","backgroundColor","absoluteFillObject","justifyContent","alignItems","padding","fontSize","color","fontWeight","marginBottom","textAlign","position","top","left","right","flexDirection","paddingLeft","paddingRight","paddingVertical","borderRadius","marginTop","paddingHorizontal","bottom","borderWidth","borderColor","lineHeight"],"sourceRoot":"../../../../src","sources":["features/devConnect/DevConnectQrScanner.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
// ---- react-native-camera-kit types ----
|
|
4
|
-
|
|
5
|
-
// ---- expo-camera types ----
|
|
6
|
-
|
|
7
|
-
// ---- Unified scanner ----
|
|
8
|
-
|
|
9
|
-
let cached = false;
|
|
10
|
-
function tryCameraKit() {
|
|
11
|
-
try {
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
-
const mod = require('react-native-camera-kit');
|
|
14
|
-
if (mod.Camera) {
|
|
15
|
-
return {
|
|
16
|
-
kind: 'camera-kit',
|
|
17
|
-
CameraKit: {
|
|
18
|
-
Camera: mod.Camera,
|
|
19
|
-
CameraType: mod.CameraType
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
} catch {/* not installed */}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
function tryExpoCamera() {
|
|
27
|
-
try {
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
29
|
-
const mod = require('expo-camera');
|
|
30
|
-
if (mod.Camera) {
|
|
31
|
-
return {
|
|
32
|
-
kind: 'expo-camera',
|
|
33
|
-
ExpoCamera: {
|
|
34
|
-
Camera: mod.Camera
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
} catch {/* not installed */}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
export function getScannerModule() {
|
|
42
|
-
if (cached !== false) return cached;
|
|
43
|
-
cached = tryCameraKit() ?? tryExpoCamera();
|
|
44
|
-
return cached;
|
|
45
|
-
}
|
|
46
|
-
export function isCameraKitAvailable() {
|
|
47
|
-
return getScannerModule() !== null;
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=cameraKit.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["cached","tryCameraKit","mod","require","Camera","kind","CameraKit","CameraType","tryExpoCamera","ExpoCamera","getScannerModule","isCameraKitAvailable"],"sourceRoot":"../../../../src","sources":["features/devConnect/cameraKit.ts"],"mappings":";;AAGA;;AAwBA;;AAiBA;;AAUA,IAAIA,MAAoC,GAAG,KAAK;AAEhD,SAASC,YAAYA,CAAA,EAAyB;EAC5C,IAAI;IACF;IACA,MAAMC,GAAG,GAAGC,OAAO,CAAC,yBAAyB,CAA6B;IAC1E,IAAID,GAAG,CAACE,MAAM,EAAE;MACd,OAAO;QACLC,IAAI,EAAE,YAAY;QAClBC,SAAS,EAAE;UAAEF,MAAM,EAAEF,GAAG,CAACE,MAAM;UAAEG,UAAU,EAAEL,GAAG,CAACK;QAAW;MAC9D,CAAC;IACH;EACF,CAAC,CAAC,MAAM,CAAE;EACV,OAAO,IAAI;AACb;AAEA,SAASC,aAAaA,CAAA,EAAyB;EAC7C,IAAI;IACF;IACA,MAAMN,GAAG,GAAGC,OAAO,CAAC,aAAa,CAA8B;IAC/D,IAAID,GAAG,CAACE,MAAM,EAAE;MACd,OAAO;QACLC,IAAI,EAAE,aAAa;QACnBI,UAAU,EAAE;UAAEL,MAAM,EAAEF,GAAG,CAACE;QAAO;MACnC,CAAC;IACH;EACF,CAAC,CAAC,MAAM,CAAE;EACV,OAAO,IAAI;AACb;AAEA,OAAO,SAASM,gBAAgBA,CAAA,EAAyB;EACvD,IAAIV,MAAM,KAAK,KAAK,EAAE,OAAOA,MAAM;EACnCA,MAAM,GAAGC,YAAY,CAAC,CAAC,IAAIO,aAAa,CAAC,CAAC;EAC1C,OAAOR,MAAM;AACf;AAEA,OAAO,SAASW,oBAAoBA,CAAA,EAAY;EAC9C,OAAOD,gBAAgB,CAAC,CAAC,KAAK,IAAI;AACpC","ignoreList":[]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { type ParsedComputerTarget } from './devConnectUtils';
|
|
3
|
-
interface DevConnectQrScannerProps {
|
|
4
|
-
visible: boolean;
|
|
5
|
-
onClose: () => void;
|
|
6
|
-
onScanTarget: (target: ParsedComputerTarget) => void;
|
|
7
|
-
}
|
|
8
|
-
export declare function DevConnectQrScanner({ visible, onClose, onScanTarget }: DevConnectQrScannerProps): React.JSX.Element | null;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=DevConnectQrScanner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DevConnectQrScanner.d.ts","sourceRoot":"","sources":["../../../../../src/features/devConnect/DevConnectQrScanner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8D,MAAM,OAAO,CAAC;AAenF,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAmCnF,UAAU,wBAAwB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACtD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,wBAAwB,4BAyG/F"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { ComponentType } from 'react';
|
|
2
|
-
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
-
export interface CameraKitReadCodeEvent {
|
|
4
|
-
nativeEvent?: {
|
|
5
|
-
codeStringValue?: string;
|
|
6
|
-
};
|
|
7
|
-
}
|
|
8
|
-
export interface CameraKitCameraProps {
|
|
9
|
-
style?: StyleProp<ViewStyle>;
|
|
10
|
-
cameraType?: unknown;
|
|
11
|
-
scanBarcode?: boolean;
|
|
12
|
-
onReadCode?: (event: CameraKitReadCodeEvent) => void;
|
|
13
|
-
showFrame?: boolean;
|
|
14
|
-
laserColor?: string;
|
|
15
|
-
frameColor?: string;
|
|
16
|
-
allowedBarcodeTypes?: string[];
|
|
17
|
-
}
|
|
18
|
-
export interface CameraKitModule {
|
|
19
|
-
Camera: ComponentType<CameraKitCameraProps>;
|
|
20
|
-
CameraType?: {
|
|
21
|
-
Back?: unknown;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export interface ExpoCameraScanResult {
|
|
25
|
-
boundingBox?: unknown;
|
|
26
|
-
cornerPoints?: unknown;
|
|
27
|
-
type?: string;
|
|
28
|
-
value?: string;
|
|
29
|
-
}
|
|
30
|
-
export interface ExpoCameraModule {
|
|
31
|
-
Camera: ComponentType<{
|
|
32
|
-
style?: StyleProp<ViewStyle>;
|
|
33
|
-
onBarCodeScanned?: (result: ExpoCameraScanResult) => void;
|
|
34
|
-
barCodeScannerSettings?: {
|
|
35
|
-
barCodeTypes: string[];
|
|
36
|
-
};
|
|
37
|
-
}>;
|
|
38
|
-
}
|
|
39
|
-
export type ScannerKind = 'camera-kit' | 'expo-camera';
|
|
40
|
-
export interface ScannerModule {
|
|
41
|
-
kind: ScannerKind;
|
|
42
|
-
CameraKit?: CameraKitModule;
|
|
43
|
-
ExpoCamera?: ExpoCameraModule;
|
|
44
|
-
}
|
|
45
|
-
export declare function getScannerModule(): ScannerModule | null;
|
|
46
|
-
export declare function isCameraKitAvailable(): boolean;
|
|
47
|
-
//# sourceMappingURL=cameraKit.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cameraKit.d.ts","sourceRoot":"","sources":["../../../../../src/features/devConnect/cameraKit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzD,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE;QACZ,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACjC;AAID,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,aAAa,CAAC;QACpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7B,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;QAC1D,sBAAsB,CAAC,EAAE;YAAE,YAAY,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;KACrD,CAAC,CAAC;CACJ;AAID,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,aAAa,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAgCD,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAIvD;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C"}
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import React, { Component, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Modal,
|
|
4
|
-
StyleSheet,
|
|
5
|
-
Text,
|
|
6
|
-
TouchableOpacity,
|
|
7
|
-
View,
|
|
8
|
-
} from 'react-native';
|
|
9
|
-
|
|
10
|
-
import { Colors } from '../../ui/theme/colors';
|
|
11
|
-
import {
|
|
12
|
-
getScannerModule,
|
|
13
|
-
type CameraKitReadCodeEvent,
|
|
14
|
-
type ExpoCameraScanResult,
|
|
15
|
-
} from './cameraKit';
|
|
16
|
-
import { parseMetroQrPayload, type ParsedComputerTarget } from './devConnectUtils';
|
|
17
|
-
|
|
18
|
-
// ─── Camera Error Boundary ─────────────────────────────────
|
|
19
|
-
|
|
20
|
-
interface CameraBoundaryProps {
|
|
21
|
-
children: React.ReactNode;
|
|
22
|
-
onCameraError: (msg: string) => void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface CameraBoundaryState {
|
|
26
|
-
hasError: boolean;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
class CameraErrorBoundary extends Component<CameraBoundaryProps, CameraBoundaryState> {
|
|
30
|
-
state: CameraBoundaryState = { hasError: false };
|
|
31
|
-
|
|
32
|
-
static getDerivedStateFromError(): CameraBoundaryState {
|
|
33
|
-
return { hasError: true };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
componentDidCatch(error: Error) {
|
|
37
|
-
console.warn('[DevConnect] Camera error:', error.message);
|
|
38
|
-
this.props.onCameraError(error.message || 'Camera failed to initialize.');
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
render() {
|
|
42
|
-
if (this.state.hasError) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
return this.props.children;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ─── QR Scanner ─────────────────────────────────────────────
|
|
50
|
-
|
|
51
|
-
interface DevConnectQrScannerProps {
|
|
52
|
-
visible: boolean;
|
|
53
|
-
onClose: () => void;
|
|
54
|
-
onScanTarget: (target: ParsedComputerTarget) => void;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function DevConnectQrScanner({ visible, onClose, onScanTarget }: DevConnectQrScannerProps) {
|
|
58
|
-
const scannedRef = useRef(false);
|
|
59
|
-
const [error, setError] = useState<string | null>(null);
|
|
60
|
-
const [cameraFailed, setCameraFailed] = useState(false);
|
|
61
|
-
const scanner = getScannerModule();
|
|
62
|
-
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
if (visible) {
|
|
65
|
-
scannedRef.current = false;
|
|
66
|
-
setError(null);
|
|
67
|
-
setCameraFailed(false);
|
|
68
|
-
}
|
|
69
|
-
}, [visible]);
|
|
70
|
-
|
|
71
|
-
const handleScanned = useCallback((rawValue: string) => {
|
|
72
|
-
if (scannedRef.current) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
if (typeof rawValue !== 'string') {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const parsed = parseMetroQrPayload(rawValue);
|
|
80
|
-
if (!parsed) {
|
|
81
|
-
setError('QR code does not contain a supported Metro URL.');
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
scannedRef.current = true;
|
|
86
|
-
setError(null);
|
|
87
|
-
onScanTarget({
|
|
88
|
-
computerHost: parsed.computerHost,
|
|
89
|
-
metroPort: parsed.metroPort,
|
|
90
|
-
});
|
|
91
|
-
onClose();
|
|
92
|
-
}, [onClose, onScanTarget]);
|
|
93
|
-
|
|
94
|
-
const handleCameraKitRead = useCallback((event: CameraKitReadCodeEvent) => {
|
|
95
|
-
handleScanned(event.nativeEvent?.codeStringValue ?? '');
|
|
96
|
-
}, [handleScanned]);
|
|
97
|
-
|
|
98
|
-
const handleExpoScanned = useCallback((result: ExpoCameraScanResult) => {
|
|
99
|
-
handleScanned(result.value ?? '');
|
|
100
|
-
}, [handleScanned]);
|
|
101
|
-
|
|
102
|
-
const handleCameraError = useCallback((_msg: string) => {
|
|
103
|
-
setCameraFailed(true);
|
|
104
|
-
}, []);
|
|
105
|
-
|
|
106
|
-
if (!visible || !scanner) {
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<Modal visible={visible} animationType="slide" presentationStyle="fullScreen" onRequestClose={onClose}>
|
|
112
|
-
<View style={styles.container}>
|
|
113
|
-
<View style={styles.previewLayer}>
|
|
114
|
-
{!cameraFailed && (
|
|
115
|
-
<CameraErrorBoundary onCameraError={handleCameraError}>
|
|
116
|
-
{scanner.kind === 'camera-kit' && scanner.CameraKit ? (
|
|
117
|
-
<scanner.CameraKit.Camera
|
|
118
|
-
style={styles.camera}
|
|
119
|
-
cameraType={scanner.CameraKit.CameraType?.Back}
|
|
120
|
-
scanBarcode
|
|
121
|
-
onReadCode={handleCameraKitRead}
|
|
122
|
-
showFrame
|
|
123
|
-
laserColor={Colors.primary}
|
|
124
|
-
frameColor={Colors.primary}
|
|
125
|
-
allowedBarcodeTypes={['qr']}
|
|
126
|
-
/>
|
|
127
|
-
) : scanner.kind === 'expo-camera' && scanner.ExpoCamera ? (
|
|
128
|
-
<scanner.ExpoCamera.Camera
|
|
129
|
-
style={styles.camera}
|
|
130
|
-
onBarCodeScanned={handleExpoScanned}
|
|
131
|
-
barCodeScannerSettings={{ barCodeTypes: ['qr'] }}
|
|
132
|
-
/>
|
|
133
|
-
) : null}
|
|
134
|
-
</CameraErrorBoundary>
|
|
135
|
-
)}
|
|
136
|
-
{cameraFailed && (
|
|
137
|
-
<View style={styles.cameraFallback}>
|
|
138
|
-
<Text style={styles.cameraFallbackText}>Camera unavailable.</Text>
|
|
139
|
-
<Text style={styles.cameraFallbackHint}>Please enter computer IP manually.</Text>
|
|
140
|
-
</View>
|
|
141
|
-
)}
|
|
142
|
-
</View>
|
|
143
|
-
|
|
144
|
-
<View style={styles.topBar}>
|
|
145
|
-
<View style={styles.titleGroup}>
|
|
146
|
-
<Text style={styles.title}>Scan Metro QR</Text>
|
|
147
|
-
<Text style={styles.subtitle}>Expo or Metro URL</Text>
|
|
148
|
-
</View>
|
|
149
|
-
<TouchableOpacity style={styles.closeButton} onPress={onClose} activeOpacity={0.75}>
|
|
150
|
-
<Text style={styles.closeButtonText}>Close</Text>
|
|
151
|
-
</TouchableOpacity>
|
|
152
|
-
</View>
|
|
153
|
-
|
|
154
|
-
<View style={[styles.statusPill, error && styles.statusPillError]}>
|
|
155
|
-
<Text style={[styles.statusText, error && styles.statusTextError]}>
|
|
156
|
-
{error ?? 'Point the camera at exp:// or http:// Metro URL.'}
|
|
157
|
-
</Text>
|
|
158
|
-
</View>
|
|
159
|
-
</View>
|
|
160
|
-
</Modal>
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const styles = StyleSheet.create({
|
|
165
|
-
container: { flex: 1, backgroundColor: '#000' },
|
|
166
|
-
previewLayer: { ...StyleSheet.absoluteFillObject },
|
|
167
|
-
camera: { ...StyleSheet.absoluteFillObject },
|
|
168
|
-
cameraFallback: { ...StyleSheet.absoluteFillObject, justifyContent: 'center', alignItems: 'center', padding: 24 },
|
|
169
|
-
cameraFallbackText: { fontSize: 16, color: '#fff', fontWeight: '600', marginBottom: 8 },
|
|
170
|
-
cameraFallbackHint: { fontSize: 13, color: 'rgba(255,255,255,0.6)', textAlign: 'center' },
|
|
171
|
-
topBar: {
|
|
172
|
-
position: 'absolute',
|
|
173
|
-
top: 44,
|
|
174
|
-
left: 16,
|
|
175
|
-
right: 16,
|
|
176
|
-
flexDirection: 'row',
|
|
177
|
-
alignItems: 'center',
|
|
178
|
-
justifyContent: 'space-between',
|
|
179
|
-
paddingLeft: 14,
|
|
180
|
-
paddingRight: 8,
|
|
181
|
-
paddingVertical: 8,
|
|
182
|
-
borderRadius: 12,
|
|
183
|
-
backgroundColor: 'rgba(0,0,0,0.62)',
|
|
184
|
-
},
|
|
185
|
-
titleGroup: { flex: 1, paddingRight: 10 },
|
|
186
|
-
title: { color: '#fff', fontSize: 15, fontWeight: '700' },
|
|
187
|
-
subtitle: { color: 'rgba(255,255,255,0.68)', fontSize: 11, marginTop: 2 },
|
|
188
|
-
closeButton: {
|
|
189
|
-
alignItems: 'center',
|
|
190
|
-
justifyContent: 'center',
|
|
191
|
-
paddingHorizontal: 12,
|
|
192
|
-
paddingVertical: 8,
|
|
193
|
-
borderRadius: 8,
|
|
194
|
-
backgroundColor: 'rgba(255,255,255,0.14)',
|
|
195
|
-
},
|
|
196
|
-
closeButtonText: { color: '#fff', fontSize: 14, fontWeight: '600' },
|
|
197
|
-
statusPill: {
|
|
198
|
-
position: 'absolute',
|
|
199
|
-
left: 16,
|
|
200
|
-
right: 16,
|
|
201
|
-
bottom: 30,
|
|
202
|
-
paddingHorizontal: 14,
|
|
203
|
-
paddingVertical: 11,
|
|
204
|
-
borderRadius: 12,
|
|
205
|
-
backgroundColor: 'rgba(0,0,0,0.62)',
|
|
206
|
-
},
|
|
207
|
-
statusPillError: {
|
|
208
|
-
backgroundColor: `${Colors.error}22`,
|
|
209
|
-
borderWidth: 1,
|
|
210
|
-
borderColor: `${Colors.error}66`,
|
|
211
|
-
},
|
|
212
|
-
statusText: { color: '#fff', fontSize: 13, textAlign: 'center', lineHeight: 18 },
|
|
213
|
-
statusTextError: { color: '#fff' },
|
|
214
|
-
});
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import type { ComponentType } from 'react';
|
|
2
|
-
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
-
|
|
4
|
-
// ---- react-native-camera-kit types ----
|
|
5
|
-
|
|
6
|
-
export interface CameraKitReadCodeEvent {
|
|
7
|
-
nativeEvent?: {
|
|
8
|
-
codeStringValue?: string;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface CameraKitCameraProps {
|
|
13
|
-
style?: StyleProp<ViewStyle>;
|
|
14
|
-
cameraType?: unknown;
|
|
15
|
-
scanBarcode?: boolean;
|
|
16
|
-
onReadCode?: (event: CameraKitReadCodeEvent) => void;
|
|
17
|
-
showFrame?: boolean;
|
|
18
|
-
laserColor?: string;
|
|
19
|
-
frameColor?: string;
|
|
20
|
-
allowedBarcodeTypes?: string[];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface CameraKitModule {
|
|
24
|
-
Camera: ComponentType<CameraKitCameraProps>;
|
|
25
|
-
CameraType?: { Back?: unknown };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ---- expo-camera types ----
|
|
29
|
-
|
|
30
|
-
export interface ExpoCameraScanResult {
|
|
31
|
-
boundingBox?: unknown;
|
|
32
|
-
cornerPoints?: unknown;
|
|
33
|
-
type?: string;
|
|
34
|
-
value?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface ExpoCameraModule {
|
|
38
|
-
Camera: ComponentType<{
|
|
39
|
-
style?: StyleProp<ViewStyle>;
|
|
40
|
-
onBarCodeScanned?: (result: ExpoCameraScanResult) => void;
|
|
41
|
-
barCodeScannerSettings?: { barCodeTypes: string[] };
|
|
42
|
-
}>;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// ---- Unified scanner ----
|
|
46
|
-
|
|
47
|
-
export type ScannerKind = 'camera-kit' | 'expo-camera';
|
|
48
|
-
|
|
49
|
-
export interface ScannerModule {
|
|
50
|
-
kind: ScannerKind;
|
|
51
|
-
CameraKit?: CameraKitModule;
|
|
52
|
-
ExpoCamera?: ExpoCameraModule;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let cached: ScannerModule | null | false = false;
|
|
56
|
-
|
|
57
|
-
function tryCameraKit(): ScannerModule | null {
|
|
58
|
-
try {
|
|
59
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
60
|
-
const mod = require('react-native-camera-kit') as Partial<CameraKitModule>;
|
|
61
|
-
if (mod.Camera) {
|
|
62
|
-
return {
|
|
63
|
-
kind: 'camera-kit',
|
|
64
|
-
CameraKit: { Camera: mod.Camera, CameraType: mod.CameraType },
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
} catch { /* not installed */ }
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function tryExpoCamera(): ScannerModule | null {
|
|
72
|
-
try {
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
74
|
-
const mod = require('expo-camera') as Partial<ExpoCameraModule>;
|
|
75
|
-
if (mod.Camera) {
|
|
76
|
-
return {
|
|
77
|
-
kind: 'expo-camera',
|
|
78
|
-
ExpoCamera: { Camera: mod.Camera },
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
} catch { /* not installed */ }
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function getScannerModule(): ScannerModule | null {
|
|
86
|
-
if (cached !== false) return cached;
|
|
87
|
-
cached = tryCameraKit() ?? tryExpoCamera();
|
|
88
|
-
return cached;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function isCameraKitAvailable(): boolean {
|
|
92
|
-
return getScannerModule() !== null;
|
|
93
|
-
}
|