react-native-inapp-inspector 1.0.18 → 1.1.1
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/README.md +42 -40
- package/dist/commonjs/components/ReduxTreeView.d.ts +4 -0
- package/dist/commonjs/components/ReduxTreeView.js +35 -5
- package/dist/commonjs/constants/index.d.ts +1 -0
- package/dist/commonjs/constants/index.js +5 -1
- package/dist/commonjs/constants/version.d.ts +1 -0
- package/dist/commonjs/constants/version.js +6 -0
- package/dist/commonjs/customHooks/reduxLogger.js +9 -1
- package/dist/commonjs/index.js +488 -40
- package/dist/esm/components/ReduxTreeView.d.ts +4 -0
- package/dist/esm/components/ReduxTreeView.js +30 -4
- package/dist/esm/constants/index.d.ts +1 -0
- package/dist/esm/constants/index.js +3 -0
- package/dist/esm/constants/version.d.ts +1 -0
- package/dist/esm/constants/version.js +3 -0
- package/dist/esm/customHooks/reduxLogger.js +9 -1
- package/dist/esm/index.js +490 -42
- package/example/ios/example.xcodeproj/project.pbxproj +10 -0
- package/package.json +3 -2
package/dist/esm/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import CopyButton from './components/CopyButton';
|
|
|
11
11
|
import SectionHeader from './components/SectionHeader';
|
|
12
12
|
import EmptyState from './components/EmptyState';
|
|
13
13
|
import JsonViewer from './components/JsonViewer';
|
|
14
|
-
import { ReduxTreeView, ReduxActionTimeline } from './components/ReduxTreeView';
|
|
14
|
+
import { ReduxTreeView, ReduxActionTimeline, ReduxTimelineIcon, ReduxTreeIcon, } from './components/ReduxTreeView';
|
|
15
15
|
import DomainHeader from './components/DomainHeader';
|
|
16
16
|
import DiffViewer from './components/DiffViewer';
|
|
17
17
|
import LogCard from './components/LogCard';
|
|
@@ -100,7 +100,7 @@ const previewInspectScript = `
|
|
|
100
100
|
true;
|
|
101
101
|
`;
|
|
102
102
|
import { getReduxState, subscribeReduxState, setReduxAutoRefresh, getLastActionForReducer, getActionHistory, clearActionHistory, } from './customHooks/reduxLogger';
|
|
103
|
-
import { METHOD_COLORS, STATUS_FILTERS } from './constants';
|
|
103
|
+
import { METHOD_COLORS, STATUS_FILTERS, LIB_VERSION } from './constants';
|
|
104
104
|
const NavigationTracker = ({ onStateChange }) => {
|
|
105
105
|
const navState = useNavigationState(state => state);
|
|
106
106
|
useEffect(() => {
|
|
@@ -114,6 +114,12 @@ const animateNextLayout = () => {
|
|
|
114
114
|
const NetworkInspector = ({ enabled = true, }) => {
|
|
115
115
|
const [isDark, setIsDark] = useState(false);
|
|
116
116
|
const [reduxState, setReduxState] = useState(null);
|
|
117
|
+
// Action timeline + per-reducer last action are kept in component state so the
|
|
118
|
+
// Redux tab re-renders live on every dispatch, independent of the state tree ref.
|
|
119
|
+
const [reduxActionHistory, setReduxActionHistory] = useState([]);
|
|
120
|
+
const [reduxLastActionMap, setReduxLastActionMap] = useState({});
|
|
121
|
+
// Inspector panel height as a percentage of the screen (configurable in Settings).
|
|
122
|
+
const [modalHeightPercent, setModalHeightPercent] = useState(90);
|
|
117
123
|
const [expandedReducers, setExpandedReducers] = useState({});
|
|
118
124
|
const [logs, setLogs] = useState([]);
|
|
119
125
|
const [visible, setVisible] = useState(false);
|
|
@@ -480,8 +486,14 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
480
486
|
}, 200);
|
|
481
487
|
});
|
|
482
488
|
setReduxState(getReduxState());
|
|
489
|
+
setReduxActionHistory([...getActionHistory()]);
|
|
490
|
+
setReduxLastActionMap({ ...getLastActionForReducer() });
|
|
483
491
|
const unsubscribeRedux = subscribeReduxState(() => {
|
|
492
|
+
// New references each time guarantee the Redux tab updates live, even when
|
|
493
|
+
// the root state object reference is unchanged or auto-refresh is paused.
|
|
484
494
|
setReduxState(getReduxState());
|
|
495
|
+
setReduxActionHistory([...getActionHistory()]);
|
|
496
|
+
setReduxLastActionMap({ ...getLastActionForReducer() });
|
|
485
497
|
});
|
|
486
498
|
return () => {
|
|
487
499
|
unsubscribe();
|
|
@@ -995,7 +1007,7 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
995
1007
|
fontSize: 10.5,
|
|
996
1008
|
color: '#FFFFFF',
|
|
997
1009
|
}}>
|
|
998
|
-
|
|
1010
|
+
v{LIB_VERSION}
|
|
999
1011
|
</Text>
|
|
1000
1012
|
</View>
|
|
1001
1013
|
</View>
|
|
@@ -1163,24 +1175,50 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
1163
1175
|
width: 38,
|
|
1164
1176
|
height: 22,
|
|
1165
1177
|
borderRadius: 11,
|
|
1166
|
-
backgroundColor:
|
|
1167
|
-
? AppColors.
|
|
1168
|
-
:
|
|
1178
|
+
backgroundColor: isLocked
|
|
1179
|
+
? AppColors.grayBackground
|
|
1180
|
+
: isVisible
|
|
1181
|
+
? AppColors.purple
|
|
1182
|
+
: AppColors.grayBorderSecondary,
|
|
1183
|
+
borderWidth: isLocked ? 1.5 : 0,
|
|
1184
|
+
borderColor: isLocked
|
|
1185
|
+
? AppColors.grayBorderSecondary
|
|
1186
|
+
: 'transparent',
|
|
1187
|
+
borderStyle: isLocked ? 'dashed' : 'solid',
|
|
1169
1188
|
padding: 2,
|
|
1170
1189
|
justifyContent: 'center',
|
|
1171
1190
|
alignItems: isVisible ? 'flex-end' : 'flex-start',
|
|
1191
|
+
opacity: isLocked ? 0.9 : 1,
|
|
1172
1192
|
}}>
|
|
1173
1193
|
<View style={{
|
|
1174
1194
|
width: 18,
|
|
1175
1195
|
height: 18,
|
|
1176
1196
|
borderRadius: 9,
|
|
1177
|
-
backgroundColor:
|
|
1197
|
+
backgroundColor: isLocked
|
|
1198
|
+
? AppColors.grayBorderSecondary
|
|
1199
|
+
: '#FFFFFF',
|
|
1200
|
+
alignItems: 'center',
|
|
1201
|
+
justifyContent: 'center',
|
|
1178
1202
|
shadowColor: '#000',
|
|
1179
|
-
shadowOpacity: 0.15,
|
|
1203
|
+
shadowOpacity: isLocked ? 0 : 0.15,
|
|
1180
1204
|
shadowRadius: 1.5,
|
|
1181
1205
|
shadowOffset: { width: 0, height: 1 },
|
|
1182
|
-
}}
|
|
1206
|
+
}}>
|
|
1207
|
+
{isLocked && (<Svg width={10} height={10} viewBox="0 0 24 24" fill="none">
|
|
1208
|
+
<Path d="M7 10V7a5 5 0 0 1 10 0v3" stroke={AppColors.grayText} strokeWidth="2.2" strokeLinecap="round"/>
|
|
1209
|
+
<Path d="M5 10h14v9a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1z" fill={AppColors.grayText}/>
|
|
1210
|
+
</Svg>)}
|
|
1211
|
+
</View>
|
|
1183
1212
|
</TouchableScale>
|
|
1213
|
+
{isLocked && (<Text style={{
|
|
1214
|
+
fontFamily: AppFonts.interBold,
|
|
1215
|
+
fontSize: 8,
|
|
1216
|
+
color: AppColors.grayTextWeak,
|
|
1217
|
+
letterSpacing: 0.4,
|
|
1218
|
+
marginTop: 3,
|
|
1219
|
+
}}>
|
|
1220
|
+
REQUIRED
|
|
1221
|
+
</Text>)}
|
|
1184
1222
|
</View>
|
|
1185
1223
|
</View>);
|
|
1186
1224
|
})}
|
|
@@ -1269,6 +1307,86 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
1269
1307
|
}}/>
|
|
1270
1308
|
</TouchableScale>
|
|
1271
1309
|
</View>
|
|
1310
|
+
|
|
1311
|
+
{/* Divider */}
|
|
1312
|
+
<View style={{
|
|
1313
|
+
height: 1,
|
|
1314
|
+
backgroundColor: AppColors.dividerColor,
|
|
1315
|
+
}}/>
|
|
1316
|
+
|
|
1317
|
+
{/* Modal Height */}
|
|
1318
|
+
<View style={{
|
|
1319
|
+
paddingVertical: 12,
|
|
1320
|
+
paddingHorizontal: 14,
|
|
1321
|
+
}}>
|
|
1322
|
+
<View style={{
|
|
1323
|
+
flexDirection: 'row',
|
|
1324
|
+
alignItems: 'center',
|
|
1325
|
+
gap: 8,
|
|
1326
|
+
}}>
|
|
1327
|
+
<View style={{
|
|
1328
|
+
width: 20,
|
|
1329
|
+
height: 20,
|
|
1330
|
+
borderRadius: 6,
|
|
1331
|
+
backgroundColor: AppColors.purpleShade50,
|
|
1332
|
+
borderWidth: 1,
|
|
1333
|
+
borderColor: 'rgba(104,75,155,0.2)',
|
|
1334
|
+
alignItems: 'center',
|
|
1335
|
+
justifyContent: 'center',
|
|
1336
|
+
}}>
|
|
1337
|
+
<ScreenIcon color={AppColors.purple} size={11}/>
|
|
1338
|
+
</View>
|
|
1339
|
+
<View style={{ flex: 1 }}>
|
|
1340
|
+
<Text style={{
|
|
1341
|
+
fontFamily: AppFonts.interBold,
|
|
1342
|
+
fontSize: 13,
|
|
1343
|
+
color: AppColors.primaryBlack,
|
|
1344
|
+
}}>
|
|
1345
|
+
Modal Height
|
|
1346
|
+
</Text>
|
|
1347
|
+
<Text style={{
|
|
1348
|
+
fontFamily: AppFonts.interRegular,
|
|
1349
|
+
fontSize: 11,
|
|
1350
|
+
color: AppColors.grayText,
|
|
1351
|
+
marginTop: 1,
|
|
1352
|
+
}}>
|
|
1353
|
+
Height of the inspector panel relative to the screen
|
|
1354
|
+
</Text>
|
|
1355
|
+
</View>
|
|
1356
|
+
</View>
|
|
1357
|
+
|
|
1358
|
+
{/* Segmented picker */}
|
|
1359
|
+
<View style={{
|
|
1360
|
+
flexDirection: 'row',
|
|
1361
|
+
backgroundColor: AppColors.grayBackground,
|
|
1362
|
+
borderRadius: 8,
|
|
1363
|
+
padding: 2.5,
|
|
1364
|
+
marginTop: 10,
|
|
1365
|
+
borderWidth: 1,
|
|
1366
|
+
borderColor: AppColors.dividerColor,
|
|
1367
|
+
}}>
|
|
1368
|
+
{[50, 70, 90, 100].map(opt => {
|
|
1369
|
+
const isActive = modalHeightPercent === opt;
|
|
1370
|
+
return (<TouchableScale key={opt} onPress={() => setModalHeightPercent(opt)} style={{
|
|
1371
|
+
flex: 1,
|
|
1372
|
+
paddingVertical: 6,
|
|
1373
|
+
alignItems: 'center',
|
|
1374
|
+
borderRadius: 6,
|
|
1375
|
+
backgroundColor: isActive
|
|
1376
|
+
? AppColors.purple
|
|
1377
|
+
: 'transparent',
|
|
1378
|
+
}}>
|
|
1379
|
+
<Text style={{
|
|
1380
|
+
fontFamily: AppFonts.interBold,
|
|
1381
|
+
fontSize: 11,
|
|
1382
|
+
color: isActive ? '#FFFFFF' : AppColors.grayText,
|
|
1383
|
+
}}>
|
|
1384
|
+
{opt}%
|
|
1385
|
+
</Text>
|
|
1386
|
+
</TouchableScale>);
|
|
1387
|
+
})}
|
|
1388
|
+
</View>
|
|
1389
|
+
</View>
|
|
1272
1390
|
</View>
|
|
1273
1391
|
</View>
|
|
1274
1392
|
</ScrollView>
|
|
@@ -1403,11 +1521,13 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
1403
1521
|
fontSize: 11,
|
|
1404
1522
|
color: isActive ? '#FFFFFF' : AppColors.grayText,
|
|
1405
1523
|
}}>
|
|
1406
|
-
{
|
|
1407
|
-
opt
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1524
|
+
{opts.picker.formatLabel
|
|
1525
|
+
? opts.picker.formatLabel(opt)
|
|
1526
|
+
: typeof opt === 'number' &&
|
|
1527
|
+
opt >= 500 &&
|
|
1528
|
+
settingsPage === 'insights'
|
|
1529
|
+
? `${opt}ms`
|
|
1530
|
+
: opt}
|
|
1411
1531
|
</Text>
|
|
1412
1532
|
</TouchableScale>);
|
|
1413
1533
|
})}
|
|
@@ -1872,7 +1992,187 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
1872
1992
|
e.name === 'page_view' ||
|
|
1873
1993
|
e.name === 'firebase_screen_class').length;
|
|
1874
1994
|
const webviewTotal = webViewNavHistory.length;
|
|
1995
|
+
// --- Richer insights metrics ---
|
|
1996
|
+
const slowestTime = durations.length > 0 ? Math.max(...durations) : null;
|
|
1997
|
+
const fastestTime = durations.length > 0 ? Math.min(...durations) : null;
|
|
1998
|
+
const slowCount = durations.filter(d => d >= slowRequestThreshold).length;
|
|
1999
|
+
const status2xx = logs.filter(l => l.status != null && l.status >= 200 && l.status < 300).length;
|
|
2000
|
+
const status3xx = logs.filter(l => l.status != null && l.status >= 300 && l.status < 400).length;
|
|
2001
|
+
const status4xx = logs.filter(l => l.status != null && l.status >= 400 && l.status < 500).length;
|
|
2002
|
+
const status5xx = logs.filter(l => l.status != null && l.status >= 500).length;
|
|
2003
|
+
const totalSignals = apiTotal + logTotal + analyticsTotal + webviewTotal;
|
|
2004
|
+
const totalIssues = apiErrors + logErrors;
|
|
2005
|
+
const activeModules = [
|
|
2006
|
+
tabVisibility.apis,
|
|
2007
|
+
tabVisibility.logs,
|
|
2008
|
+
tabVisibility.analytics,
|
|
2009
|
+
tabVisibility.webview,
|
|
2010
|
+
tabVisibility.redux,
|
|
2011
|
+
].filter(Boolean).length;
|
|
2012
|
+
// Composite health score: success rate penalised by error volume and slow requests.
|
|
2013
|
+
const healthScore = totalSignals === 0
|
|
2014
|
+
? 100
|
|
2015
|
+
: Math.max(0, Math.min(100, Math.round(apiSuccessRate -
|
|
2016
|
+
(logErrors > 0 ? Math.min(15, logErrors * 3) : 0) -
|
|
2017
|
+
(slowCount > 0 ? Math.min(10, slowCount * 2) : 0))));
|
|
2018
|
+
const healthColor = healthScore >= 90
|
|
2019
|
+
? AppColors.greenColor
|
|
2020
|
+
: healthScore >= 70
|
|
2021
|
+
? AppColors.warningIconGold
|
|
2022
|
+
: AppColors.errorColor;
|
|
2023
|
+
const healthLabel = healthScore >= 90
|
|
2024
|
+
? 'Healthy'
|
|
2025
|
+
: healthScore >= 70
|
|
2026
|
+
? 'Needs attention'
|
|
2027
|
+
: 'Degraded';
|
|
1875
2028
|
return (<View style={styles.dashboardContainer}>
|
|
2029
|
+
{/* Overview hero card */}
|
|
2030
|
+
<View style={{
|
|
2031
|
+
backgroundColor: AppColors.primaryLight,
|
|
2032
|
+
borderRadius: 14,
|
|
2033
|
+
borderWidth: 1,
|
|
2034
|
+
borderColor: AppColors.grayBorderSecondary,
|
|
2035
|
+
padding: 16,
|
|
2036
|
+
marginBottom: 12,
|
|
2037
|
+
}}>
|
|
2038
|
+
<View style={{
|
|
2039
|
+
flexDirection: 'row',
|
|
2040
|
+
alignItems: 'center',
|
|
2041
|
+
gap: 14,
|
|
2042
|
+
}}>
|
|
2043
|
+
{/* Health ring stand-in */}
|
|
2044
|
+
<View style={{
|
|
2045
|
+
width: 64,
|
|
2046
|
+
height: 64,
|
|
2047
|
+
borderRadius: 32,
|
|
2048
|
+
borderWidth: 4,
|
|
2049
|
+
borderColor: healthColor,
|
|
2050
|
+
alignItems: 'center',
|
|
2051
|
+
justifyContent: 'center',
|
|
2052
|
+
backgroundColor: AppColors.purpleShade50,
|
|
2053
|
+
}}>
|
|
2054
|
+
<Text style={{
|
|
2055
|
+
fontFamily: AppFonts.interBold,
|
|
2056
|
+
fontSize: 18,
|
|
2057
|
+
color: healthColor,
|
|
2058
|
+
}}>
|
|
2059
|
+
{healthScore}
|
|
2060
|
+
</Text>
|
|
2061
|
+
<Text style={{
|
|
2062
|
+
fontFamily: AppFonts.interMedium,
|
|
2063
|
+
fontSize: 7.5,
|
|
2064
|
+
color: AppColors.grayTextWeak,
|
|
2065
|
+
letterSpacing: 0.4,
|
|
2066
|
+
}}>
|
|
2067
|
+
HEALTH
|
|
2068
|
+
</Text>
|
|
2069
|
+
</View>
|
|
2070
|
+
<View style={{ flex: 1 }}>
|
|
2071
|
+
<Text style={{
|
|
2072
|
+
fontFamily: AppFonts.interBold,
|
|
2073
|
+
fontSize: 15,
|
|
2074
|
+
color: AppColors.primaryBlack,
|
|
2075
|
+
}}>
|
|
2076
|
+
Session Overview
|
|
2077
|
+
</Text>
|
|
2078
|
+
<View style={{
|
|
2079
|
+
flexDirection: 'row',
|
|
2080
|
+
alignItems: 'center',
|
|
2081
|
+
gap: 6,
|
|
2082
|
+
marginTop: 3,
|
|
2083
|
+
}}>
|
|
2084
|
+
<View style={{
|
|
2085
|
+
width: 7,
|
|
2086
|
+
height: 7,
|
|
2087
|
+
borderRadius: 3.5,
|
|
2088
|
+
backgroundColor: healthColor,
|
|
2089
|
+
}}/>
|
|
2090
|
+
<Text style={{
|
|
2091
|
+
fontFamily: AppFonts.interMedium,
|
|
2092
|
+
fontSize: 11.5,
|
|
2093
|
+
color: healthColor,
|
|
2094
|
+
}}>
|
|
2095
|
+
{healthLabel}
|
|
2096
|
+
</Text>
|
|
2097
|
+
<Text style={{
|
|
2098
|
+
fontFamily: AppFonts.interRegular,
|
|
2099
|
+
fontSize: 11.5,
|
|
2100
|
+
color: AppColors.grayTextWeak,
|
|
2101
|
+
}}>
|
|
2102
|
+
• {activeModules} modules active
|
|
2103
|
+
</Text>
|
|
2104
|
+
</View>
|
|
2105
|
+
</View>
|
|
2106
|
+
</View>
|
|
2107
|
+
|
|
2108
|
+
{/* Quick totals strip */}
|
|
2109
|
+
<View style={{
|
|
2110
|
+
flexDirection: 'row',
|
|
2111
|
+
marginTop: 14,
|
|
2112
|
+
borderTopWidth: 1,
|
|
2113
|
+
borderTopColor: AppColors.dividerColor,
|
|
2114
|
+
paddingTop: 12,
|
|
2115
|
+
}}>
|
|
2116
|
+
<View style={{ flex: 1, alignItems: 'center' }}>
|
|
2117
|
+
<Text style={{
|
|
2118
|
+
fontFamily: AppFonts.interBold,
|
|
2119
|
+
fontSize: 16,
|
|
2120
|
+
color: AppColors.primaryBlack,
|
|
2121
|
+
}}>
|
|
2122
|
+
{totalSignals}
|
|
2123
|
+
</Text>
|
|
2124
|
+
<Text style={{
|
|
2125
|
+
fontFamily: AppFonts.interRegular,
|
|
2126
|
+
fontSize: 10,
|
|
2127
|
+
color: AppColors.grayTextWeak,
|
|
2128
|
+
marginTop: 1,
|
|
2129
|
+
}}>
|
|
2130
|
+
Signals
|
|
2131
|
+
</Text>
|
|
2132
|
+
</View>
|
|
2133
|
+
<View style={{ width: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
2134
|
+
<View style={{ flex: 1, alignItems: 'center' }}>
|
|
2135
|
+
<Text style={{
|
|
2136
|
+
fontFamily: AppFonts.interBold,
|
|
2137
|
+
fontSize: 16,
|
|
2138
|
+
color: totalIssues > 0
|
|
2139
|
+
? AppColors.errorColor
|
|
2140
|
+
: AppColors.primaryBlack,
|
|
2141
|
+
}}>
|
|
2142
|
+
{totalIssues}
|
|
2143
|
+
</Text>
|
|
2144
|
+
<Text style={{
|
|
2145
|
+
fontFamily: AppFonts.interRegular,
|
|
2146
|
+
fontSize: 10,
|
|
2147
|
+
color: AppColors.grayTextWeak,
|
|
2148
|
+
marginTop: 1,
|
|
2149
|
+
}}>
|
|
2150
|
+
Issues
|
|
2151
|
+
</Text>
|
|
2152
|
+
</View>
|
|
2153
|
+
<View style={{ width: 1, backgroundColor: AppColors.dividerColor }}/>
|
|
2154
|
+
<View style={{ flex: 1, alignItems: 'center' }}>
|
|
2155
|
+
<Text style={{
|
|
2156
|
+
fontFamily: AppFonts.interBold,
|
|
2157
|
+
fontSize: 16,
|
|
2158
|
+
color: slowCount > 0
|
|
2159
|
+
? AppColors.warningIconGold
|
|
2160
|
+
: AppColors.primaryBlack,
|
|
2161
|
+
}}>
|
|
2162
|
+
{slowCount}
|
|
2163
|
+
</Text>
|
|
2164
|
+
<Text style={{
|
|
2165
|
+
fontFamily: AppFonts.interRegular,
|
|
2166
|
+
fontSize: 10,
|
|
2167
|
+
color: AppColors.grayTextWeak,
|
|
2168
|
+
marginTop: 1,
|
|
2169
|
+
}}>
|
|
2170
|
+
Slow ({slowRequestThreshold}ms+)
|
|
2171
|
+
</Text>
|
|
2172
|
+
</View>
|
|
2173
|
+
</View>
|
|
2174
|
+
</View>
|
|
2175
|
+
|
|
1876
2176
|
{/* Module 1: APIs */}
|
|
1877
2177
|
{tabVisibility.apis && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('apis')}>
|
|
1878
2178
|
<View style={styles.dashboardModuleHeader}>
|
|
@@ -1912,9 +2212,75 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
1912
2212
|
<Text style={styles.dashboardGridLbl}>Avg Latency</Text>
|
|
1913
2213
|
</View>
|
|
1914
2214
|
</View>
|
|
1915
|
-
</TouchableScale>)}
|
|
1916
2215
|
|
|
1917
|
-
|
|
2216
|
+
{/* Status-class breakdown + latency range */}
|
|
2217
|
+
<View style={{
|
|
2218
|
+
marginTop: 10,
|
|
2219
|
+
paddingTop: 10,
|
|
2220
|
+
borderTopWidth: 1,
|
|
2221
|
+
borderTopColor: AppColors.dividerColor,
|
|
2222
|
+
flexDirection: 'row',
|
|
2223
|
+
alignItems: 'center',
|
|
2224
|
+
flexWrap: 'wrap',
|
|
2225
|
+
gap: 6,
|
|
2226
|
+
}}>
|
|
2227
|
+
{[
|
|
2228
|
+
{ label: '2xx', value: status2xx, color: AppColors.greenColor },
|
|
2229
|
+
{ label: '3xx', value: status3xx, color: AppColors.skyBlue },
|
|
2230
|
+
{
|
|
2231
|
+
label: '4xx',
|
|
2232
|
+
value: status4xx,
|
|
2233
|
+
color: AppColors.warningIconGold,
|
|
2234
|
+
},
|
|
2235
|
+
{ label: '5xx', value: status5xx, color: AppColors.errorColor },
|
|
2236
|
+
].map(s => (<View key={s.label} style={{
|
|
2237
|
+
flexDirection: 'row',
|
|
2238
|
+
alignItems: 'center',
|
|
2239
|
+
gap: 4,
|
|
2240
|
+
backgroundColor: AppColors.grayBackground,
|
|
2241
|
+
borderRadius: 6,
|
|
2242
|
+
borderWidth: 1,
|
|
2243
|
+
borderColor: AppColors.dividerColor,
|
|
2244
|
+
paddingHorizontal: 7,
|
|
2245
|
+
paddingVertical: 3,
|
|
2246
|
+
}}>
|
|
2247
|
+
<View style={{
|
|
2248
|
+
width: 6,
|
|
2249
|
+
height: 6,
|
|
2250
|
+
borderRadius: 3,
|
|
2251
|
+
backgroundColor: s.color,
|
|
2252
|
+
}}/>
|
|
2253
|
+
<Text style={{
|
|
2254
|
+
fontFamily: AppFonts.interBold,
|
|
2255
|
+
fontSize: 10,
|
|
2256
|
+
color: AppColors.grayTextStrong,
|
|
2257
|
+
}}>
|
|
2258
|
+
{s.label} {s.value}
|
|
2259
|
+
</Text>
|
|
2260
|
+
</View>))}
|
|
2261
|
+
{slowestTime != null && (<View style={{
|
|
2262
|
+
marginLeft: 'auto',
|
|
2263
|
+
flexDirection: 'row',
|
|
2264
|
+
alignItems: 'center',
|
|
2265
|
+
gap: 4,
|
|
2266
|
+
}}>
|
|
2267
|
+
<Text style={{
|
|
2268
|
+
fontFamily: AppFonts.interRegular,
|
|
2269
|
+
fontSize: 10,
|
|
2270
|
+
color: AppColors.grayTextWeak,
|
|
2271
|
+
}}>
|
|
2272
|
+
Range
|
|
2273
|
+
</Text>
|
|
2274
|
+
<Text style={{
|
|
2275
|
+
fontFamily: AppFonts.interBold,
|
|
2276
|
+
fontSize: 10,
|
|
2277
|
+
color: AppColors.grayTextStrong,
|
|
2278
|
+
}}>
|
|
2279
|
+
{fastestTime}–{slowestTime}ms
|
|
2280
|
+
</Text>
|
|
2281
|
+
</View>)}
|
|
2282
|
+
</View>
|
|
2283
|
+
</TouchableScale>)}
|
|
1918
2284
|
{tabVisibility.logs && (<TouchableScale style={styles.dashboardModuleCard} onPress={() => switchActiveTab('logs')}>
|
|
1919
2285
|
<View style={styles.dashboardModuleHeader}>
|
|
1920
2286
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
@@ -2118,9 +2484,10 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
2118
2484
|
<Text style={styles.emptySub}>Connected store state is empty.</Text>
|
|
2119
2485
|
</View>);
|
|
2120
2486
|
}
|
|
2121
|
-
// Build hierarchical tree: Store -> Reducers -> Action -> Data
|
|
2122
|
-
|
|
2123
|
-
const
|
|
2487
|
+
// Build hierarchical tree: Store -> Reducers -> Action -> Data.
|
|
2488
|
+
// These come from component state (refreshed on every dispatch) so the view stays live.
|
|
2489
|
+
const lastActionMap = reduxLastActionMap;
|
|
2490
|
+
const actionHistory = reduxActionHistory;
|
|
2124
2491
|
return (<ScrollView style={styles.detailScroll} contentContainerStyle={{ paddingBottom: 24 }}>
|
|
2125
2492
|
{/* Top Summary Card */}
|
|
2126
2493
|
<View style={{
|
|
@@ -2190,15 +2557,25 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
2190
2557
|
? AppColors.purple
|
|
2191
2558
|
: 'transparent',
|
|
2192
2559
|
}}>
|
|
2193
|
-
<
|
|
2560
|
+
<View style={{
|
|
2561
|
+
flexDirection: 'row',
|
|
2562
|
+
alignItems: 'center',
|
|
2563
|
+
justifyContent: 'center',
|
|
2564
|
+
gap: 6,
|
|
2565
|
+
}}>
|
|
2566
|
+
<ReduxTimelineIcon color={reduxActiveSubTab === 'timeline'
|
|
2567
|
+
? '#FFFFFF'
|
|
2568
|
+
: AppColors.grayText} size={13}/>
|
|
2569
|
+
<Text style={{
|
|
2194
2570
|
fontFamily: AppFonts.interBold,
|
|
2195
2571
|
fontSize: 11,
|
|
2196
2572
|
color: reduxActiveSubTab === 'timeline'
|
|
2197
2573
|
? '#FFFFFF'
|
|
2198
2574
|
: AppColors.grayText,
|
|
2199
2575
|
}}>
|
|
2200
|
-
|
|
2201
|
-
|
|
2576
|
+
Action Timeline
|
|
2577
|
+
</Text>
|
|
2578
|
+
</View>
|
|
2202
2579
|
</TouchableOpacity>
|
|
2203
2580
|
<TouchableOpacity onPress={() => {
|
|
2204
2581
|
animateNextLayout();
|
|
@@ -2211,13 +2588,23 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
2211
2588
|
borderRadius: 8,
|
|
2212
2589
|
backgroundColor: reduxActiveSubTab === 'tree' ? AppColors.purple : 'transparent',
|
|
2213
2590
|
}}>
|
|
2214
|
-
<
|
|
2591
|
+
<View style={{
|
|
2592
|
+
flexDirection: 'row',
|
|
2593
|
+
alignItems: 'center',
|
|
2594
|
+
justifyContent: 'center',
|
|
2595
|
+
gap: 6,
|
|
2596
|
+
}}>
|
|
2597
|
+
<ReduxTreeIcon color={reduxActiveSubTab === 'tree' ? '#FFFFFF' : AppColors.grayText} size={13}/>
|
|
2598
|
+
<Text style={{
|
|
2215
2599
|
fontFamily: AppFonts.interBold,
|
|
2216
2600
|
fontSize: 11,
|
|
2217
|
-
color: reduxActiveSubTab === 'tree'
|
|
2601
|
+
color: reduxActiveSubTab === 'tree'
|
|
2602
|
+
? '#FFFFFF'
|
|
2603
|
+
: AppColors.grayText,
|
|
2218
2604
|
}}>
|
|
2219
|
-
|
|
2220
|
-
|
|
2605
|
+
Store Tree
|
|
2606
|
+
</Text>
|
|
2607
|
+
</View>
|
|
2221
2608
|
</TouchableOpacity>
|
|
2222
2609
|
</View>
|
|
2223
2610
|
|
|
@@ -2283,7 +2670,10 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
2283
2670
|
{visible && (<ErrorBoundary onClose={closeModal}>
|
|
2284
2671
|
<View style={styles.modalBackdrop}>
|
|
2285
2672
|
<Pressable style={styles.modalBackdropPressable} onPress={closeModal}/>
|
|
2286
|
-
<View style={
|
|
2673
|
+
<View style={[
|
|
2674
|
+
styles.modalContentCard,
|
|
2675
|
+
{ height: `${modalHeightPercent}%` },
|
|
2676
|
+
]}>
|
|
2287
2677
|
<StatusBar translucent backgroundColor="transparent" barStyle="light-content"/>
|
|
2288
2678
|
|
|
2289
2679
|
<LinearGradient colors={[AppColors.purple, '#6B4EFF']} style={styles.headerGradient}>
|
|
@@ -2343,25 +2733,83 @@ const NetworkInspector = ({ enabled = true, }) => {
|
|
|
2343
2733
|
<View style={{
|
|
2344
2734
|
flexDirection: 'row',
|
|
2345
2735
|
alignItems: 'center',
|
|
2346
|
-
gap:
|
|
2736
|
+
gap: 6,
|
|
2347
2737
|
}}>
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2738
|
+
{/* OS chip */}
|
|
2739
|
+
<View style={{
|
|
2740
|
+
flexDirection: 'row',
|
|
2741
|
+
alignItems: 'center',
|
|
2742
|
+
borderRadius: 6,
|
|
2743
|
+
overflow: 'hidden',
|
|
2744
|
+
borderWidth: 1,
|
|
2745
|
+
borderColor: 'rgba(255,255,255,0.18)',
|
|
2746
|
+
}}>
|
|
2747
|
+
<View style={{
|
|
2748
|
+
paddingHorizontal: 5,
|
|
2749
|
+
paddingVertical: 2,
|
|
2750
|
+
backgroundColor: 'rgba(255,255,255,0.28)',
|
|
2751
|
+
}}>
|
|
2752
|
+
<Text style={{
|
|
2753
|
+
fontFamily: AppFonts.interBold,
|
|
2754
|
+
fontSize: 9,
|
|
2755
|
+
color: '#FFFFFF',
|
|
2756
|
+
letterSpacing: 0.3,
|
|
2757
|
+
}}>
|
|
2758
|
+
{Platform.OS === 'ios' ? 'iOS' : 'Android'}
|
|
2759
|
+
</Text>
|
|
2760
|
+
</View>
|
|
2761
|
+
<View style={{
|
|
2762
|
+
paddingHorizontal: 5,
|
|
2763
|
+
paddingVertical: 2,
|
|
2764
|
+
backgroundColor: 'rgba(255,255,255,0.12)',
|
|
2765
|
+
}}>
|
|
2766
|
+
<Text style={{
|
|
2356
2767
|
fontFamily: AppFonts.interMedium,
|
|
2357
|
-
fontSize:
|
|
2358
|
-
color: 'rgba(255,255,255,0.
|
|
2768
|
+
fontSize: 9.5,
|
|
2769
|
+
color: 'rgba(255,255,255,0.92)',
|
|
2770
|
+
}}>
|
|
2771
|
+
{String(Platform.Version)}
|
|
2772
|
+
</Text>
|
|
2773
|
+
</View>
|
|
2774
|
+
</View>
|
|
2775
|
+
|
|
2776
|
+
{/* npm chip */}
|
|
2777
|
+
<View style={{
|
|
2778
|
+
flexDirection: 'row',
|
|
2779
|
+
alignItems: 'center',
|
|
2780
|
+
borderRadius: 6,
|
|
2781
|
+
overflow: 'hidden',
|
|
2782
|
+
borderWidth: 1,
|
|
2783
|
+
borderColor: 'rgba(255,255,255,0.18)',
|
|
2784
|
+
}}>
|
|
2785
|
+
<View style={{
|
|
2786
|
+
paddingHorizontal: 5,
|
|
2787
|
+
paddingVertical: 2,
|
|
2788
|
+
backgroundColor: 'rgba(255,255,255,0.28)',
|
|
2789
|
+
}}>
|
|
2790
|
+
<Text style={{
|
|
2791
|
+
fontFamily: AppFonts.interBold,
|
|
2792
|
+
fontSize: 9,
|
|
2793
|
+
color: '#FFFFFF',
|
|
2359
2794
|
letterSpacing: 0.3,
|
|
2360
2795
|
}}>
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2796
|
+
npm
|
|
2797
|
+
</Text>
|
|
2798
|
+
</View>
|
|
2799
|
+
<View style={{
|
|
2800
|
+
paddingHorizontal: 5,
|
|
2801
|
+
paddingVertical: 2,
|
|
2802
|
+
backgroundColor: 'rgba(255,255,255,0.12)',
|
|
2803
|
+
}}>
|
|
2804
|
+
<Text style={{
|
|
2805
|
+
fontFamily: AppFonts.interMedium,
|
|
2806
|
+
fontSize: 9.5,
|
|
2807
|
+
color: 'rgba(255,255,255,0.92)',
|
|
2808
|
+
}}>
|
|
2809
|
+
v{LIB_VERSION}
|
|
2810
|
+
</Text>
|
|
2811
|
+
</View>
|
|
2812
|
+
</View>
|
|
2365
2813
|
</View>
|
|
2366
2814
|
</View>
|
|
2367
2815
|
</View>) : null}
|