react-native-debug-toolkit 3.3.3 → 3.3.8

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 (98) hide show
  1. package/README.md +48 -13
  2. package/README.zh-CN.md +48 -13
  3. package/android/src/main/java/com/reactnativedebugtoolkit/DebugToolkitDevConnectModule.java +0 -187
  4. package/bin/debug-toolkit.js +1 -16
  5. package/ios/DebugToolkitDevConnect.h +0 -12
  6. package/ios/DebugToolkitDevConnect.mm +0 -354
  7. package/lib/commonjs/core/initialize.js +8 -1
  8. package/lib/commonjs/core/initialize.js.map +1 -1
  9. package/lib/commonjs/features/devConnect/DevConnectTab.js +18 -470
  10. package/lib/commonjs/features/devConnect/DevConnectTab.js.map +1 -1
  11. package/lib/commonjs/features/devConnect/devConnectPreferences.js +0 -12
  12. package/lib/commonjs/features/devConnect/devConnectPreferences.js.map +1 -1
  13. package/lib/commonjs/features/devConnect/devConnectUtils.js +2 -57
  14. package/lib/commonjs/features/devConnect/devConnectUtils.js.map +1 -1
  15. package/lib/commonjs/features/devConnect/index.js +1 -23
  16. package/lib/commonjs/features/devConnect/index.js.map +1 -1
  17. package/lib/commonjs/features/devConnect/nativeDevConnect.js +1 -103
  18. package/lib/commonjs/features/devConnect/nativeDevConnect.js.map +1 -1
  19. package/lib/commonjs/index.js +7 -0
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/commonjs/ui/DebugView.js +2 -0
  22. package/lib/commonjs/ui/DebugView.js.map +1 -1
  23. package/lib/commonjs/ui/panel/FloatPanelView.js +22 -10
  24. package/lib/commonjs/ui/panel/FloatPanelView.js.map +1 -1
  25. package/lib/commonjs/ui/panel/tabPersistence.js +17 -0
  26. package/lib/commonjs/ui/panel/tabPersistence.js.map +1 -0
  27. package/lib/commonjs/utils/createDebugTab.js +21 -0
  28. package/lib/commonjs/utils/createDebugTab.js.map +1 -0
  29. package/lib/commonjs/utils/debugPreferences.js +0 -1
  30. package/lib/commonjs/utils/debugPreferences.js.map +1 -1
  31. package/lib/module/core/initialize.js +8 -1
  32. package/lib/module/core/initialize.js.map +1 -1
  33. package/lib/module/features/devConnect/DevConnectTab.js +21 -473
  34. package/lib/module/features/devConnect/DevConnectTab.js.map +1 -1
  35. package/lib/module/features/devConnect/devConnectPreferences.js +1 -12
  36. package/lib/module/features/devConnect/devConnectPreferences.js.map +1 -1
  37. package/lib/module/features/devConnect/devConnectUtils.js +1 -53
  38. package/lib/module/features/devConnect/devConnectUtils.js.map +1 -1
  39. package/lib/module/features/devConnect/index.js +5 -9
  40. package/lib/module/features/devConnect/index.js.map +1 -1
  41. package/lib/module/features/devConnect/nativeDevConnect.js +1 -100
  42. package/lib/module/features/devConnect/nativeDevConnect.js.map +1 -1
  43. package/lib/module/index.js +1 -0
  44. package/lib/module/index.js.map +1 -1
  45. package/lib/module/ui/DebugView.js +2 -0
  46. package/lib/module/ui/DebugView.js.map +1 -1
  47. package/lib/module/ui/panel/FloatPanelView.js +22 -10
  48. package/lib/module/ui/panel/FloatPanelView.js.map +1 -1
  49. package/lib/module/ui/panel/tabPersistence.js +13 -0
  50. package/lib/module/ui/panel/tabPersistence.js.map +1 -0
  51. package/lib/module/utils/createDebugTab.js +17 -0
  52. package/lib/module/utils/createDebugTab.js.map +1 -0
  53. package/lib/module/utils/debugPreferences.js +0 -1
  54. package/lib/module/utils/debugPreferences.js.map +1 -1
  55. package/lib/typescript/src/core/initialize.d.ts +2 -0
  56. package/lib/typescript/src/core/initialize.d.ts.map +1 -1
  57. package/lib/typescript/src/features/devConnect/DevConnectTab.d.ts.map +1 -1
  58. package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts +0 -2
  59. package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts.map +1 -1
  60. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts +0 -20
  61. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts.map +1 -1
  62. package/lib/typescript/src/features/devConnect/index.d.ts +2 -2
  63. package/lib/typescript/src/features/devConnect/index.d.ts.map +1 -1
  64. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts +0 -25
  65. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts.map +1 -1
  66. package/lib/typescript/src/features/devConnect/types.d.ts +1 -3
  67. package/lib/typescript/src/features/devConnect/types.d.ts.map +1 -1
  68. package/lib/typescript/src/index.d.ts +2 -0
  69. package/lib/typescript/src/index.d.ts.map +1 -1
  70. package/lib/typescript/src/ui/DebugView.d.ts +4 -2
  71. package/lib/typescript/src/ui/DebugView.d.ts.map +1 -1
  72. package/lib/typescript/src/ui/panel/FloatPanelView.d.ts.map +1 -1
  73. package/lib/typescript/src/ui/panel/tabPersistence.d.ts +3 -0
  74. package/lib/typescript/src/ui/panel/tabPersistence.d.ts.map +1 -0
  75. package/lib/typescript/src/utils/createDebugTab.d.ts +18 -0
  76. package/lib/typescript/src/utils/createDebugTab.d.ts.map +1 -0
  77. package/lib/typescript/src/utils/debugPreferences.d.ts +0 -1
  78. package/lib/typescript/src/utils/debugPreferences.d.ts.map +1 -1
  79. package/package.json +2 -4
  80. package/src/core/initialize.ts +17 -1
  81. package/src/features/devConnect/DevConnectTab.tsx +17 -381
  82. package/src/features/devConnect/devConnectPreferences.ts +0 -15
  83. package/src/features/devConnect/devConnectUtils.ts +1 -81
  84. package/src/features/devConnect/index.ts +2 -9
  85. package/src/features/devConnect/nativeDevConnect.ts +1 -136
  86. package/src/features/devConnect/types.ts +1 -3
  87. package/src/index.ts +2 -0
  88. package/src/ui/DebugView.tsx +5 -1
  89. package/src/ui/panel/FloatPanelView.tsx +22 -10
  90. package/src/ui/panel/tabPersistence.ts +22 -0
  91. package/src/utils/createDebugTab.ts +32 -0
  92. package/src/utils/debugPreferences.ts +0 -1
  93. package/scripts/android-debug-bundle.gradle +0 -23
  94. package/scripts/eas-postinstall.sh +0 -6
  95. package/scripts/embed-android.js +0 -116
  96. package/scripts/embed-expo.js +0 -109
  97. package/scripts/embed-ios.js +0 -119
  98. package/scripts/embed.js +0 -224
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import {
3
3
  KeyboardAvoidingView,
4
4
  Platform,
@@ -21,10 +21,7 @@ import {
21
21
  } from '../../utils/DaemonClient';
22
22
  import {
23
23
  DEFAULT_DAEMON_PORT,
24
- DEFAULT_METRO_PORT,
25
24
  buildDaemonDeviceHost,
26
- buildMetroTarget,
27
- buildMetroUrls,
28
25
  normalizeComputerHost,
29
26
  normalizePort,
30
27
  parseComputerTarget,
@@ -33,52 +30,25 @@ import {
33
30
  saveComputerHost,
34
31
  saveComputerTarget,
35
32
  saveDaemonPort,
36
- saveMetroPort,
37
33
  } from './devConnectPreferences';
38
- import {
39
- applyMetroBundle,
40
- getNativeDiagnostics,
41
- resetMetroBundle,
42
- type NativeDiagnostics,
43
- } from './nativeDevConnect';
44
34
  import type { DevConnectFeatureControls, DevConnectSettingsPatch, DevConnectState } from './types';
45
35
 
46
36
  const CONNECTION_TIMEOUT_MS = 2000;
47
37
 
48
38
  type SyncUiState = 'idle' | 'checking' | 'connected' | 'retrying' | 'failed' | 'running';
49
39
 
50
- function getSimulatorMetroHost(): string {
40
+ function getSimulatorHost(): string {
51
41
  return Platform.OS === 'android' ? '10.0.2.2' : 'localhost';
52
42
  }
53
43
 
54
- function describeMetroFailure(result: { reason: string; error?: string }): string {
55
- if (result.reason === 'native_unavailable') {
56
- return 'Native DevConnect not installed. Rebuild app after installing native module.';
57
- }
58
- if (result.reason === 'metro_unreachable') {
59
- return result.error ? `Metro not reachable: ${result.error}` : 'Metro not reachable. Start Metro on that port.';
60
- }
61
- if (result.reason === 'fetch_unavailable') {
62
- return 'Cannot check Metro because fetch is unavailable.';
63
- }
64
- if (result.reason === 'invalid_target') {
65
- return 'Enter a valid computer IP and Metro port.';
66
- }
67
- return result.error ? `Metro switch failed: ${result.error}` : 'Metro switch failed.';
68
- }
69
-
70
44
  export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<DevConnectState>) {
71
45
  const inputRef = useRef<TextInput>(null);
72
46
  const [computerHost, setComputerHost] = useState(snapshot.computerHost);
73
- const [metroPort, setMetroPort] = useState(snapshot.metroPort);
74
47
  const [daemonPort, setDaemonPort] = useState(snapshot.daemonPort);
75
48
  const [streaming, setStreaming] = useState(snapshot.streaming);
76
49
  const [syncState, setSyncState] = useState<SyncUiState>(snapshot.streaming ? 'running' : 'idle');
77
50
  const [message, setMessage] = useState<string | null>(null);
78
51
  const [sending, setSending] = useState(false);
79
- const [metroBusy, setMetroBusy] = useState(false);
80
- const [diagData, setDiagData] = useState<NativeDiagnostics | null>(null);
81
- const [diagOpen, setDiagOpen] = useState(false);
82
52
 
83
53
  const isSim = snapshot.isSimulator;
84
54
 
@@ -86,31 +56,10 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
86
56
  (feature as unknown as DevConnectFeatureControls).updateSettings?.(patch);
87
57
  }, [feature]);
88
58
 
89
- useEffect(() => {
90
- getNativeDiagnostics().then((result) => {
91
- if (result) {
92
- setDiagData(result);
93
- console.info(
94
- `[DevConnect] debugBuild=${result.isDebugBuild} appDelegate=${result.appDelegateClass} persistedHost=${result.persistedMetroHost ?? 'none'}`,
95
- );
96
- }
97
- }).catch(() => {});
98
- }, []);
99
-
100
- const refreshDiag = useCallback(() => {
101
- getNativeDiagnostics().then((result) => {
102
- if (result) setDiagData(result);
103
- }).catch(() => {});
104
- }, []);
105
-
106
59
  useEffect(() => {
107
60
  setComputerHost(snapshot.computerHost);
108
61
  }, [snapshot.computerHost]);
109
62
 
110
- useEffect(() => {
111
- setMetroPort(snapshot.metroPort);
112
- }, [snapshot.metroPort]);
113
-
114
63
  useEffect(() => {
115
64
  setDaemonPort(snapshot.daemonPort);
116
65
  }, [snapshot.daemonPort]);
@@ -120,27 +69,15 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
120
69
  setSyncState(snapshot.streaming ? 'running' : 'idle');
121
70
  }, [snapshot.streaming]);
