react-native-inapp-inspector 2.3.10 → 2.3.11

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 (43) hide show
  1. package/dist/commonjs/components/Inspector/DebuggingTab.d.ts +3 -0
  2. package/dist/commonjs/components/Inspector/DebuggingTab.js +682 -0
  3. package/dist/commonjs/components/Inspector/MainScreen.js +2 -0
  4. package/dist/commonjs/components/Inspector/SettingsPanel.js +12 -0
  5. package/dist/commonjs/components/Inspector/TabBar.js +9 -0
  6. package/dist/commonjs/components/NetworkIcons.d.ts +1 -0
  7. package/dist/commonjs/components/NetworkIcons.js +8 -1
  8. package/dist/commonjs/components/QRCodeView.d.ts +9 -0
  9. package/dist/commonjs/components/QRCodeView.js +79 -0
  10. package/dist/commonjs/constants/version.d.ts +1 -1
  11. package/dist/commonjs/constants/version.js +1 -1
  12. package/dist/commonjs/helpers/qrGenerator.d.ts +2 -0
  13. package/dist/commonjs/helpers/qrGenerator.js +170 -0
  14. package/dist/commonjs/index.js +2 -0
  15. package/dist/commonjs/types/enums.d.ts +2 -0
  16. package/dist/commonjs/types/enums.js +2 -0
  17. package/dist/esm/components/Inspector/DebuggingTab.d.ts +3 -0
  18. package/dist/esm/components/Inspector/DebuggingTab.js +642 -0
  19. package/dist/esm/components/Inspector/MainScreen.js +2 -0
  20. package/dist/esm/components/Inspector/SettingsPanel.js +13 -1
  21. package/dist/esm/components/Inspector/TabBar.js +10 -1
  22. package/dist/esm/components/NetworkIcons.d.ts +1 -0
  23. package/dist/esm/components/NetworkIcons.js +6 -0
  24. package/dist/esm/components/QRCodeView.d.ts +9 -0
  25. package/dist/esm/components/QRCodeView.js +42 -0
  26. package/dist/esm/constants/version.d.ts +1 -1
  27. package/dist/esm/constants/version.js +1 -1
  28. package/dist/esm/helpers/qrGenerator.d.ts +2 -0
  29. package/dist/esm/helpers/qrGenerator.js +167 -0
  30. package/dist/esm/index.js +2 -0
  31. package/dist/esm/types/enums.d.ts +2 -0
  32. package/dist/esm/types/enums.js +2 -0
  33. package/package.json +1 -1
  34. package/src/components/Inspector/DebuggingTab.tsx +755 -0
  35. package/src/components/Inspector/MainScreen.tsx +2 -0
  36. package/src/components/Inspector/SettingsPanel.tsx +20 -0
  37. package/src/components/Inspector/TabBar.tsx +11 -0
  38. package/src/components/NetworkIcons.tsx +39 -0
  39. package/src/components/QRCodeView.tsx +71 -0
  40. package/src/constants/version.ts +1 -1
  41. package/src/helpers/qrGenerator.ts +184 -0
  42. package/src/index.tsx +2 -0
  43. package/src/types/enums.ts +2 -0
@@ -29,6 +29,7 @@ import CrashTab from './CrashTab';
29
29
  import CrashDetail from './CrashDetail';
30
30
  import DeviceInfoTab from './DeviceInfoTab';
31
31
  import StorageTab from './StorageTab';
32
+ import DebuggingTab from './DebuggingTab';
32
33
  import SettingsPanel from './SettingsPanel';
33
34
  import NpmUpdateToast from './NpmUpdateToast';
34
35
  import Toast from '../Toast';
