react-native-inapp-inspector 2.2.3 → 2.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/components/AnalyticsDetail.js +5 -1
- package/dist/commonjs/components/AnalyticsEventCard.js +2 -1
- package/dist/commonjs/components/BrandSquareIcon.js +51 -117
- package/dist/commonjs/components/DiffViewer.js +1 -1
- package/dist/commonjs/components/Inspector/BundleTab.js +22 -0
- package/dist/commonjs/components/Inspector/DeviceInfoTab.d.ts +3 -0
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +835 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +12 -14
- package/dist/commonjs/components/Inspector/LogDetail.js +6 -3
- package/dist/commonjs/components/Inspector/MainScreen.js +7 -3
- package/dist/commonjs/components/Inspector/NetworkTab.js +92 -15
- package/dist/commonjs/components/Inspector/PerformanceTab.js +38 -12
- package/dist/commonjs/components/Inspector/SettingsPanel.js +440 -229
- package/dist/commonjs/components/Inspector/StorageTab.d.ts +3 -0
- package/dist/commonjs/components/Inspector/StorageTab.js +892 -0
- package/dist/commonjs/components/Inspector/TabBar.js +14 -0
- package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +12 -18
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +4 -1
- package/dist/commonjs/components/NetworkIcons.d.ts +6 -0
- package/dist/commonjs/components/NetworkIcons.js +30 -1
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.js +44 -22
- package/dist/commonjs/customHooks/storageInspector.d.ts +67 -0
- package/dist/commonjs/customHooks/storageInspector.js +486 -0
- package/dist/commonjs/i18n/locales/en.json +8 -2
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +16 -1
- package/dist/commonjs/native/NativeInspector.js +50 -26
- package/dist/commonjs/storage.d.ts +5 -0
- package/dist/commonjs/storage.js +18 -0
- package/dist/commonjs/types/enums.d.ts +5 -0
- package/dist/commonjs/types/enums.js +5 -0
- package/dist/esm/components/AnalyticsDetail.js +6 -2
- package/dist/esm/components/AnalyticsEventCard.js +2 -1
- package/dist/esm/components/BrandSquareIcon.js +52 -118
- package/dist/esm/components/DiffViewer.js +1 -1
- package/dist/esm/components/Inspector/BundleTab.js +22 -0
- package/dist/esm/components/Inspector/DeviceInfoTab.d.ts +3 -0
- package/dist/esm/components/Inspector/DeviceInfoTab.js +796 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +13 -15
- package/dist/esm/components/Inspector/LogDetail.js +7 -4
- package/dist/esm/components/Inspector/MainScreen.js +7 -3
- package/dist/esm/components/Inspector/NetworkTab.js +93 -16
- package/dist/esm/components/Inspector/PerformanceTab.js +39 -13
- package/dist/esm/components/Inspector/SettingsPanel.js +441 -230
- package/dist/esm/components/Inspector/StorageTab.d.ts +3 -0
- package/dist/esm/components/Inspector/StorageTab.js +853 -0
- package/dist/esm/components/Inspector/TabBar.js +15 -1
- package/dist/esm/components/Inspector/TelemetryConsentModal.js +12 -18
- package/dist/esm/components/Inspector/UpdateAvailableModal.js +4 -1
- package/dist/esm/components/NetworkIcons.d.ts +6 -0
- package/dist/esm/components/NetworkIcons.js +23 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/bundleAnalyzer.js +44 -22
- package/dist/esm/customHooks/storageInspector.d.ts +67 -0
- package/dist/esm/customHooks/storageInspector.js +469 -0
- package/dist/esm/i18n/locales/en.json +8 -2
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/native/NativeInspector.js +51 -27
- package/dist/esm/storage.d.ts +5 -0
- package/dist/esm/storage.js +5 -0
- package/dist/esm/types/enums.d.ts +5 -0
- package/dist/esm/types/enums.js +5 -0
- package/ios/NetworkInspectorModule.mm +34 -19
- package/package.json +8 -1
- package/src/components/AnalyticsDetail.tsx +6 -1
- package/src/components/AnalyticsEventCard.tsx +2 -1
- package/src/components/BrandSquareIcon.tsx +109 -118
- package/src/components/DiffViewer.tsx +1 -1
- package/src/components/Inspector/BundleTab.tsx +29 -0
- package/src/components/Inspector/DeviceInfoTab.tsx +1204 -0
- package/src/components/Inspector/InspectorHeader.tsx +13 -14
- package/src/components/Inspector/LogDetail.tsx +15 -11
- package/src/components/Inspector/MainScreen.tsx +7 -3
- package/src/components/Inspector/NetworkTab.tsx +104 -16
- package/src/components/Inspector/PerformanceTab.tsx +46 -12
- package/src/components/Inspector/SettingsPanel.tsx +570 -304
- package/src/components/Inspector/StorageTab.tsx +1048 -0
- package/src/components/Inspector/TabBar.tsx +20 -0
- package/src/components/Inspector/TelemetryConsentModal.tsx +17 -52
- package/src/components/Inspector/UpdateAvailableModal.tsx +13 -1
- package/src/components/NetworkIcons.tsx +103 -0
- package/src/constants/version.ts +1 -1
- package/src/customHooks/bundleAnalyzer.ts +47 -22
- package/src/customHooks/storageInspector.ts +509 -0
- package/src/i18n/locales/en.json +8 -2
- package/src/index.tsx +21 -1
- package/src/native/NativeInspector.ts +56 -24
- package/src/storage.ts +18 -0
- package/src/types/enums.ts +5 -0
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
ReduxIcon,
|
|
13
13
|
PerformanceIcon,
|
|
14
14
|
CrashIcon,
|
|
15
|
+
SmartphoneIcon,
|
|
16
|
+
DatabaseIcon,
|
|
15
17
|
} from '../NetworkIcons';
|
|
16
18
|
|
|
17
19
|
import {isReduxConnected} from '../../customHooks/reduxLogger';
|
|
@@ -86,6 +88,18 @@ const TabBar = React.memo(() => {
|
|
|
86
88
|
count: crashRecords?.length || 0,
|
|
87
89
|
icon: 'crash',
|
|
88
90
|
},
|
|
91
|
+
{
|
|
92
|
+
key: 'device',
|
|
93
|
+
label: 'Device',
|
|
94
|
+
count: 0,
|
|
95
|
+
icon: 'device',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
key: 'storage',
|
|
99
|
+
label: 'Storage',
|
|
100
|
+
count: 0,
|
|
101
|
+
icon: 'storage',
|
|
102
|
+
},
|
|
89
103
|
] as const
|
|
90
104
|
)
|
|
91
105
|
.filter(tab => {
|
|
@@ -149,6 +163,12 @@ const TabBar = React.memo(() => {
|
|
|
149
163
|
{tab.icon === 'crash' && (
|
|
150
164
|
<CrashIcon color={iconColor} size={14} />
|
|
151
165
|
)}
|
|
166
|
+
{tab.icon === 'device' && (
|
|
167
|
+
<SmartphoneIcon color={iconColor} size={14} />
|
|
168
|
+
)}
|
|
169
|
+
{tab.icon === 'storage' && (
|
|
170
|
+
<DatabaseIcon color={iconColor} size={14} />
|
|
171
|
+
)}
|
|
152
172
|
<Text
|
|
153
173
|
numberOfLines={1}
|
|
154
174
|
ellipsizeMode="tail"
|
|
@@ -8,59 +8,19 @@ import {
|
|
|
8
8
|
Animated,
|
|
9
9
|
Platform,
|
|
10
10
|
} from 'react-native';
|
|
11
|
-
import Svg, {Path} from 'react-native-svg';
|
|
12
11
|
import {BrandSquareIcon} from '../BrandSquareIcon';
|
|
12
|
+
import {
|
|
13
|
+
SettingsIcon,
|
|
14
|
+
ShieldCheckIcon,
|
|
15
|
+
CheckIcon,
|
|
16
|
+
ClearIcon,
|
|
17
|
+
} from '../NetworkIcons';
|
|
13
18
|
import {
|
|
14
19
|
getTelemetryConsentStatus,
|
|
15
20
|
setTelemetryConsent,
|
|
16
21
|
sendSessionTelemetryPing,
|
|
17
22
|
} from '../../helpers/telemetry';
|
|
18
23
|
|
|
19
|
-
// ─── Inline Crisp SVG Icons ───────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
const ShieldCheckSvg = ({size = 15, color = '#7C3AED'}: {size?: number; color?: string}) => (
|
|
22
|
-
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
23
|
-
<Path
|
|
24
|
-
d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"
|
|
25
|
-
stroke={color}
|
|
26
|
-
strokeWidth="2"
|
|
27
|
-
strokeLinecap="round"
|
|
28
|
-
strokeLinejoin="round"
|
|
29
|
-
/>
|
|
30
|
-
<Path
|
|
31
|
-
d="M9 12l2 2 4-4"
|
|
32
|
-
stroke={color}
|
|
33
|
-
strokeWidth="2"
|
|
34
|
-
strokeLinecap="round"
|
|
35
|
-
strokeLinejoin="round"
|
|
36
|
-
/>
|
|
37
|
-
</Svg>
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
const CheckSvg = ({size = 14, color = '#FFFFFF'}: {size?: number; color?: string}) => (
|
|
41
|
-
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
42
|
-
<Path
|
|
43
|
-
d="M20 6L9 17l-5-5"
|
|
44
|
-
stroke={color}
|
|
45
|
-
strokeWidth="2.4"
|
|
46
|
-
strokeLinecap="round"
|
|
47
|
-
strokeLinejoin="round"
|
|
48
|
-
/>
|
|
49
|
-
</Svg>
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
const CloseSvg = ({size = 13, color = '#64748B'}: {size?: number; color?: string}) => (
|
|
53
|
-
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
54
|
-
<Path
|
|
55
|
-
d="M18 6L6 18M6 6l12 12"
|
|
56
|
-
stroke={color}
|
|
57
|
-
strokeWidth="2.2"
|
|
58
|
-
strokeLinecap="round"
|
|
59
|
-
strokeLinejoin="round"
|
|
60
|
-
/>
|
|
61
|
-
</Svg>
|
|
62
|
-
);
|
|
63
|
-
|
|
64
24
|
export const TelemetryConsentModal = () => {
|
|
65
25
|
const [visible, setVisible] = useState(false);
|
|
66
26
|
const fadeAnim = useState(new Animated.Value(0))[0];
|
|
@@ -136,7 +96,7 @@ export const TelemetryConsentModal = () => {
|
|
|
136
96
|
onPress={() => handleDecision(false)}
|
|
137
97
|
hitSlop={10}
|
|
138
98
|
activeOpacity={0.7}>
|
|
139
|
-
<
|
|
99
|
+
<ClearIcon size={12} color="#64748B" />
|
|
140
100
|
</TouchableOpacity>
|
|
141
101
|
|
|
142
102
|
{/* Centered Enlarged Square Brand Icon Header */}
|
|
@@ -150,8 +110,9 @@ export const TelemetryConsentModal = () => {
|
|
|
150
110
|
|
|
151
111
|
{/* Subheading instruction hint badge */}
|
|
152
112
|
<View style={styles.hintBadge}>
|
|
113
|
+
<SettingsIcon size={12} color="#6366F1" />
|
|
153
114
|
<Text style={styles.hintBadgeText}>
|
|
154
|
-
|
|
115
|
+
You can enable or disable this anytime in Settings
|
|
155
116
|
</Text>
|
|
156
117
|
</View>
|
|
157
118
|
</View>
|
|
@@ -166,7 +127,7 @@ export const TelemetryConsentModal = () => {
|
|
|
166
127
|
{/* Privacy Callout Box */}
|
|
167
128
|
<View style={styles.privacyBadge}>
|
|
168
129
|
<View style={styles.privacyShieldWrapper}>
|
|
169
|
-
<
|
|
130
|
+
<ShieldCheckIcon size={15} color="#7C3AED" />
|
|
170
131
|
</View>
|
|
171
132
|
<Text style={styles.privacyText}>
|
|
172
133
|
<Text style={styles.privacyHighlight}>Privacy Guaranteed:</Text> We
|
|
@@ -181,7 +142,7 @@ export const TelemetryConsentModal = () => {
|
|
|
181
142
|
style={styles.declineButton}
|
|
182
143
|
onPress={() => handleDecision(false)}
|
|
183
144
|
activeOpacity={0.7}>
|
|
184
|
-
<
|
|
145
|
+
<ClearIcon size={12} color="#64748B" />
|
|
185
146
|
<Text style={styles.declineText}>Not Now</Text>
|
|
186
147
|
</TouchableOpacity>
|
|
187
148
|
|
|
@@ -189,7 +150,7 @@ export const TelemetryConsentModal = () => {
|
|
|
189
150
|
style={styles.allowButton}
|
|
190
151
|
onPress={() => handleDecision(true)}
|
|
191
152
|
activeOpacity={0.85}>
|
|
192
|
-
<
|
|
153
|
+
<CheckIcon size={13} color="#FFFFFF" />
|
|
193
154
|
<Text style={styles.allowText}>Allow & Share</Text>
|
|
194
155
|
</TouchableOpacity>
|
|
195
156
|
</View>
|
|
@@ -290,12 +251,16 @@ const styles = StyleSheet.create({
|
|
|
290
251
|
...fontStack,
|
|
291
252
|
},
|
|
292
253
|
hintBadge: {
|
|
254
|
+
flexDirection: 'row',
|
|
255
|
+
alignItems: 'center',
|
|
256
|
+
justifyContent: 'center',
|
|
257
|
+
gap: 5,
|
|
293
258
|
backgroundColor: '#EDE9FE80',
|
|
294
259
|
borderWidth: 1,
|
|
295
260
|
borderColor: '#DDD6FE',
|
|
296
261
|
borderRadius: 7,
|
|
297
262
|
paddingHorizontal: 8,
|
|
298
|
-
paddingVertical:
|
|
263
|
+
paddingVertical: 3,
|
|
299
264
|
marginBottom: 8,
|
|
300
265
|
},
|
|
301
266
|
hintBadgeText: {
|
|
@@ -96,6 +96,18 @@ const SparkleSvg = ({size = 14, color = '#F59E0B'}: {size?: number; color?: stri
|
|
|
96
96
|
</Svg>
|
|
97
97
|
);
|
|
98
98
|
|
|
99
|
+
const ArrowRightSvg = ({size = 14, color = '#94A3B8'}: {size?: number; color?: string}) => (
|
|
100
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
101
|
+
<Path
|
|
102
|
+
d="M5 12h14M12 5l7 7-7 7"
|
|
103
|
+
stroke={color}
|
|
104
|
+
strokeWidth="2.2"
|
|
105
|
+
strokeLinecap="round"
|
|
106
|
+
strokeLinejoin="round"
|
|
107
|
+
/>
|
|
108
|
+
</Svg>
|
|
109
|
+
);
|
|
110
|
+
|
|
99
111
|
interface UpdateAvailableModalProps {
|
|
100
112
|
visible: boolean;
|
|
101
113
|
latestVersion: string | null;
|
|
@@ -215,7 +227,7 @@ export const UpdateAvailableModal: React.FC<UpdateAvailableModalProps> = ({
|
|
|
215
227
|
</View>
|
|
216
228
|
|
|
217
229
|
<View style={styles.arrowContainer}>
|
|
218
|
-
<
|
|
230
|
+
<ArrowRightSvg size={14} color="#94A3B8" />
|
|
219
231
|
</View>
|
|
220
232
|
|
|
221
233
|
<View style={styles.versionColumn}>
|
|
@@ -2116,3 +2116,106 @@ export const ChevronDownIcon = ({color = AppColors.grayTextWeak, size = 14}: Ico
|
|
|
2116
2116
|
</Svg>
|
|
2117
2117
|
);
|
|
2118
2118
|
|
|
2119
|
+
export const CpuIcon = ({
|
|
2120
|
+
color = AppColors.grayTextWeak,
|
|
2121
|
+
size = 14,
|
|
2122
|
+
}: IconProps) => (
|
|
2123
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2124
|
+
<Rect x="4" y="4" width="16" height="16" rx="2" stroke={color} strokeWidth="2" />
|
|
2125
|
+
<Rect x="9" y="9" width="6" height="6" stroke={color} strokeWidth="2" />
|
|
2126
|
+
<Path
|
|
2127
|
+
d="M9 1v3M15 1v3M9 20v3M15 20v3M20 9h3M20 14h3M1 9h3M1 14h3"
|
|
2128
|
+
stroke={color}
|
|
2129
|
+
strokeWidth="2"
|
|
2130
|
+
strokeLinecap="round"
|
|
2131
|
+
/>
|
|
2132
|
+
</Svg>
|
|
2133
|
+
);
|
|
2134
|
+
|
|
2135
|
+
export const WifiIcon = ({
|
|
2136
|
+
color = AppColors.grayTextWeak,
|
|
2137
|
+
size = 14,
|
|
2138
|
+
}: IconProps) => (
|
|
2139
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2140
|
+
<Path
|
|
2141
|
+
d="M5 12.55a11 11 0 0 1 14.08 0M1.42 9a16 16 0 0 1 21.16 0M8.53 16.11a6 6 0 0 1 6.95 0M12 20h.01"
|
|
2142
|
+
stroke={color}
|
|
2143
|
+
strokeWidth="2"
|
|
2144
|
+
strokeLinecap="round"
|
|
2145
|
+
/>
|
|
2146
|
+
</Svg>
|
|
2147
|
+
);
|
|
2148
|
+
|
|
2149
|
+
export const ShieldCheckIcon = ({
|
|
2150
|
+
color = AppColors.grayTextWeak,
|
|
2151
|
+
size = 14,
|
|
2152
|
+
}: IconProps) => (
|
|
2153
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2154
|
+
<Path
|
|
2155
|
+
d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"
|
|
2156
|
+
stroke={color}
|
|
2157
|
+
strokeWidth="2"
|
|
2158
|
+
strokeLinecap="round"
|
|
2159
|
+
strokeLinejoin="round"
|
|
2160
|
+
/>
|
|
2161
|
+
<Path
|
|
2162
|
+
d="M9 12l2 2 4-4"
|
|
2163
|
+
stroke={color}
|
|
2164
|
+
strokeWidth="2"
|
|
2165
|
+
strokeLinecap="round"
|
|
2166
|
+
strokeLinejoin="round"
|
|
2167
|
+
/>
|
|
2168
|
+
</Svg>
|
|
2169
|
+
);
|
|
2170
|
+
|
|
2171
|
+
export const DatabaseIcon = ({
|
|
2172
|
+
color = AppColors.grayTextWeak,
|
|
2173
|
+
size = 14,
|
|
2174
|
+
}: IconProps) => (
|
|
2175
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2176
|
+
<Ellipse cx="12" cy="5" rx="9" ry="3" stroke={color} strokeWidth="2" />
|
|
2177
|
+
<Path
|
|
2178
|
+
d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"
|
|
2179
|
+
stroke={color}
|
|
2180
|
+
strokeWidth="2"
|
|
2181
|
+
strokeLinecap="round"
|
|
2182
|
+
/>
|
|
2183
|
+
<Path
|
|
2184
|
+
d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"
|
|
2185
|
+
stroke={color}
|
|
2186
|
+
strokeWidth="2"
|
|
2187
|
+
strokeLinecap="round"
|
|
2188
|
+
/>
|
|
2189
|
+
</Svg>
|
|
2190
|
+
);
|
|
2191
|
+
|
|
2192
|
+
export const PencilIcon = ({
|
|
2193
|
+
color = AppColors.grayTextWeak,
|
|
2194
|
+
size = 14,
|
|
2195
|
+
}: IconProps) => (
|
|
2196
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2197
|
+
<Path
|
|
2198
|
+
d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"
|
|
2199
|
+
stroke={color}
|
|
2200
|
+
strokeWidth="2"
|
|
2201
|
+
strokeLinecap="round"
|
|
2202
|
+
strokeLinejoin="round"
|
|
2203
|
+
/>
|
|
2204
|
+
</Svg>
|
|
2205
|
+
);
|
|
2206
|
+
|
|
2207
|
+
export const PlusIcon = ({
|
|
2208
|
+
color = AppColors.grayTextWeak,
|
|
2209
|
+
size = 14,
|
|
2210
|
+
}: IconProps) => (
|
|
2211
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
2212
|
+
<Path
|
|
2213
|
+
d="M12 5v14M5 12h14"
|
|
2214
|
+
stroke={color}
|
|
2215
|
+
strokeWidth="2"
|
|
2216
|
+
strokeLinecap="round"
|
|
2217
|
+
strokeLinejoin="round"
|
|
2218
|
+
/>
|
|
2219
|
+
</Svg>
|
|
2220
|
+
);
|
|
2221
|
+
|
package/src/constants/version.ts
CHANGED
|
@@ -120,8 +120,9 @@ export const getBundleModuleEnabled = () => isBundleModuleEnabled;
|
|
|
120
120
|
const getSourceCodeModule = (): any => {
|
|
121
121
|
try {
|
|
122
122
|
const legacy = NativeModules?.SourceCode;
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
const scriptURL = legacy?.scriptURL || legacy?.getConstants?.()?.scriptURL;
|
|
124
|
+
if (typeof scriptURL === 'string' && scriptURL.length > 0) {
|
|
125
|
+
return {scriptURL};
|
|
125
126
|
}
|
|
126
127
|
} catch {}
|
|
127
128
|
try {
|
|
@@ -203,11 +204,11 @@ const extractHostAndPort = (
|
|
|
203
204
|
|
|
204
205
|
const probeCandidateUrlsInParallel = async (
|
|
205
206
|
scriptURL: string,
|
|
206
|
-
timeoutMs =
|
|
207
|
+
timeoutMs = 3000,
|
|
207
208
|
): Promise<{text: string; bytes: number; url: string} | null> => {
|
|
208
209
|
const {host: extractedHost, port: extractedPort} = extractHostAndPort(scriptURL);
|
|
209
210
|
|
|
210
|
-
// 1. If we have a direct scriptURL, try fetching directly
|
|
211
|
+
// 1. If we have a direct HTTP scriptURL, try fetching directly
|
|
211
212
|
if (scriptURL && scriptURL.startsWith('http')) {
|
|
212
213
|
try {
|
|
213
214
|
const controller = new AbortController();
|
|
@@ -227,7 +228,7 @@ const probeCandidateUrlsInParallel = async (
|
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
|
|
230
|
-
// 2. Dynamic Port Discovery via lightweight Metro /status
|
|
231
|
+
// 2. Dynamic Port Discovery via parallel lightweight Metro /status probes
|
|
231
232
|
const candidateHosts = extractedHost
|
|
232
233
|
? [extractedHost, 'localhost', '127.0.0.1', ...(Platform.OS === 'android' ? ['10.0.2.2', '10.0.3.2'] : [])]
|
|
233
234
|
: ['localhost', '127.0.0.1', ...(Platform.OS === 'android' ? ['10.0.2.2', '10.0.3.2'] : [])];
|
|
@@ -237,28 +238,52 @@ const probeCandidateUrlsInParallel = async (
|
|
|
237
238
|
? Array.from(new Set([extractedPort, ...DYNAMIC_DEV_PORTS]))
|
|
238
239
|
: DYNAMIC_DEV_PORTS;
|
|
239
240
|
|
|
240
|
-
|
|
241
|
+
const probeTasks: Promise<{host: string; port: number}>[] = [];
|
|
241
242
|
|
|
242
|
-
// Probe lightweight /status on candidate ports (very fast 400ms timeout)
|
|
243
243
|
for (const host of uniqueHosts) {
|
|
244
244
|
for (const port of candidatePorts) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
245
|
+
probeTasks.push(
|
|
246
|
+
new Promise(async (resolve, reject) => {
|
|
247
|
+
const controller = new AbortController();
|
|
248
|
+
const timer = setTimeout(() => controller.abort(), 700);
|
|
249
|
+
try {
|
|
250
|
+
const res = await fetch(`http://${host}:${port}/status`, {signal: controller.signal});
|
|
251
|
+
clearTimeout(timer);
|
|
252
|
+
if (res.ok) {
|
|
253
|
+
const statusText = await res.text();
|
|
254
|
+
if (statusText && statusText.includes('packager-status:running')) {
|
|
255
|
+
resolve({host, port});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} catch {
|
|
260
|
+
clearTimeout(timer);
|
|
255
261
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
262
|
+
reject(new Error('unreachable'));
|
|
263
|
+
}),
|
|
264
|
+
);
|
|
260
265
|
}
|
|
261
|
-
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
let activeServer: {host: string; port: number} | null = null;
|
|
269
|
+
try {
|
|
270
|
+
activeServer = await new Promise<{host: string; port: number}>((resolve, reject) => {
|
|
271
|
+
let pending = probeTasks.length;
|
|
272
|
+
if (pending === 0) {
|
|
273
|
+
reject(new Error('No candidate hosts'));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
probeTasks.forEach(p => {
|
|
277
|
+
p.then(resolve).catch(() => {
|
|
278
|
+
pending--;
|
|
279
|
+
if (pending === 0) {
|
|
280
|
+
reject(new Error('All probes failed'));
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
} catch {
|
|
286
|
+
activeServer = null;
|
|
262
287
|
}
|
|
263
288
|
|
|
264
289
|
// 3. If a live Metro port was detected dynamically, fetch the bundle from it
|