122
71
 
123
- const metroHost = isSim ? getSimulatorMetroHost() : computerHost;
124
- const metroTarget = useMemo(
125
- () => buildMetroTarget(metroHost, metroPort),
126
- [metroHost, metroPort],
127
- );
128
- const metroUrls = useMemo(
129
- () => buildMetroUrls(metroHost, metroPort),
130
- [metroHost, metroPort],
131
- );
132
-
133
72
  const handleHostChange = useCallback((value: string) => {
134
73
  setComputerHost(value);
135
74
  const target = parseComputerTarget(value);
136
75
  if (target) {
137
- setMetroPort(target.metroPort);
138
76
  saveComputerTarget(value)
139
77
  .then((savedTarget) => {
140
78
  if (savedTarget) {
141
79
  updateFeatureSettings({
142
80
  computerHost: savedTarget.computerHost,
143
- metroPort: savedTarget.metroPort,
144
81
  });
145
82
  }
146
83
  })
@@ -150,17 +87,6 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
150
87
  setMessage(null);
151
88
  }, [updateFeatureSettings]);
152
89
 
153
- const handleMetroPortChange = useCallback((value: string) => {
154
- setMetroPort(value);
155
- const normalized = normalizePort(value);
156
- if (normalized) {
157
- saveMetroPort(normalized)
158
- .then(() => updateFeatureSettings({ metroPort: normalized }))
159
- .catch(() => {});
160
- }
161
- setMessage(null);
162
- }, [updateFeatureSettings]);
163
-
164
90
  const handleDaemonPortChange = useCallback((value: string) => {
165
91
  setDaemonPort(value);
166
92
  const normalized = normalizePort(value);
@@ -194,38 +120,10 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
194
120
  setComputerHost(normalizedHost);
195
121
  }
196
122
 
197
- const normalizedMetroPort = normalizePort(metroPort);
198
- if (normalizedMetroPort) {
199
- patch.metroPort = normalizedMetroPort;
200
- writes.push(saveMetroPort(normalizedMetroPort));
201
- setMetroPort(normalizedMetroPort);
202
- }
203
-
204
- await Promise.all(writes);
205
- updateFeatureSettings(patch);
206
- return true;
207
- }, [computerHost, daemonPort, isSim, metroPort, updateFeatureSettings]);
208
-
209
- const persistMetroSettings = useCallback(async (): Promise<boolean> => {
210
- if (!metroTarget) {
211
- setMessage('Enter a valid computer IP and Metro port.');
212
- return false;
213
- }
214
-
215
- const patch: DevConnectSettingsPatch = { metroPort: metroTarget.port };
216
- const writes: Array<Promise<unknown>> = [saveMetroPort(metroTarget.port)];
217
- setMetroPort(metroTarget.port);
218
-
219
- if (!isSim) {
220
- patch.computerHost = metroTarget.host;
221
- writes.push(saveComputerTarget(metroTarget.hostPort));
222
- setComputerHost(metroTarget.host);
223
- }
224
-
225
123
  await Promise.all(writes);
226
124
  updateFeatureSettings(patch);
227
125
  return true;
228
- }, [isSim, metroTarget, updateFeatureSettings]);
126
+ }, [computerHost, daemonPort, isSim, updateFeatureSettings]);
229
127
 
