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.
Files changed (67) hide show
  1. package/android/src/main/java/com/reactnativedebugtoolkit/DebugToolkitDevConnectModule.java +43 -8
  2. package/ios/DebugToolkitDevConnect.mm +54 -1
  3. package/lib/commonjs/core/initialize.js +15 -3
  4. package/lib/commonjs/core/initialize.js.map +1 -1
  5. package/lib/commonjs/features/devConnect/DevConnectTab.js +30 -47
  6. package/lib/commonjs/features/devConnect/DevConnectTab.js.map +1 -1
  7. package/lib/commonjs/features/devConnect/devConnectUtils.js +8 -0
  8. package/lib/commonjs/features/devConnect/devConnectUtils.js.map +1 -1
  9. package/lib/commonjs/features/devConnect/index.js +22 -3
  10. package/lib/commonjs/features/devConnect/index.js.map +1 -1
  11. package/lib/commonjs/features/devConnect/nativeDevConnect.js +26 -0
  12. package/lib/commonjs/features/devConnect/nativeDevConnect.js.map +1 -1
  13. package/lib/commonjs/ui/DebugView.js +10 -2
  14. package/lib/commonjs/ui/DebugView.js.map +1 -1
  15. package/lib/commonjs/utils/DaemonClient.js +5 -0
  16. package/lib/commonjs/utils/DaemonClient.js.map +1 -1
  17. package/lib/module/core/initialize.js +16 -4
  18. package/lib/module/core/initialize.js.map +1 -1
  19. package/lib/module/features/devConnect/DevConnectTab.js +30 -47
  20. package/lib/module/features/devConnect/DevConnectTab.js.map +1 -1
  21. package/lib/module/features/devConnect/devConnectUtils.js +7 -0
  22. package/lib/module/features/devConnect/devConnectUtils.js.map +1 -1
  23. package/lib/module/features/devConnect/index.js +19 -5
  24. package/lib/module/features/devConnect/index.js.map +1 -1
  25. package/lib/module/features/devConnect/nativeDevConnect.js +24 -0
  26. package/lib/module/features/devConnect/nativeDevConnect.js.map +1 -1
  27. package/lib/module/ui/DebugView.js +11 -3
  28. package/lib/module/ui/DebugView.js.map +1 -1
  29. package/lib/module/utils/DaemonClient.js +5 -0
  30. package/lib/module/utils/DaemonClient.js.map +1 -1
  31. package/lib/typescript/src/core/initialize.d.ts +4 -2
  32. package/lib/typescript/src/core/initialize.d.ts.map +1 -1
  33. package/lib/typescript/src/features/devConnect/DevConnectTab.d.ts.map +1 -1
  34. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts +1 -0
  35. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts.map +1 -1
  36. package/lib/typescript/src/features/devConnect/index.d.ts +1 -0
  37. package/lib/typescript/src/features/devConnect/index.d.ts.map +1 -1
  38. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts +2 -0
  39. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts.map +1 -1
  40. package/lib/typescript/src/features/devConnect/types.d.ts +1 -1
  41. package/lib/typescript/src/features/devConnect/types.d.ts.map +1 -1
  42. package/lib/typescript/src/ui/DebugView.d.ts.map +1 -1
  43. package/lib/typescript/src/utils/DaemonClient.d.ts +2 -0
  44. package/lib/typescript/src/utils/DaemonClient.d.ts.map +1 -1
  45. package/package.json +2 -10
  46. package/src/core/initialize.ts +17 -5
  47. package/src/features/devConnect/DevConnectTab.tsx +18 -34
  48. package/src/features/devConnect/devConnectUtils.ts +8 -0
  49. package/src/features/devConnect/index.ts +18 -5
  50. package/src/features/devConnect/nativeDevConnect.ts +28 -0
  51. package/src/features/devConnect/types.ts +1 -1
  52. package/src/ui/DebugView.tsx +12 -3
  53. package/src/utils/DaemonClient.ts +7 -0
  54. package/lib/commonjs/features/devConnect/DevConnectQrScanner.js +0 -248
  55. package/lib/commonjs/features/devConnect/DevConnectQrScanner.js.map +0 -1
  56. package/lib/commonjs/features/devConnect/cameraKit.js +0 -54
  57. package/lib/commonjs/features/devConnect/cameraKit.js.map +0 -1
  58. package/lib/module/features/devConnect/DevConnectQrScanner.js +0 -243
  59. package/lib/module/features/devConnect/DevConnectQrScanner.js.map +0 -1
  60. package/lib/module/features/devConnect/cameraKit.js +0 -49
  61. package/lib/module/features/devConnect/cameraKit.js.map +0 -1
  62. package/lib/typescript/src/features/devConnect/DevConnectQrScanner.d.ts +0 -10
  63. package/lib/typescript/src/features/devConnect/DevConnectQrScanner.d.ts.map +0 -1
  64. package/lib/typescript/src/features/devConnect/cameraKit.d.ts +0 -47
  65. package/lib/typescript/src/features/devConnect/cameraKit.d.ts.map +0 -1
  66. package/src/features/devConnect/DevConnectQrScanner.tsx +0 -214
  67. 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
- }