react-native-debug-toolkit 3.2.2 → 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 +123 -4
  2. package/ios/DebugToolkitDevConnect.mm +69 -2
  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 -2
  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 +25 -3
  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 +29 -3
  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 -214
  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 -209
  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 -184
  67. package/src/features/devConnect/cameraKit.ts +0 -93
@@ -1,54 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getScannerModule = getScannerModule;
7
- exports.isCameraKitAvailable = isCameraKitAvailable;
8
- // ---- react-native-camera-kit types ----
9
-
10
- // ---- expo-camera types ----
11
-
12
- // ---- Unified scanner ----
13
-
14
- let cached = false;
15
- function tryCameraKit() {
16
- try {
17
- // eslint-disable-next-line @typescript-eslint/no-require-imports
18
- const mod = require('react-native-camera-kit');
19
- if (mod.Camera) {
20
- return {
21
- kind: 'camera-kit',
22
- CameraKit: {
23
- Camera: mod.Camera,
24
- CameraType: mod.CameraType
25
- }
26
- };
27
- }
28
- } catch {/* not installed */}
29
- return null;
30
- }
31
- function tryExpoCamera() {
32
- try {
33
- // eslint-disable-next-line @typescript-eslint/no-require-imports
34
- const mod = require('expo-camera');
35
- if (mod.Camera) {
36
- return {
37
- kind: 'expo-camera',
38
- ExpoCamera: {
39
- Camera: mod.Camera
40
- }
41
- };
42
- }
43
- } catch {/* not installed */}
44
- return null;
45
- }
46
- function getScannerModule() {
47
- if (cached !== false) return cached;
48
- cached = tryCameraKit() ?? tryExpoCamera();
49
- return cached;
50
- }
51
- function isCameraKitAvailable() {
52
- return getScannerModule() !== null;
53
- }
54
- //# 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;AAEO,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;AAEO,SAASW,oBAAoBA,CAAA,EAAY;EAC9C,OAAOD,gBAAgB,CAAC,CAAC,KAAK,IAAI;AACpC","ignoreList":[]}
@@ -1,209 +0,0 @@
1
- "use strict";
2
-
3
- import React, { Component, useCallback, useEffect, useRef, useState } from 'react';
4
- import { Modal, Pressable, 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
- onRequestClose: onClose,
86
- children: /*#__PURE__*/_jsxs(View, {
87
- style: styles.container,
88
- children: [!cameraFailed && /*#__PURE__*/_jsx(CameraErrorBoundary, {
89
- onCameraError: handleCameraError,
90
- children: scanner.kind === 'camera-kit' && scanner.CameraKit ? /*#__PURE__*/_jsx(scanner.CameraKit.Camera, {
91
- style: styles.camera,
92
- cameraType: scanner.CameraKit.CameraType?.Back,
93
- scanBarcode: true,
94
- onReadCode: handleCameraKitRead,
95
- showFrame: true,
96
- laserColor: Colors.primary,
97
- frameColor: Colors.primary,
98
- allowedBarcodeTypes: ['qr']
99
- }) : scanner.kind === 'expo-camera' && scanner.ExpoCamera ? /*#__PURE__*/_jsx(scanner.ExpoCamera.Camera, {
100
- style: styles.camera,
101
- onBarCodeScanned: handleExpoScanned,
102
- barCodeScannerSettings: {
103
- barCodeTypes: ['qr']
104
- }
105
- }) : null
106
- }), cameraFailed && /*#__PURE__*/_jsxs(View, {
107
- style: styles.cameraFallback,
108
- children: [/*#__PURE__*/_jsx(Text, {
109
- style: styles.cameraFallbackText,
110
- children: "Camera unavailable."
111
- }), /*#__PURE__*/_jsx(Text, {
112
- style: styles.cameraFallbackHint,
113
- children: "Please enter computer IP manually."
114
- })]
115
- }), /*#__PURE__*/_jsxs(View, {
116
- style: styles.footer,
117
- children: [!cameraFailed && !error && /*#__PURE__*/_jsx(Text, {
118
- style: styles.hint,
119
- children: "Scan a Metro QR code."
120
- }), error && /*#__PURE__*/_jsx(Text, {
121
- style: styles.error,
122
- children: error
123
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
124
- style: styles.closeButton,
125
- onPress: onClose,
126
- activeOpacity: 0.7,
127
- children: /*#__PURE__*/_jsx(Text, {
128
- style: styles.closeButtonText,
129
- children: "Close"
130
- })
131
- })]
132
- }), /*#__PURE__*/_jsx(Pressable, {
133
- style: styles.topClose,
134
- onPress: onClose,
135
- children: /*#__PURE__*/_jsx(Text, {
136
- style: styles.topCloseText,
137
- children: "Close"
138
- })
139
- })]
140
- })
141
- });
142
- }
143
- const styles = StyleSheet.create({
144
- container: {
145
- flex: 1,
146
- backgroundColor: '#000'
147
- },
148
- camera: {
149
- flex: 1
150
- },
151
- cameraFallback: {
152
- flex: 1,
153
- justifyContent: 'center',
154
- alignItems: 'center',
155
- padding: 24
156
- },
157
- cameraFallbackText: {
158
- fontSize: 16,
159
- color: '#fff',
160
- fontWeight: '600',
161
- marginBottom: 8
162
- },
163
- cameraFallbackHint: {
164
- fontSize: 13,
165
- color: 'rgba(255,255,255,0.6)',
166
- textAlign: 'center'
167
- },
168
- footer: {
169
- padding: 16,
170
- backgroundColor: Colors.surface
171
- },
172
- hint: {
173
- fontSize: 13,
174
- color: Colors.textSecondary,
175
- marginBottom: 12
176
- },
177
- error: {
178
- fontSize: 13,
179
- color: Colors.error,
180
- marginBottom: 12
181
- },
182
- closeButton: {
183
- alignItems: 'center',
184
- justifyContent: 'center',
185
- paddingVertical: 11,
186
- borderRadius: 10,
187
- backgroundColor: Colors.primary
188
- },
189
- closeButtonText: {
190
- color: '#fff',
191
- fontSize: 14,
192
- fontWeight: '600'
193
- },
194
- topClose: {
195
- position: 'absolute',
196
- top: 48,
197
- right: 16,
198
- paddingHorizontal: 12,
199
- paddingVertical: 8,
200
- borderRadius: 8,
201
- backgroundColor: 'rgba(0,0,0,0.55)'
202
- },
203
- topCloseText: {
204
- color: '#fff',
205
- fontSize: 13,
206
- fontWeight: '600'
207
- }
208
- });
209
- //# sourceMappingURL=DevConnectQrScanner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["React","Component","useCallback","useEffect","useRef","useState","Modal","Pressable","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","onRequestClose","style","styles","container","kind","CameraKit","Camera","camera","cameraType","CameraType","Back","scanBarcode","onReadCode","showFrame","laserColor","primary","frameColor","allowedBarcodeTypes","ExpoCamera","onBarCodeScanned","barCodeScannerSettings","barCodeTypes","cameraFallback","cameraFallbackText","cameraFallbackHint","footer","hint","closeButton","onPress","activeOpacity","closeButtonText","topClose","topCloseText","create","flex","backgroundColor","justifyContent","alignItems","padding","fontSize","color","fontWeight","marginBottom","textAlign","surface","textSecondary","paddingVertical","borderRadius","position","top","right","paddingHorizontal"],"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;AAgBnF,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,4BAiG/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,184 +0,0 @@
1
- import React, { Component, useCallback, useEffect, useRef, useState } from 'react';
2
- import {
3
- Modal,
4
- Pressable,
5
- StyleSheet,
6
- Text,
7
- TouchableOpacity,
8
- View,
9
- } from 'react-native';
10
-
11
- import { Colors } from '../../ui/theme/colors';
12
- import {
13
- getScannerModule,
14
- type CameraKitReadCodeEvent,
15
- type ExpoCameraScanResult,
16
- } from './cameraKit';
17
- import { parseMetroQrPayload, type ParsedComputerTarget } from './devConnectUtils';
18
-
19
- // ─── Camera Error Boundary ─────────────────────────────────
20
-
21
- interface CameraBoundaryProps {
22
- children: React.ReactNode;
23
- onCameraError: (msg: string) => void;
24
- }
25
-
26
- interface CameraBoundaryState {
27
- hasError: boolean;
28
- }
29
-
30
- class CameraErrorBoundary extends Component<CameraBoundaryProps, CameraBoundaryState> {
31
- state: CameraBoundaryState = { hasError: false };
32
-
33
- static getDerivedStateFromError(): CameraBoundaryState {
34
- return { hasError: true };
35
- }
36
-
37
- componentDidCatch(error: Error) {
38
- console.warn('[DevConnect] Camera error:', error.message);
39
- this.props.onCameraError(error.message || 'Camera failed to initialize.');
40
- }
41
-
42
- render() {
43
- if (this.state.hasError) {
44
- return null;
45
- }
46
- return this.props.children;
47
- }
48
- }
49
-
50
- // ─── QR Scanner ─────────────────────────────────────────────
51
-
52
- interface DevConnectQrScannerProps {
53
- visible: boolean;
54
- onClose: () => void;
55
- onScanTarget: (target: ParsedComputerTarget) => void;
56
- }
57
-
58
- export function DevConnectQrScanner({ visible, onClose, onScanTarget }: DevConnectQrScannerProps) {
59
- const scannedRef = useRef(false);
60
- const [error, setError] = useState<string | null>(null);
61
- const [cameraFailed, setCameraFailed] = useState(false);
62
- const scanner = getScannerModule();
63
-
64
- useEffect(() => {
65
- if (visible) {
66
- scannedRef.current = false;
67
- setError(null);
68
- setCameraFailed(false);
69
- }
70
- }, [visible]);
71
-
72
- const handleScanned = useCallback((rawValue: string) => {
73
- if (scannedRef.current) {
74
- return;
75
- }
76
- if (typeof rawValue !== 'string') {
77
- return;
78
- }
79
-
80
- const parsed = parseMetroQrPayload(rawValue);
81
- if (!parsed) {
82
- setError('QR code does not contain a supported Metro URL.');
83
- return;
84
- }
85
-
86
- scannedRef.current = true;
87
- setError(null);
88
- onScanTarget({
89
- computerHost: parsed.computerHost,
90
- metroPort: parsed.metroPort,
91
- });
92
- onClose();
93
- }, [onClose, onScanTarget]);
94
-
95
- const handleCameraKitRead = useCallback((event: CameraKitReadCodeEvent) => {
96
- handleScanned(event.nativeEvent?.codeStringValue ?? '');
97
- }, [handleScanned]);
98
-
99
- const handleExpoScanned = useCallback((result: ExpoCameraScanResult) => {
100
- handleScanned(result.value ?? '');
101
- }, [handleScanned]);
102
-
103
- const handleCameraError = useCallback((_msg: string) => {
104
- setCameraFailed(true);
105
- }, []);
106
-
107
- if (!visible || !scanner) {
108
- return null;
109
- }
110
-
111
- return (
112
- <Modal visible={visible} animationType="slide" onRequestClose={onClose}>
113
- <View style={styles.container}>
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 style={styles.footer}>
143
- {!cameraFailed && !error && <Text style={styles.hint}>Scan a Metro QR code.</Text>}
144
- {error && <Text style={styles.error}>{error}</Text>}
145
- <TouchableOpacity style={styles.closeButton} onPress={onClose} activeOpacity={0.7}>
146
- <Text style={styles.closeButtonText}>Close</Text>
147
- </TouchableOpacity>
148
- </View>
149
- <Pressable style={styles.topClose} onPress={onClose}>
150
- <Text style={styles.topCloseText}>Close</Text>
151
- </Pressable>
152
- </View>
153
- </Modal>
154
- );
155
- }
156
-
157
- const styles = StyleSheet.create({
158
- container: { flex: 1, backgroundColor: '#000' },
159
- camera: { flex: 1 },
160
- cameraFallback: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 24 },
161
- cameraFallbackText: { fontSize: 16, color: '#fff', fontWeight: '600', marginBottom: 8 },
162
- cameraFallbackHint: { fontSize: 13, color: 'rgba(255,255,255,0.6)', textAlign: 'center' },
163
- footer: { padding: 16, backgroundColor: Colors.surface },
164
- hint: { fontSize: 13, color: Colors.textSecondary, marginBottom: 12 },
165
- error: { fontSize: 13, color: Colors.error, marginBottom: 12 },
166
- closeButton: {
167
- alignItems: 'center',
168
- justifyContent: 'center',
169
- paddingVertical: 11,
170
- borderRadius: 10,
171
- backgroundColor: Colors.primary,
172
- },
173
- closeButtonText: { color: '#fff', fontSize: 14, fontWeight: '600' },
174
- topClose: {
175
- position: 'absolute',
176
- top: 48,
177
- right: 16,
178
- paddingHorizontal: 12,
179
- paddingVertical: 8,
180
- borderRadius: 8,
181
- backgroundColor: 'rgba(0,0,0,0.55)',
182
- },
183
- topCloseText: { color: '#fff', fontSize: 13, fontWeight: '600' },
184
- });
@@ -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
- }