230
128
  const validateSettings = useCallback((): boolean => {
231
129
  if (!isSim && !normalizeComputerHost(computerHost)) {
@@ -350,57 +248,7 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
350
248
  }
351
249
  }, [configureDaemon, persistConnectionSettings, validateSettings]);
352
250
 
353
- const applyRemoteBundle = useCallback(async () => {
354
- if (!metroTarget) {
355
- setMessage('Enter a valid computer IP and Metro port.');
356
- return;
357
- }
358
- if (!snapshot.nativeMetroAvailable) {
359
- setMessage(describeMetroFailure({ reason: 'native_unavailable' }));
360
- return;
361
- }
362
-
363
- setMetroBusy(true);
364
- setMessage('Checking Metro...');
365
- try {
366
- if (!(await persistMetroSettings())) {
367
- return;
368
- }
369
- const result = await applyMetroBundle(metroTarget.host, metroTarget.port);
370
- if (result.ok) {
371
- setMessage(`Using Metro at ${result.hostPort}. Reloading...`);
372
- } else {
373
- setMessage(describeMetroFailure(result));
374
- }
375
- } finally {
376
- setMetroBusy(false);
377
- }
378
- }, [metroTarget, persistMetroSettings, snapshot.nativeMetroAvailable]);
379
-
380
- const resetRemoteBundle = useCallback(async () => {
381
- if (!snapshot.nativeMetroAvailable) {
382
- setMessage(describeMetroFailure({ reason: 'native_unavailable' }));
383
- return;
384
- }
385
-
386
- setMetroBusy(true);
387
- try {
388
- const result = await resetMetroBundle();
389
- if (result.ok) {
390
- setMessage('Metro host reset. Reloading...');
391
- } else {
392
- setMessage(describeMetroFailure(result));
393
- }
394
- } finally {
395
- setMetroBusy(false);
396
- }
397
- }, [snapshot.nativeMetroAvailable]);
398
-
399
- // Metro host switching only works in Debug builds. diagData is iOS-populated; when we know
400
- // it's a Release build, disable the controls (Android reports null → stays enabled).
401
- const metroReleaseBlocked = diagData ? !diagData.isDebugBuild : false;
402
251
  const canConnect = isSim || (Boolean(normalizeComputerHost(computerHost)) && Boolean(normalizePort(daemonPort)));