@@ -170,6 +171,7 @@ const MainScreen = () => {
170
171
  {activeTab === 'crash' && <CrashTab />}
171
172
  {activeTab === 'device' && <DeviceInfoTab />}
172
173
  {activeTab === 'storage' && <StorageTab />}
174
+ {activeTab === 'debugging' && <DebuggingTab />}
173
175
  </Animated.View>
174
176
 
175
177
  {/* Detail View Layer - Rendered on top with smooth slide & spring transition */}
@@ -56,6 +56,7 @@ import {
56
56
  BrainIcon,
57
57
  SmartphoneIcon,
58
58
  DatabaseIcon,
59
+ QrCodeIcon,
59
60
  } from '../NetworkIcons';
60
61
  import {LIB_VERSION} from '../../constants';
61
62
  import {copyToClipboard} from '../../helpers';
@@ -194,6 +195,13 @@ const SettingsPanel = () => {
194
195
  icon: 'storage',
195
196
  desc: 'AsyncStorage & MMKV key-value store viewer with full CRUD support',
196
197
  },
198
+ {
199
+ key: 'debugging',
200
+ label: 'Multi-Device Debugging',
201
+ category: 'diagnostic',
202
+ icon: 'debugging',
203
+ desc: 'QR Code bridge for direct Debug APK download & Metro live-reload sync',
204
+ },
197
205
  ] as const;
198
206
 
199
207
  // Staged selection state for checkboxes before clicking "Save Changes"
@@ -209,6 +217,7 @@ const SettingsPanel = () => {
209
217
  crash: Boolean(tabVisibility?.crash),
210
218
  device: Boolean(tabVisibility?.device),
211
219
  storage: Boolean(tabVisibility?.storage),
220
+ debugging: Boolean(tabVisibility?.debugging ?? true),
212
221
  }));
213
222
 
214
223
  // Synchronize staged state with tabVisibility when tabVisibility updates
@@ -223,6 +232,7 @@ const SettingsPanel = () => {
223
232
  crash: Boolean(tabVisibility?.crash),
224
233
  device: Boolean(tabVisibility?.device),
225
234
  storage: Boolean(tabVisibility?.storage),
235
+ debugging: Boolean(tabVisibility?.debugging ?? true),
226
236
  });
227
237
  }, [tabVisibility]);
228
238
 
@@ -823,6 +833,16 @@ const SettingsPanel = () => {
823
833
  size={16}
824
834
  />
825
835
  )}
836
+ {moduleItem.icon === 'debugging' && (
837
+ <QrCodeIcon
838
+ color={
839
+ isChecked
840
+ ? AppColors.purple
841
+ : AppColors.grayTextWeak
842
+ }
843
+ size={16}
844
+ />
845
+ )}
826
846
  </View>
827
847
 
828
848
  {/* Titles & Status Pill */}
@@ -14,6 +14,7 @@ import {
14
14
  CrashIcon,
15
15
  SmartphoneIcon,
16
16
  DatabaseIcon,
17
+ QrCodeIcon,
17
18
  } from '../NetworkIcons';
18
19
 
19
20
  import {isReduxConnected} from '../../customHooks/reduxLogger';
@@ -100,9 +101,16 @@ const TabBar = React.memo(() => {
100
101
  count: 0,
101
102
  icon: 'storage',
102
103
  },
104
+ {
105
+ key: 'debugging',
106
+ label: 'Debugging',
107
+ count: 0,
108
+ icon: 'debugging',
109
+ },
103
110
  ] as const
104
111
  )