403
- const canUseMetro = Boolean(metroTarget) && snapshot.nativeMetroAvailable && !metroBusy && !metroReleaseBlocked;
404
252
  const busy = sending || syncState === 'checking';
405
253
  const subnetPrefix = snapshot.subnetPrefix;
406
254
  const ipPlaceholder = subnetPrefix ? `${subnetPrefix}...` : '192.168.1.10';
@@ -411,7 +259,7 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
411
259
 
412
260
  {isSim ? (
413
261
  <View style={styles.badge}>
414
- <Text style={styles.badgeText}>Simulator/emulator - using {getSimulatorMetroHost()}</Text>
262
+ <Text style={styles.badgeText}>Simulator/emulator - using {getSimulatorHost()}</Text>
415
263
  </View>
416
264
  ) : (
417
265
  <View style={styles.section}>
@@ -448,36 +296,19 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
448
296
  )}
449
297
 
450
298
  <View style={styles.section}>
451
- <Text style={styles.label}>Ports</Text>
452
- <View style={styles.portRow}>
453
- <View style={styles.portField}>
454
- <Text style={styles.portLabel}>Metro</Text>
455
- <TextInput
456
- style={styles.portInput}
457
- value={metroPort}
458
- onChangeText={handleMetroPortChange}
459
- placeholder={DEFAULT_METRO_PORT}
460
- placeholderTextColor={Colors.textLight}
461
- autoCapitalize="none"
462
- autoCorrect={false}
463
- keyboardType="number-pad"
464
- returnKeyType="done"
465
- />
466
- </View>
467
- <View style={styles.portField}>
468
- <Text style={styles.portLabel}>Logs</Text>
469
- <TextInput
470
- style={styles.portInput}
471
- value={daemonPort}
472
- onChangeText={handleDaemonPortChange}
473
- placeholder={DEFAULT_DAEMON_PORT}
474
- placeholderTextColor={Colors.textLight}
475
- autoCapitalize="none"
476
- autoCorrect={false}
477
- keyboardType="number-pad"
478
- returnKeyType="done"
479
- />
480
- </View>
299
+ <Text style={styles.label}>Desktop Logs Port</Text>
300
+ <View style={styles.inputRow}>
301
+ <TextInput
302
+ style={styles.input}
303
+ value={daemonPort}
304
+ onChangeText={handleDaemonPortChange}
305
+ placeholder={DEFAULT_DAEMON_PORT}
306
+ placeholderTextColor={Colors.textLight}
307
+ autoCapitalize="none"
308
+ autoCorrect={false}
309
+ keyboardType="number-pad"
310
+ returnKeyType="done"
311
+ />
481
312
  </View>