105
112
  .filter(tab => {
113
+ if (tab.key === 'debugging') return true;
106
114
  if (!tabVisibility?.[tab.key]) return false;
107
115
  if (tab.key === 'redux' && !isReduxAvail) return false;
108
116
  if (tab.key === 'analytics' && !isAnalyticsAvail) return false;
@@ -169,6 +177,9 @@ const TabBar = React.memo(() => {
169
177
  {tab.icon === 'storage' && (
170
178
  <DatabaseIcon color={iconColor} size={14} />
171
179
  )}
180
+ {tab.icon === 'debugging' && (
181
+ <QrCodeIcon color={iconColor} size={14} />
182
+ )}
172
183
  <Text
173
184
  numberOfLines={1}
174
185
  ellipsizeMode="tail"
@@ -2246,3 +2246,42 @@ export const LockIcon = ({
2246
2246
  </Svg>
2247
2247
  );
2248
2248
 
2249
+ export const QrCodeIcon = ({
2250
+ color = AppColors.grayTextWeak,
2251
+ size = 14,
2252
+ }: IconProps) => (
2253
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
2254
+ <Rect
2255
+ x="3"
2256
+ y="3"
2257
+ width="7"
2258
+ height="7"
2259
+ rx="1.5"
2260
+ stroke={color}
2261
+ strokeWidth="2"
2262
+ />
2263
+ <Rect
2264
+ x="14"
2265
+ y="3"
2266
+ width="7"
2267
+ height="7"
2268
+ rx="1.5"
2269
+ stroke={color}
2270
+ strokeWidth="2"
2271
+ />
2272
+ <Rect
2273
+ x="3"
2274
+ y="14"
2275
+ width="7"
2276
+ height="7"
2277
+ rx="1.5"
2278
+ stroke={color}
2279
+ strokeWidth="2"
2280
+ />
2281
+ <Path
2282
+ d="M14 14h3v3h-3zM18 18h3v3h-3zM14 19h3v2h-3zM19 14h2v3h-2z"
2283
+ fill={color}
2284
+ />
2285
+ </Svg>
2286
+ );
2287
+
@@ -0,0 +1,71 @@
1
+ import React, {useMemo} from 'react';
2
+ import {View, StyleSheet} from 'react-native';
3
+ import Svg, {Rect, G} from 'react-native-svg';
4
+ import {generateQRMatrix} from '../helpers/qrGenerator';
5
+ import {AppColors} from '../styles/AppColors';
6
+
7
+ interface QRCodeViewProps {
8
+ value: string;
9
+ size?: number;
10
+ color?: string;
11
+ backgroundColor?: string;
12
+ }
13
+
14
+ export const QRCodeView: React.FC<QRCodeViewProps> = ({
15
+ value,
16
+ size = 180,
17
+ color = AppColors.primaryBlack,
18
+ backgroundColor = AppColors.white,
19
+ }) => {
20
+ const matrix = useMemo(() => generateQRMatrix(value), [value]);
21
+ const numCells = matrix.length;
22
+ const cellSize = size / numCells;
23
+
24
+ return (
25
+ <View
26
+ style={[
27
+ styles.container,
28
+ {
29
+ width: size + 16,
30
+ height: size + 16,
31
+ backgroundColor,
32
+ },
33
+ ]}>
34
+ <Svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
35
+ <G>
36
+ {matrix.map((row, r) =>
37
+ row.map((cell, c) => {
38
+ if (!cell) return null;
39
+ return (
40
+ <Rect
41
+ key={`${r}-${c}`}
42
+ x={c * cellSize}
43
+ y={r * cellSize}
44
+ width={cellSize + 0.2}
45
+ height={cellSize + 0.2}
46
+ fill={color}
47
+ />
48
+ );
49
+ }),
50
+ )}
51
+ </G>
52
+ </Svg>
53
+ </View>
54
+ );
55
+ };
56
+
57
+ const styles = StyleSheet.create({
58
+ container: {
59
+ padding: 8,
60
+ borderRadius: 14,
61
+ alignItems: 'center',
62
+ justifyContent: 'center',
63
+ shadowColor: AppColors.black,
64
+ shadowOffset: {width: 0, height: 2},
65
+ shadowOpacity: 0.1,
66
+ shadowRadius: 6,
67
+ elevation: 3,
68
+ },
69
+ });
70
+
71
+ export default QRCodeView;
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED FILE — do not edit by hand.
2
2
  // Regenerated from package.json on every build by scripts/gen-version.js.
3
- export const LIB_VERSION = '2.3.10';
3
+ export const LIB_VERSION = '2.3.11';
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Compact Pure TypeScript QR Code Matrix Generator
3
+ * Generates standard QR Code 2D boolean matrices for rendering with react-native-svg
4
+ */
5
+
6
+ // Error correction levels: L (7%), M (15%), Q (25%), H (30%)
7
+ export type QRECC = 'L' | 'M' | 'Q' | 'H';
8
+
9
+ // QR Code generation helper (using compact byte-mode QR encoder)
10
+ export function generateQRMatrix(text: string, ecc: QRECC = 'M'): boolean[][] {
11
+ try {
12
+ return createQRMatrix(text, ecc);
13
+ } catch {
14
+ // Fallback: create a structured matrix pattern if text is excessively long
15
+ return createFallbackMatrix(text);
16
+ }
17
+ }
18
+
19
+ // ─── Simple & Robust QR Code Matrix Generator Implementation ──────────────────
20
+
21
+ function createQRMatrix(data: string, ecc: QRECC): boolean[][] {
22
+ const length = data.length;
23
+ // Choose minimum version based on data length
24
+ let version = 1;
25
+ if (length > 14) version = 2;
26
+ if (length > 26) version = 3;
27
+ if (length > 42) version = 4;
28
+ if (length > 62) version = 5;
29
+ if (length > 84) version = 6;
30
+ if (length > 106) version = 7;
31
+ if (length > 122) version = 8;
32
+ if (length > 152) version = 9;
33
+ if (length > 180) version = 10;
34
+
35
+ const size = version * 4 + 17;
36
+ const matrix: (boolean | null)[][] = Array(size)
37
+ .fill(null)
38
+ .map(() => Array(size).fill(null));
39
+
40
+ // 1. Position finder patterns (top-left, top-right, bottom-left)
41
+ addFinderPattern(matrix, 0, 0);
42
+ addFinderPattern(matrix, size - 7, 0);
43
+ addFinderPattern(matrix, 0, size - 7);
44
+
45
+ // 2. Timing patterns (horizontal and vertical alternating lines)
46
+ for (let i = 8; i < size - 8; i++) {
47
+ const val = i % 2 === 0;
48
+ if (matrix[6][i] === null) matrix[6][i] = val;
49
+ if (matrix[i][6] === null) matrix[i][6] = val;
50
+ }
51
+
52
+ // 3. Alignment patterns for version >= 2
53
+ if (version >= 2) {
54
+ const pos = getAlignmentPositions(version);
55
+ for (const r of pos) {
56
+ for (const c of pos) {
57
+ if (matrix[r][c] === null) {
58
+ addAlignmentPattern(matrix, r - 2, c - 2);
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ // 4. Encode data bytes into bit stream
65
+ const bits: boolean[] = [];
66
+ // Mode indicator: 0100 (8-bit byte mode)
67
+ bits.push(false, true, false, false);
68
+ // Character count indicator (8 bits for version 1-9)
69
+ for (let i = 7; i >= 0; i--) {
70
+ bits.push(((length >> i) & 1) === 1);
71
+ }
72
+ // Data bits
73
+ for (let i = 0; i < length; i++) {
74
+ const code = data.charCodeAt(i);
75
+ for (let b = 7; b >= 0; b--) {
76
+ bits.push(((code >> b) & 1) === 1);
77
+ }
78
+ }
79
+ // Terminator
80
+ for (let i = 0; i < 4 && bits.length % 8 !== 0; i++) {
81
+ bits.push(false);
82
+ }
83
+ while (bits.length % 8 !== 0) {
84
+ bits.push(false);
85
+ }
86
+
87
+ // Add padding bytes (0xEC, 0x11)
88
+ const padBytes = [0xec, 0x11];
89
+ let padIdx = 0;
90
+ const totalDataBits = size * size * 0.6; // approx capacity
91
+ while (bits.length < totalDataBits) {
92
+ const b = padBytes[padIdx % 2];
93
+ padIdx++;
94
+ for (let bit = 7; bit >= 0; bit--) {
95
+ bits.push(((b >> bit) & 1) === 1);
96
+ }
97
+ }
98
+
99
+ // 5. Place data bits in matrix (right to left, zig-zag)
100
+ let bitIdx = 0;
101
+ let upwards = true;
102
+ for (let col = size - 1; col > 0; col -= 2) {
103
+ if (col === 6) col--; // Skip vertical timing column
104
+ const rows = upwards
105
+ ? Array.from({length: size}, (_, i) => size - 1 - i)
106
+ : Array.from({length: size}, (_, i) => i);
107
+
108
+ for (const row of rows) {
109
+ for (const c of [col, col - 1]) {
110
+ if (matrix[row][c] === null) {
111
+ const bit = bitIdx < bits.length ? bits[bitIdx++] : false;
112
+ // Apply mask pattern 0 ((row + col) % 2 === 0)
113
+ const mask = (row + c) % 2 === 0;
114
+ matrix[row][c] = bit !== mask;
115
+ }
116
+ }
117
+ }
118
+ upwards = !upwards;
119
+ }
120
+
121
+ // Replace remaining nulls with false
122
+ return matrix.map(row => row.map(cell => cell ?? false));
123
+ }
124
+
125
+ function addFinderPattern(matrix: (boolean | null)[][], row: number, col: number) {
126
+ for (let r = -1; r <= 7; r++) {
127
+ for (let c = -1; c <= 7; c++) {
128
+ const mr = row + r;
129
+ const mc = col + c;
130
+ if (mr >= 0 && mr < matrix.length && mc >= 0 && mc < matrix.length) {
131
+ if (
132
+ (r >= 0 && r <= 6 && (c === 0 || c === 6)) ||
133
+ (c >= 0 && c <= 6 && (r === 0 || r === 6)) ||
134
+ (r >= 2 && r <= 4 && c >= 2 && c <= 4)
135
+ ) {
136
+ matrix[mr][mc] = true;
137
+ } else if (r >= 0 && r <= 6 && c >= 0 && c <= 6) {
138
+ matrix[mr][mc] = false;
139
+ } else {
140
+ matrix[mr][mc] = false; // separator
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ function addAlignmentPattern(matrix: (boolean | null)[][], row: number, col: number) {
148
+ for (let r = 0; r < 5; r++) {
149
+ for (let c = 0; c < 5; c++) {
150
+ const isOuter = r === 0 || r === 4 || c === 0 || c === 4;
151
+ const isCenter = r === 2 && c === 2;
152
+ matrix[row + r][col + c] = isOuter || isCenter;
153
+ }
154
+ }
155
+ }
156
+
157
+ function getAlignmentPositions(version: number): number[] {
158
+ if (version === 1) return [];
159
+ if (version === 2) return [6, 18];
160
+ if (version === 3) return [6, 22];
161
+ if (version === 4) return [6, 26];
162
+ if (version === 5) return [6, 30];
163
+ if (version === 6) return [6, 34];
164
+ if (version === 7) return [6, 22, 38];
165
+ if (version === 8) return [6, 24, 42];
166
+ if (version === 9) return [6, 26, 46];
167
+ return [6, 28, 50];
168
+ }
169
+
170
+ function createFallbackMatrix(text: string): boolean[][] {
171
+ const size = 25;
172
+ const matrix: boolean[][] = Array(size)
173
+ .fill(false)
174
+ .map(() => Array(size).fill(false));
175
+ addFinderPattern(matrix as any, 0, 0);
176
+ addFinderPattern(matrix as any, size - 7, 0);
177
+ addFinderPattern(matrix as any, 0, size - 7);
178
+ for (let i = 0; i < text.length; i++) {
179
+ const r = (i * 3) % (size - 10) + 8;
180
+ const c = (i * 7) % (size - 10) + 8;
181
+ matrix[r][c] = true;
182
+ }
183
+ return matrix;
184
+ }
package/src/index.tsx CHANGED
@@ -365,6 +365,7 @@ const NetworkInspector = ({
365
365
  crash: false,
366
366
  device: false,
367
367
  storage: false,
368
+ debugging: true,
368
369
  });
369
370
 
370
371
  const [maxNetworkLogs, setMaxNetworkLogs] = useState<number>(100);
@@ -427,6 +428,7 @@ const NetworkInspector = ({
427
428
  crash: false,
428
429
  device: false,
429
430
  storage: false,
431
+ debugging: true,
430
432
  });
431
433
  setDefaultTab('apis');
432
434
  setIsAutoRamLimitEnabled(true);
@@ -12,6 +12,7 @@ export const ActiveTab = {
12
12
  Crash: 'crash',
13
13
  Device: 'device',
14
14
  Storage: 'storage',
15
+ Debugging: 'debugging',
15
16
  } as const;
16
17
  export type ActiveTab = (typeof ActiveTab)[keyof typeof ActiveTab];
17
18
 
@@ -70,6 +71,7 @@ export const SettingsPage = {
70
71
  Crash: 'crash',
71
72
  Device: 'device',
72
73
  Storage: 'storage',
74
+ Debugging: 'debugging',
73
75
  } as const;
74
76
  export type SettingsPage =
75
77
  | (typeof SettingsPage)[keyof typeof SettingsPage]