482
313
  </View>
483
314
 
@@ -505,129 +336,6 @@ export function DevConnectTab({ snapshot, feature }: DebugFeatureRenderProps<Dev
505
336
  </View>
506
337
 
507
338
  {message ? <Text style={styles.message}>{message}</Text> : null}
508
-
509
- <View style={styles.section}>
510
- <View style={styles.sectionTitleRow}>
511
- <Text style={styles.sectionTitle}>Remote JS Bundle</Text>
512
- {diagData ? (
513
- <View style={styles.swizzleBadge}>
514
- <View style={[styles.swizzleDot, diagData.isDebugBuild ? styles.dotGreen : styles.dotRed]} />
515
- <Text style={styles.swizzleBadgeText}>
516
- {diagData.isDebugBuild ? 'debug build' : 'release: disabled'}
517
- </Text>
518
- </View>
519
- ) : null}
520
- </View>
521
- <Text style={styles.sectionDesc}>
522
- Starts from the embedded bundle. After you apply a computer IP, hot-reloads from that
523
- Metro. Debug builds only — use Reset to go back to the embedded bundle.
524
- </Text>
525
-
526
- {!metroUrls ? (
527
- <View style={styles.stepCard}>
528
- <Text style={styles.stepHint}>Enter your computer IP and Metro port to get started.</Text>
529
- </View>
530
- ) : (
531
- <View style={styles.stepCard}>
532
- <View style={styles.urlRow}>
533
- <Text style={styles.urlLabel}>HTTP</Text>
534
- <Text style={styles.urlText} numberOfLines={1}>{metroUrls.httpUrl}</Text>
535
- </View>
536
- <View style={styles.urlRow}>
537
- <Text style={styles.urlLabel}>Expo</Text>
538
- <Text style={styles.urlText} numberOfLines={1}>{metroUrls.expUrl}</Text>
539
- </View>
540
- </View>
541
- )}
542
-
543
- <View style={styles.actions}>
544
- <TouchableOpacity
545
- style={[styles.primaryButton, !canUseMetro && styles.buttonDisabled]}
546
- onPress={applyRemoteBundle}
547
- disabled={!canUseMetro}
548
- activeOpacity={0.75}
549
- >
550
- <Text style={styles.primaryButtonText}>
551
- {metroBusy ? 'Checking...' : 'Use Metro Bundle'}
552
- </Text>
553
- </TouchableOpacity>
554
- <TouchableOpacity
555
- style={[styles.secondaryButton, (!snapshot.nativeMetroAvailable || metroBusy) && styles.buttonDisabled]}
556
- onPress={resetRemoteBundle}
557
- disabled={!snapshot.nativeMetroAvailable || metroBusy}
558
- activeOpacity={0.75}
559
- >
560
- <Text style={styles.secondaryButtonText}>Reset</Text>
561
- </TouchableOpacity>
562
- </View>
563
-
564
- {!snapshot.nativeMetroAvailable ? (
565
- <Text style={styles.hint}>Native DevConnect requires pod install / Gradle sync and app rebuild.</Text>
566
- ) : null}
567
-
568
- {metroReleaseBlocked ? (
569
- <Text style={styles.diagWarning}>
570
- ⚠ This is a Release build. Metro host switching is disabled — RN loads the embedded
571
- bundle and strips the packager machinery in Release. Run a Debug build to switch hosts.
572
- </Text>
573
- ) : null}
574
- </View>
575
-
576
- {snapshot.nativeMetroAvailable && diagData ? (
577
- <View style={styles.section}>
578
- <TouchableOpacity
579
- style={styles.diagHeader}
580
- onPress={() => { setDiagOpen((v) => !v); refreshDiag(); }}
581
- activeOpacity={0.7}
582
- >
583
- <Text style={styles.sectionTitle}>iOS Bundle Status</Text>
584
- <Text style={styles.diagChevron}>{diagOpen ? '▲' : '▼'}</Text>
585
- </TouchableOpacity>
586
-
587
- {diagOpen ? (
588
- <View style={styles.diagCard}>
589
- <View style={styles.diagRow}>
590
- <Text style={styles.diagKey}>AppDelegate</Text>
591
- <Text style={styles.diagVal}>{diagData.appDelegateClass}</Text>
592
- </View>
593
- <View style={styles.diagRow}>
594
- <Text style={styles.diagKey}>packagerHost</Text>
595
- <Text style={styles.diagVal}>{diagData.persistedMetroHost ?? '—'}</Text>
596
- </View>
597
- <View style={styles.diagRow}>
598
- <Text style={styles.diagKey}>embedded</Text>
599
- <Text style={[styles.diagVal, diagData.hasEmbeddedBundle ? styles.diagGood : styles.diagWarn]}>
600
- {diagData.hasEmbeddedBundle ? 'main.jsbundle' : 'missing'}
601
- </Text>
602
- </View>
603
- <View style={styles.diagRow}>
604
- <Text style={styles.diagKey}>build</Text>
605
- <Text style={[styles.diagVal, diagData.isDebugBuild ? styles.diagGood : styles.diagWarn]}>
606
- {diagData.isDebugBuild ? 'Debug' : 'Release'}
607
- </Text>
608
- </View>
609
- <View style={styles.diagRow}>
610
- <Text style={styles.diagKey}>embedded-first</Text>
611
- <Text style={[styles.diagVal, diagData.embeddedFirstHookInstalled ? styles.diagGood : styles.diagWarn]}>
612
- {diagData.embeddedFirstHookInstalled ? 'active' : 'inactive'}
613
- </Text>
614
- </View>
615
- {!diagData.embeddedFirstHookInstalled ? (
616
- <Text style={styles.diagWarning}>
617
- ⚠ Embedded-first hook not active (bundleRoot=
618
- {diagData.bundleRootHookInstalled ? 'Y' : 'N'}). Rebuild after pod install.
619
- Without it, Debug may still try Metro on launch.
620
- </Text>
621
- ) : diagData.hasEmbeddedBundle === false ? (
622
- <Text style={styles.diagWarning}>
623
- ⚠ main.jsbundle is missing from the app package. Build with an embedded bundle
624
- (e.g. export/bundle) or cold start cannot use offline JS.
625
- </Text>
626
- ) : null}
627
- </View>
628
- ) : null}
629
- </View>
630
- ) : null}
631
339
  </ScrollView>
632
340
  </KeyboardAvoidingView>
633
341
  );
@@ -647,8 +355,6 @@ const styles = StyleSheet.create({
647
355
  },
648
356
  badgeText: { fontSize: 13, fontWeight: '500', color: Colors.primary },
649
357
  section: { marginBottom: 14 },
650
- sectionTitle: { fontSize: 14, fontWeight: '600', color: Colors.text, marginBottom: 4 },
651
- sectionDesc: { fontSize: 12, color: Colors.textSecondary, marginBottom: 10, lineHeight: 17 },
652
358
  label: { fontSize: 13, fontWeight: '500', color: Colors.textSecondary, marginBottom: 6 },
653
359
  inputRow: { flexDirection: 'row', alignItems: 'center' },
654
360
  subnetHint: { marginTop: 6 },
@@ -665,20 +371,6 @@ const styles = StyleSheet.create({
665
371
  color: Colors.text,
666
372
  fontFamily: 'Courier',
667
373
  },
668
- portRow: { flexDirection: 'row', gap: 10 },
669
- portField: { flex: 1 },
670
- portLabel: { fontSize: 11, color: Colors.textSecondary, marginBottom: 4 },
671
- portInput: {
672
- backgroundColor: Colors.surface,
673
- borderWidth: 1,
674
- borderColor: Colors.border,
675
- borderRadius: 8,
676
- paddingHorizontal: 12,
677
- paddingVertical: 9,
678
- fontSize: 13,
679
- color: Colors.text,
680
- fontFamily: 'Courier',
681
- },
682
374
  actions: { flexDirection: 'row', gap: 10, marginTop: 4, marginBottom: 12 },
683
375
  primaryButton: {
684
376
  flex: 1,
@@ -702,60 +394,4 @@ const styles = StyleSheet.create({
702
394
  secondaryButtonText: { color: Colors.primary, fontSize: 14, fontWeight: '600' },
703
395
  buttonDisabled: { opacity: 0.5 },
704
396
  message: { fontSize: 12, lineHeight: 17, color: Colors.textSecondary, marginBottom: 12 },
705
- hint: { fontSize: 12, color: Colors.textLight, lineHeight: 17 },
706
- stepCard: {
707
- backgroundColor: Colors.surface,
708
- borderWidth: 1,
709
- borderColor: Colors.border,
710
- borderRadius: 10,
711
- padding: 12,
712
- marginBottom: 8,
713
- },
714
- stepHint: { fontSize: 12, color: Colors.textSecondary, lineHeight: 17 },
715
- urlLabel: {
716
- minWidth: 40,
717
- fontSize: 10,
718
- fontWeight: '600',
719
- color: Colors.primary,
720
- backgroundColor: `${Colors.primary}15`,
721
- paddingHorizontal: 6,
722
- paddingVertical: 2,
723
- borderRadius: 4,
724
- marginRight: 8,
725
- textAlign: 'center',
726
- },
727
- urlRow: {
728
- flexDirection: 'row',
729
- alignItems: 'center',
730
- borderBottomWidth: StyleSheet.hairlineWidth,
731
- borderBottomColor: Colors.border,
732
- paddingVertical: 7,
733
- },
734
- urlText: { flex: 1, fontSize: 13, fontFamily: 'Courier', color: Colors.text },
735
- sectionTitleRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 4 },
736
- swizzleBadge: { flexDirection: 'row', alignItems: 'center', gap: 4, paddingHorizontal: 7, paddingVertical: 3, borderRadius: 10, backgroundColor: Colors.surface, borderWidth: 1, borderColor: Colors.border },
737
- swizzleDot: { width: 6, height: 6, borderRadius: 3 },
738
- dotGreen: { backgroundColor: '#34C759' },
739
- dotRed: { backgroundColor: '#FF3B30' },
740
- swizzleBadgeText: { fontSize: 11, color: Colors.textSecondary, fontFamily: 'Courier' },
741
- diagHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 },
742
- diagChevron: { fontSize: 12, color: Colors.textSecondary },
743
- diagCard: {
744
- backgroundColor: Colors.surface,
745
- borderWidth: 1,
746
- borderColor: Colors.border,
747
- borderRadius: 10,
748
- padding: 10,
749
- },
750
- diagRow: { flexDirection: 'row', justifyContent: 'space-between', paddingVertical: 4 },
751
- diagKey: { fontSize: 12, color: Colors.textSecondary, fontFamily: 'Courier' },
752
- diagVal: { fontSize: 12, color: Colors.text, fontFamily: 'Courier', fontWeight: '600' },
753
- diagGood: { color: '#34C759' },
754
- diagWarn: { color: '#FF9500' },
755
- diagWarning: {
756
- marginTop: 10,
757
- fontSize: 11,
758
- color: '#FF9500',
759
- lineHeight: 16,
760
- },
761
397
  });
@@ -2,7 +2,6 @@ import { daemonClient } from '../../utils/DaemonClient';
2
2
  import { getPreference, KEYS, setPreference } from '../../utils/debugPreferences';
3
3
  import {
4
4
  DEFAULT_DAEMON_PORT,
5
- DEFAULT_METRO_PORT,
6
5
  buildDaemonDeviceHost,
7
6
  normalizeComputerHost,
8
7
  normalizePort,
@@ -13,17 +12,14 @@ import { isSimulator } from './platformDetect';
13
12
 
14
13
  export interface DevConnectPreferences {
15
14
  computerHost: string;
16
- metroPort: string;
17
15
  daemonPort: string;
18
16
  }
19
17
 
20
18
  export async function loadDevConnectPreferences(): Promise<DevConnectPreferences> {
21
19
  const storedHost = await getPreference(KEYS.computerHost);
22
- const storedMetroPort = await getPreference(KEYS.metroPort);
23
20
  const storedDaemonPort = await getPreference(KEYS.daemonPort);
24
21
  return {
25
22
  computerHost: storedHost ? normalizeComputerHost(storedHost) ?? '' : '',
26
- metroPort: storedMetroPort ? normalizePort(storedMetroPort) ?? DEFAULT_METRO_PORT : DEFAULT_METRO_PORT,
27
23
  daemonPort: storedDaemonPort ? normalizePort(storedDaemonPort) ?? DEFAULT_DAEMON_PORT : DEFAULT_DAEMON_PORT,
28
24
  };
29
25
  }
@@ -35,7 +31,6 @@ export async function saveComputerTarget(value: string): Promise<ParsedComputerT
35
31
  }
36
32
 
37
33
  await setPreference(KEYS.computerHost, target.computerHost);
38
- await setPreference(KEYS.metroPort, target.metroPort);
39
34
  return target;
40
35
  }
41
36
 
@@ -49,16 +44,6 @@ export async function saveComputerHost(value: string): Promise<string | null> {
49
44
  return host;
50
45
  }
51
46
 
52
- export async function saveMetroPort(value: string): Promise<string | null> {
53
- const normalized = normalizePort(value);
54
- if (!normalized) {
55
- return null;
56
- }
57
-
58
- await setPreference(KEYS.metroPort, normalized);
59
- return normalized;
60
- }
61
-
62
47
  export async function saveDaemonPort(value: string): Promise<string | null> {
63
48
  const normalized = normalizePort(value);
64
49
  if (!normalized) {
@@ -1,27 +1,7 @@
1
- export const DEFAULT_METRO_PORT = '8081';
2
1
  export const DEFAULT_DAEMON_PORT = '3799';
3
2
 
4
- export interface MetroUrls {
5
- expUrl: string;
6
- httpUrl: string;
7
- }
8
-
9
- export interface MetroTarget {
10
- host: string;
11
- port: string;
12
- hostPort: string;
13
- statusUrl: string;
14
- }
15
-
16
3
  export interface ParsedComputerTarget {
17
4
  computerHost: string;
18
- metroPort: string;
19
- }
20
-
21
- export interface ParsedMetroQrPayload {
22
- computerHost: string;
23
- metroPort: string;
24
- source: string;
25
5
  }
26
6
 
27
7
  function isValidIpv4(host: string): boolean {
@@ -92,67 +72,7 @@ export function parseComputerTarget(raw: string): ParsedComputerTarget | null {
92
72
  return null;
93
73
  }
94
74
 
95
- const metroPort = parsed.port
96
- ? normalizePort(parsed.port)
97
- : DEFAULT_METRO_PORT;
98
- if (!metroPort) {
99
- return null;
100
- }
101
-
102
- return {
103
- computerHost: parsed.host,
104
- metroPort,
105
- };
106
- }
107
-
108
- function normalizeMetroHost(rawHost: string): string | null {
109
- const parsed = parseHostAndPort(rawHost);
110
- if (!parsed) {
111
- return null;
112
- }
113
- if (parsed.host === 'localhost') {
114
- return parsed.host;
115
- }
116
- return isValidIpv4(parsed.host) ? parsed.host : null;
117
- }
118
-
119
- export function buildMetroTarget(rawHost: string, rawPort = DEFAULT_METRO_PORT): MetroTarget | null {
120
- const host = normalizeMetroHost(rawHost);
121
- if (!host) {
122
- return null;
123
- }
124
-
125
- const port = normalizePort(rawPort);
126
- if (!port) {
127
- return null;
128
- }
129
-
130
- return {
131
- host,
132
- port,
133
- hostPort: `${host}:${port}`,
134
- statusUrl: `http://${host}:${port}/status`,
135
- };
136
- }
137
-
138
- export function buildMetroUrls(rawHost: string, rawPort = DEFAULT_METRO_PORT): MetroUrls | null {
139
- const target = buildMetroTarget(rawHost, rawPort);
140
- if (!target) {
141
- return null;
142
- }
143
-
144
- return {
145
- expUrl: `exp://${target.hostPort}`,
146
- httpUrl: `http://${target.hostPort}`,
147
- };
148
- }
149
-
150
- export function parseMetroQrPayload(payload: string): ParsedMetroQrPayload | null {
151
- const target = parseComputerTarget(payload);
152
- if (!target) {
153
- return null;
154
- }
155
- return { ...target, source: payload };
75
+ return { computerHost: parsed.host };
156
76
  }
157
77
 
158
78
  export function buildDaemonDeviceHost(computerHost: string, daemonPort: string): string {